Installing packages with Cfengine 3

For some strange reason I still have the motivation to look at the “new” Cfengine 3. While I covered editing files and checking for running services in the last posts, I will try to do some very basic package management with Cfengine 3 today.

Writing the script

body common control {
version => "1.0";
inputs => { "cfengine_stdlib.cf" };
bundlesequence => { "manage_packages" };
}

bundle agent manage_packages {
vars:
"package_list" slist => { "slapd", "ldap-utils" };

packages:
"$(package_list)"
package_policy => "add",
package_method => generic;
}

Save the file and check if the syntax is correct:

cf-promises -f /var/lib/cfengine/inputs/example3.cf

No errors? Nah, of course not! 🙂 Time to run cf-agent:

cf-agent -f /var/lib/cfengine3/inputs/example3.cf

In my case, cf-agent gives some output and shows me that the cache of the apt repos are renewed. A few seconds later, aptitude –assume-yes install ldap-utils slapd gets called (excerpt):

cf3> ?? Already have a (cached) package list for this manager
cf3> -> Package version was not specified
cf3> -> Looking for (slapd,*,*)
cf3> No installed packages matched (slapd,*,*)
cf3> -> Looking for (slapd,*,*)
cf3> No installed packages matched (slapd,*,*)
cf3> Checking if package (slapd,*,*) is at the desired state (installed=0,matched=0)
cf3> -> Package promises to refer to itself as "slapd" to the manager
cf3> -> Package version seems to match criteria
cf3> -> Schedule package for addition
cf3> -> Package (slapd,any,any) found
cf3>
cf3> .........................................................
cf3> Promise handle:
cf3> Promise made by: ldap-utils
cf3> .........................................................
cf3>
cf3> -> This promise has already been verified
cf3> ?? Already have a package list for this manager
cf3> -> Package version was not specified
cf3> -> Looking for (ldap-utils,*,*)
cf3> No installed packages matched (ldap-utils,*,*)
cf3> -> Looking for (ldap-utils,*,*)
cf3> No installed packages matched (ldap-utils,*,*)
cf3> Checking if package (ldap-utils,*,*) is at the desired state (installed=0,matched=0)
cf3> -> Package promises to refer to itself as "ldap-utils" to the manager
cf3> -> Package version seems to match criteria
cf3> -> Schedule package for addition
cf3> -> Package (ldap-utils,any,any) found
cf3> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
cf3> Offering these package-promise suggestions to the managers
cf3> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
cf3> -> Deletion schedule...
cf3> -> Addition schedule...
cf3> Execute scheduled package addition
cf3> Command prefix: /usr/bin/aptitude --assume-yes install
cf3> Executing /usr/bin/aptitude --assume-yes install ldap-utils slapd ...
cf3> Q:aptitude --assume-ye ...:Reading package lists...
cf3> Q:aptitude --assume-ye ...:Building dependency tree...
cf3> Q:aptitude --assume-ye ...:Reading state information...
cf3> Q:aptitude --assume-ye ...:Reading extended state information...
cf3> Q:aptitude --assume-ye ...:Initializing package states...
cf3> Q:aptitude --assume-ye ...:Writing extended state information...
cf3> Q:aptitude --assume-ye ...:The following NEW packages will be installed:
cf3> Q:aptitude --assume-ye ...: ldap-utils slapd
cf3> Q:aptitude --assume-ye ...:0 packages upgraded, 2 newly installed, 0 to remove and 348 not upgraded.
[...]

Some details of the Cfengine 3 script
Since I assume that you have read my previous blog posts about Cfengine 3 I am also assuming that you are already familiar with the first section of the script (“body common control”).

Hence we should directly look at the next part:

bundle agent manage_packages {
vars:
"package_list" slist => { "slapd", "ldap-utils" };

Here we define a promise of the type “vars”. The promise contains a variable with the name “package_list” and the type “slist”. The “package_list” contains a list of packages which should be always installed. If they are not, Cfengine 3 will keep the promise and install them for you..

… which leads us to the last part:

packages:
"$(package_list)"
package_policy => "add",
package_method => generic;
}

“packages” is a promise type, like “vars”, “commands” or “interfaces”. The “package_policy” basically defines what happens next and could also be “addupdate” in this example. If the packages would have already been installed on our system they simply would be updated (if even possible).

Now the “package_method” is very interesting. There are several package methods and they are all defined in the file “cfengine_stdlib.cf” which comes with Cfengine 3 by default. The method “generic” is valid for supported operating systems. This means that you could run this Cfengine3 script on Debian, RedHat and other distros and it would still be work. If you wanted some more distro-specific, you could use “package_method => apt” or “package_method => yum” for example.

Well, that’s already it! Today’s example showed how to perform a simple package management with the help of Cfengine 3. I hope this code snipped might help you in some way. If not, you maybe want to contribute a new blog entry to my blog?

Btw, you can download the Cfengine 3 script of this blog post here.

3 thoughts on “Installing packages with Cfengine 3

Comments are closed.