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