Cfengine configuration directory

User defined methods

Relevant classes: any

Sometimes we want to create a module using convergent cfengine behaviour that can be reused and can accept and return data in cfengine format (with classes and variables). For example, we might want to create a package installation scheme based in trusted source code:

The following program (that runs on cfagent 2.1.0 or later) installs its first argument in the prefixed location given by the second argument. It collects the tar file, unpacks it, configures and compiles it, then tidies its files.

####################################################
#
# This is a cfengine file that calls a method.
# It should be in the usual place for cfinputs
#
####################################################
 
control:

   actionsequence = ( methods )

#####################################################

methods:

   InstallTar(cfengine-2.1.0b7,/local/gnu)

      action=cf.install
      returnvars=null
      returnclasses=null
      server=localhost

We must install the method in the trusted modules directory (normally /var/cfengine/modules or WORKDIR/modules).
####################################################
#
# This is an example method file, that needs to be
# in the module directory /var/cfengine/modules
# since this is the trusted directory
#
# e.g. InstallFromTar(cfengine-2.1.0,/usr/local/gnu)
#
####################################################

control:


 MethodName       = ( InstallTar )
 MethodParameters = ( filename gnuprefix )
 
 path = ( /usr/local/gnu/bin )


 TrustedWorkDir = ( /tmp )

 TrustedSources = ( /iu/nexus/ud/mark/tmp )
 TrustedSourceServer = ( localhost )

 actionsequence = ( copy editfiles shellcommands tidy )

####################################################

classes:

  Force = ( any )

####################################################

copy:

 $(TrustedSources)/$(filename).tar.gz 

    dest=$(TrustedWorkDir)/$(filename).tar.gz 
    server=$(TrustedSourceServer)

####################################################

shellcommands:

 "$(path)/tar zxf $(filename).tar.gz" 

     chdir=$(TrustedWorkDir)

 "$(TrustedWorkDir)/$(filename)/configure --prefix=$(gnuprefix)" 

    chdir=$(TrustedWorkDir)/$(filename)
    define=okay

 okay::

 "$(path)/make" 

     chdir=$(TrustedWorkDir)/$(filename)

####################################################

tidy:

  $(TrustedWorkDir) pattern=$(filename) r=inf rmdirs=true age=0


####################################################

#editfiles:
#
#{ $(TrustedWorkDir)/$(filename)/configure-opts
#
#AppendIfNoSuchLine "Something ???"
#}

####################################################

alerts:

 Force::

  ReturnVariables(none)
  ReturnClasses(success)

More examples

Consider the cfengine example;
cfagent -f ./cftest -v
Where the script being called is defined below.

####################################################
#
# cftest
#
# This is a cfengine file that calls a method.
# It should be in the usual place for cfinputs
#
####################################################
 
control:

   actionsequence = ( methods )

   parent1 = ( "Send a variable..." )

   AddInstallable = ( GetEnvironmentAnalysis_class1  )


######################################################

alerts:

  # Note that the return variables are prefixed with the method space

     "Help!! Danger will robinson"

  GetEnvironmentAnalysis_class1::

     "Method got returnval : $(GetEnvironmentAnalysis.a)"

  any::

     "Finished with alerts"

###########################################################################

methods:

    # Known bug .. can't have functions and spaces in same method call
    # No point in fixing this until the language is decided fully..

    GetEnvironmentAnalysis("${parent1}",param2,ReadFile("/etc/passwd",300))

    action=cf.methodtest                  # This is the nae of the method that is in modulesdir

    returnvars=a,b,c,d                    # The variables that we get back should be called these names
                                          # with method name prefix

    returnclasses=class1,define2,class2   # This is an access list for returned classes. Classes will
                                          # only be handed back if they are included here

    server=localhost                      # The host(s) that should execute the method

#    owner=25                             # Special info for executing the method. 
#    group=root                           # Only the localhost can decide this - not a remote caller
#    chdir=/var/cfengine
#    chroot=/tmp



Within the above program, a method is called (see code below). And the file that gets called:

####################################################
#
# This is an example method file, that needs to be
# in the module directory /var/cfengine/modules
# since this is the trusted directory
#
####################################################

control:

 # Identify this file as a method

 MethodName       = ( GetEnvironmentAnalysis )

 # Where to put the formal parameters (rename values or save to file)

 MethodParameters = ( value1 value2 /tmp/file1 )
 
 # value1 is passed to this program, so lets add to it and send the result back

 var1 = ( "${value1}...and get it back" )
 var2 = ( "Method returns ${value2}" )
 var3 = ( "Method returns ${value3}" )

 actionsequence = ( shellcommands editfiles )

####################################################

classes:

 class1 = ( any )

####################################################

shellcommands:

 "/bin/echo $(var)"

####################################################

editfiles:

{ /tmp/file1

AppendIfNoSuchLine "This used to be a file..."
}

####################################################

alerts:

  "Return variables are alerts to parent..."

  ReturnVariables("${var1}","${var2}","var3",NOthing)
  ReturnClasses(class1,class2)


Note the flow of this program.
  • Alerts are always made at the end of execution.
  • Classes defined by the method trigger new actions.
  • Classes returned are prefixed by the name of the method (with an underscore).
  • Variables returned are prefixed by the name of the method (with a dot .) indicating the private context of the variable.

Known bug/limitation

To keep the parser simple, while cfengine is still being defined grammatically, certain limitations are difficult to correct. Methods and functions in cfengine may contain quoted arguments that contain spaces, e.g.
 Function(" a b c ")
They may also contain other functions:
 Function(ReadFile(/etc/passwd),abc)
However, they cannot contain both spaces and functions in different arguments. A work around is to define a variable containing the string with spaces:
control:

 var = ( " a b c ")

methods:

 Function($var,ReadFile(/etc/passwd))

Back to documentation