A cfengine configuration file for a large network can become long and complex so, before we get down to details, let's try to strip away the complexity and look only to the essentials.
Each cfengine program or configuration file is a list of declarations of items to be checked and perhaps fixed. You begin by creating a file called cfengine.conf. The simplest meaningful file you can create is something like this:
# Comment... control: actionsequence = ( links ) links: /bin -> /usr/bin
The example above checks and makes (if necessary) a link from /bin to /usr/bin. Let's examine this example more closely. In a cfengine program:
=(
list )
are
used to assign the value on the right hand side to the name on the left hand side
of the equals sign.
In simple example above has three of the four types of object described
above. The control:
section of any program tells cfengine how to
behave. In this example it adds the action links to the
actionsequence. For links you could replace some other action.
The essential point is that, if you don't have an action sequence, your
cfengine program will do absolutely nothing! The action sequence is a
list which tells cfengine what do to and in which order.
The links:
section of the file tells cfengine that what follows
is a number of links to be made. If you write this part of the file,
but forget to add links to the actionsequence, then nothing will be
done! You can add any number of links in this part of the file and they
will all be dealt with in order when—and only when—you write
links in the action sequence.
To summarize, you must have:
Now let's think a bit about how useful this short example program is. On a SunOS system, where the directory /bin is in fact supposed to be a link, such a check could be useful, but on some other system where /bin is a not a link but a separate directory, this would result in an error message from cfengine, telling you that /bin exists and is not a link. The lesson is that, if we want to use cfengine to make one single program which can be run on any host of any type, then we need some way of restricting the above link so that it only gets checked on SunOS systems. We can write the following:
# Comment... control: actionsequence = ( links ) links: sun4:: /bin -> /usr/bin # other links osf:: # other links
The names which have double colons after them are called classes
and they are used to restrict a particular action so that it only gets
performed if the host running the program is a member of that class. If
you are familiar with C++, this syntax should make you think of classes
definitions in C++. Classes works like this: the names above
sun4
, sun3
, osf
etc. are all internally defined by
cfengine. If a host running, say, the OSF operating system executes the
file it automatically becomes a member of the class osf
. Since
it cannot be a member more than one of the above, this distinguishes
between different types of operating system and creates a hidden
if
..then
...else
test.
This is the way in which cfengine makes decisions. The key idea is that actions are only carried out if they are in the same class as the host running the program. Classes are dealt with in detail in the next chapter.
Now let's see how to add another kind of action to the action sequence.
# Comment... control: actionsequence = ( tidy links ) links: /bin -> /usr/bin tidy: /tmp pattern=* age=7 recurse=inf
We have now added a new kind of declaration called tidy:
which
deletes files. In the example above, we are looking at files in the
directory /tmp which match the pattern * and have not been
accessed for more than seven days. The search for these files descends
recursively down any number of subdirectories.
To make any of this happen we must add the word tidy to the action
sequence. If we don't, the declaration will be ignored. Notice also
that, regardless of the fact that links:
comes before
tidy:
, the order in the action sequence tells us that all
tidy
actions will be performed before links:
.
The above structure can be repeated to build up a configuration file or script.