Imported Classes Have Limited Scope

From Cfwiki

Jump to: navigation, search

Lots of people seem to get bit by this! The docs make do make mention of it, but it is a subtle thing and perhaps slips by without raising the bright red flag it ought to:

Note that, if you define variables in an imported file they will not be defined for operations in their parent files. This because cfengine reads in all the import files after the main file has been parsed—not at the place where you call import in your script. This means that variables or macros defined in imported files are only defined after the main program. Variables from earlier files are inherited by later includes, but not vice-versa. (From http://www.cfengine.org/docs/cfengine-Reference.html#import)

This is somewhat misleading because it talks about "variables and macros" but does not mention "groups aka classes"; however, group/class definitions are also subject to this rule. We could also say: "Classes defined in imports do not propagate upwards to the including file". An example is in order, perhaps. (Thanks to Daniel Holth for providing this)

### This example does not work! The shellcommand never gets run.
### cf.groups:
groups:
        any::
                SomeGroup = ( any )


### cfagent.conf:
#!/usr/sbin/cfagent -vKf

import:
        any::
                cf.groups

control:
        actionsequence = ( shellcommands )

shellcommands:
        SomeGroup::
                "/usr/bin/echo hello"

Instead, use something like this:


### This example works

###
# cfagent.conf
#!/usr/sbin/cfagent -vKf

import:
        any::
                cf.groups
                cf.commands

control:
        actionsequence = ( shellcommands )
###
# cf.commands
shellcommands:
        SomeGroup::
                "/bin/echo hello"
###
# cf.groups
groups:
      SomeGroup = ( any )

A rule of thumb might be: Keep your cfagent.conf stripped down to your global control: section and an import: section that pulls in the rest of the configs, with the ones containing any groups: sections first. Alternately, you could put groups: in your top-level cfagent.conf. This can get messy pretty quickly, but it is necessary if you want to use any soft classes as conditionals for control: directives.

Alternately, pre-declare all your possible 'groups:' variables with AddInstallable. The following example works as well:


import:
        any::
                cf.groups

control:
        actionsequence = ( shellcommands )
        AddInstallable = ( SomeGroup SomeGroup_1 )

shellcommands:
        SomeGroup::
                "/bin/echo hello somegroup"

        SomeGroup_1::
                "/bin/echo hello somegroup_1"
Personal tools