Previous: Feedback classes, Up: Defining classes



4.4.5 Writing plugin modules

If the regular mechanisms for setting classes do not produce the results you require for your configuration, you can write your own routines to concoct the classes of your dreams. Plugin modules are added to cfengine programs from within the actionsequence, (see Reference manual). They allow you to write special code for answering questions which are too complex to answer using the other mechanisms above. This allows you to control classes which will be switched on and the moment at which your module attempts to evaluate the condition of the system.

Modules must lie in a special directory defined by the variable moduledirectory. They must have a name of the form module:mymodule and they must follow a simple protocol. Cfengine will only execute a module which is owned either by root or the user who is running cfengine, if it lies in the special directory and has the special name. A plug-in module may be written in any language, it can return any output you like, but lines which begin with a + sign are treated as classes to be defined (like -D), while lines which begin with a - sign are treated as classes to be undefined (like -N). Lines starting with = are variables/macros to be defined. Any other lines of output are cited by cfengine, so you should normally make your module completely silent. Here is an example module written in perl. First we define the module in the cfengine program:

     
      control:
     
        moduledirectory = ( /local/cfengine/modules )
     
        actionsequence = (
                         files
                         module:myplugin.specialclass
                         "module:argplugin.specialclass arg1 arg2"
                         copy
                         )
      ...
     

Note that the class definitions for the module can also be defined in as AddInstallables, if this is more convenient. NOTE: you must declare the classes before using them in the cfengine configuration, or else those actions will be ignored. Next we write the plugin itself.

     #!/usr/bin/perl
     #
     # module:myplugin
     #
     
       # lots of computation....
     
     if (special-condition)
        {
        print "+specialclass";
        }
     

Modules inherit the environment variables from cfengine and accept arguments, just as a regular shellcommand does.

     #!/bin/sh
     #
     # module:myplugin
     #
     
     /bin/echo $*
     

Cfengine defines the classes as an environment variable so that programs have access to these. E.g. try the following module:

     #!/usr/bin/perl
     
     print "Decoding $ENV{CFALLCLASSES}\n";
     
     @allclasses = split (":","$ENV{CFALLCLASSES}");
     
     while ($c=shift(@allclasses))
       {
       $classes{$c} = 1;
       print "$c is set\n";
       }
     

Modules can define macros in cfengine by outputting strings of the form

     
     =variablename=value