Forum: Cfengine Help
Subject: Re: Questions about the reference manual
Author: zzamboni
Link to topic: https://cfengine.com/forum/read.php?3,18107,18112#msg-18112

Hi,

Promise bodies:

The body of a promise is simply the details about the promise, and it consists 
of parameter => value pairs (also known as lvalue => rvalue pairs). For 
example, the following by itself is a complete promise:

commands:
   "/bin/ls";

This will simply cause the command to be executed. However, in the body of the 
promise you can provide more details about how and when the promise will be 
checked and fixed. For example:

commands:
  "/bin/ls"
    args => "-lR /";

In this case, the body specifies the arguments that must be passed to the 
command. Each type of promise can take different arguments in the body, and 
they are all detailed in the reference manual.

Functions:

Functions are grammatical elements that allow you to specify more complex body 
parameters. lvalue and rvalue in this context mean "left-hand value" and 
"right-hand value", as in:

lvalue => rvalue;

In the example above, "args" is the lvalue and "-lR /" is the rvalue.

Coming back to functions: some body arguments need more than a single value to 
completely specify their meaning, and in this case they are modularized into 
separate functions. For example:

files:
  # Copy inputs
  "/var/cfengine/inputs"
    perms => usystem("0600", "root"),
    copy_from => umycopy("${inputs}"),
    depth_search => urecurse("inf");
...
# somewhere else in the policy
body depth_search urecurse(d)
{
  depth => "${d}";
  exclude_dirs => { "\.svn", "\.git" };
}

body perms usystem(p,o)
{
  mode => "${p}";
  owners => { "${o}" };
  groups => { "${o}" };
}

body copy_from umycopy(from)
{
  source => "${from}";
  compare => "digest";
  verify => "true";
  purge => "false";
  trustkey => "true";
}

In this example, usystem(), urecurse() and umycopy() are parameterized 
(meaning: you can pass arguments to them) bodies that allow you to specify more 
complex values for the "perms", "copy_from" and "depth_search" parameters of 
the "/var/cfengine/inputs" promise. The parameters you give to them (e.g. 
"0600" and "root" in the case of usystem) will be passed to the corresponding 
body and used as specified there. The parameter names in a promise are fixed 
and defined by the promise type (you can look up perms, copy_from and 
depth_search in the manual), but the right-hand names (usystem, urecurse and 
umycopy in this example) are arbitrary and defined by you.

Classes:

Finally, classes. "Boolean classifier" simply means that classes are either 
true or false (a boolean value). They cannot contain any other values, but they 
can be arbitrary names that describe any property that you may want to use to 
control the execution of the cfengine policy. For example:

commands:
  windows::
      "c:\Program Files\somedirectory\someprogram.exe";
  linux::
      "/usr/bin/someprogram";

In this case, "windows" and "linux" are both classes that cfengine 
automatically defines (called "hard classes") based on the type of system in 
which it is running. Cfengine defines a whole bunch of hard classes every time 
it runs, which allow you to easily test for the type of system you are running, 
its network configuration, the time of day/week/month/year, etc. Of course, you 
can also define your own classes (called "soft classes") based on anything else 
you want to do during the execution of a cfengine policy. For example:

classes:
  # Is the cfengine key properly initialized?
  "have_ppkeys"                 expression => 
fileexists("$(sys.workdir)/ppkeys/localhost.pub");
commands:
  # If the keys have not been generated, do that now
  !have_ppkeys::
    "/usr/local/sbin/cf-key";

In this case, the have_ppkeys class will be defined (true) if the 
/var/cfengine/ppkeys/localhost.pub key exists, and undefined (false) if it 
doesn't. Then, in the commands section, the command to produce that file will 
be run if the class is undefined.

I hope this clarifies the topic a little bit. Cfengine can be a bit tricky to 
wrap your head around at the beginning because of its mix of declarative and 
imperative components. One of the main concepts (and the hardest if you have 
any sort of programming background, so if you are not a programmer you may have 
an advantage here) is that you don't really control the flow and order of the 
steps cfengine takes - you simply specify the different discrete pieces and the 
conditions they have to satisfy, and cfengine figures out on its own what needs 
to be done to ultimately satisfy all the promises that you have specified.

--
Diego Zamboni
http://blog.zzamboni.org/
@zzamboni

_______________________________________________
Help-cfengine mailing list
Help-cfengine@cfengine.org
https://cfengine.org/mailman/listinfo/help-cfengine

Reply via email to