CFengine 3 Tutorial -- Part 3 -- Hello World


So up to this point, we’ve had a high level 10,000ft introduction to how CFEngine works. Hopefully we’ve gotten the needed bits built and packaged up to bootstrap our infrastructure. As any other programming language begins, lets look at the most basic “Hello World” type policy.

/var/tmp $ cat /var/tmp/hello_world.cf
1 body common control
2 {
3 bundlesequence => { "hello_prefetch_net_friends" };
4 }
5 bundle agent hello_prefetch_net_friends
6 {
7 reports:
8 cfengine_3::
9 "Hello World";
10
11 sunos_5_10::
12 "I am a Solaris 10 host";
13 }

Great. Lets execute. Use the -f flag to point cf-agent at the Policy we want to execute against. If we don’t supply the -f, then cf-agent assumes the policy file resides in /var/cfengine/inputs. Since we created this example in /var/tmp, we need to direct cf-agent to execute the policy using the absolute path.

/var/tmp $ /var/cfengine/bin/cf-agent -f /var/tmp/hello_world.cf
R: Hello World
R: I am a Solaris 10 host
/var/tmp $ /var/cfengine/bin/cf-agent -f /var/tmp/hello_world.cf
/var/tmp $
/var/tmp $ /var/cfengine/bin/cf-agent -f /var/tmp/hello_world.cf -K
R: Hello World
R: I am a Solaris 10 host

Excellent! Lets break this down line-by-line on the sample policy above.

So, this example forms the backbone of how CFengine policies are interpreted and executed. We defined a single promise in our bundlesequence, and in that bundlesequence we defined that we wanted the “type” to be a reports action — based upon the class of machine that cf-agent discovered. Nice! But wait.. When we executed the same command again immediately after, nothing was printed to stdout. Why?

By default, cf-agent will only execute a policy at minimum once a minute. When we specify the -K flag on the command line at the 3rd execution, the -K instructs cf-agent to ignore this “one minute rule.”

$ /var/cfengine/bin/cf-agent --help | grep '-K'

--no-lock , -K - Ignore locking constraints during execution (ifelapsed/expireafter) if "too soon" to run

Nice! I want to see all the gory details of what cf-agent actually does. Show me the money! Throw in the -v flag for cf-agent to execute verbosely.

/var/cfengine/bin/cf-agent -f /var/tmp/hello_world.cf -v
1 cf3 Cfengine - autonomous configuration engine - commence self-diagnostic prelude
2 cf3 ------------------------------------------------------------------------
3 cf3 Work directory is /var/cfengine
4 cf3 Making sure that locks are private...
5 cf3 Checking integrity of the state database
6 cf3 Checking integrity of the module directory
7 cf3 Checking integrity of the PKI directory
8 cf3 Looking for a source of entropy in /var/cfengine/randseed
9 cf3 Loaded /var/cfengine/ppkeys/localhost.priv
10 cf3 Loaded /var/cfengine/ppkeys/localhost.pub
11 cf3 No registered cfengine service, using default
12 cf3 !!! System error for getservbyname: "Error 0"
13 cf3 Setting cfengine default port to 5308 = 5308
14 cf3 Reference time set to Fri Jul 2 11:15:21 2010
15 cf3 Cfengine - 3.0.4 (C) Cfengine AS 2008-
16 cf3 ------------------------------------------------------------------------
17 cf3 Host name is: sinatra
18 cf3 Operating System Type is sunos
19 cf3 Operating System Release is 5.10
20 cf3 Architecture = i86pc
21 cf3 Using internal soft-class solarisx86 for host sinatra
22 cf3 The time is now Fri Jul 2 11:15:21 2010
23 cf3 ------------------------------------------------------------------------
24 cf3 # Extended system discovery is only available in version Nova and above
25 cf3 Additional hard class defined as: 32_bit
26 cf3 Additional hard class defined as: sunos_5_10
27 cf3 Additional hard class defined as: sunos_i86pc
28 cf3 Additional hard class defined as: sunos_i86pc_5_10
29 cf3 Additional hard class defined as: i386
30 cf3 Additional hard class defined as: i86pc
31 cf3 GNU autoconf class from compile time: compiled_on_solaris2_10
32 cf3 Address given by nameserver: 172.18.33.58
33 cf3 Adding alias loghost..
34 cf3 Trying to locate my IPv6 address
35 cf3 Looking for environment from cf-monitor...
36 cf3 Loading environment...
37 cf3 Environment data loaded
39 cf3 Loading persistent classes
42 cf3 Loaded persistent memory
44 cf3 > Verifying the syntax of the inputs...
45 cf3 > Parsing file /var/tmp/hello_world.cf
46 cf3 Initiate variable convergence...
47 cf3 Initiate control variable convergence...
48 cf3 Initiate variable convergence...
49 cf3 # Knowledge map reporting feature is only available in version Nova and above
50 cf3 -> Defined classes = { 172_18_33_58 32_bit Day2 Friday GMT_Hr18 Hr11 Hr11_Q2 July Lcycle_0 Min15 Min15_20 Morning Q2 Yr2010 agent any cfengine_3 cfengine_3_0 cfengine_3_0_4 community_edition compiled_on_solaris2_10 corp diskfree_low_dev1 entropy_cfengine_in_low entropy_dns_in_low entropy_dns_out_low entropy_ftp_in_low entropy_ftp_out_low entropy_icmp_in_low entropy_icmp_out_low entropy_irc_in_low entropy_irc_out_low entropy_misc_in_low entropy_misc_out_low entropy_netbiosdgm_in_low entropy_netbiosdgm_out_low entropy_netbiosns_in_low entropy_netbiosns_out_low entropy_netbiosssn_in_low entropy_netbiosssn_out_low entropy_nfsd_in_low entropy_nfsd_out_low entropy_smtp_in_low entropy_smtp_out_low entropy_ssh_out_low entropy_tcpack_in_low entropy_tcpack_out_low entropy_tcpfin_in_low entropy_tcpfin_out_low entropy_tcpsyn_in_low entropy_tcpsyn_out_low entropy_udp_in_low entropy_udp_out_low entropy_www_in_low entropy_www_out_low entropy_wwws_in_low entropy_wwws_out_low sinatra sinatra i386 i86pc ipv4_172 ipv4_172_18 ipv4_172_18_33 ipv4_172_18_33_58 loghost net_iface_e1000g833000_2 net_iface_lo0_2 rootprocs_high_normal solarisx86 sunos_5_10 sunos_i86pc sunos_i86pc_5_10 sunos_i86pc_5_10_Generic_127128_11 verbose_mode }
51 cf3 -> Negated Classes = { }
52 cf3 Initiate variable convergence...
53 cf3 Initiate control variable convergence...
54 cf3 -> Immunizing against parental death
55 cf3 -> Bundlesequence => {'hello_prefetch_net_friends'}
56 cf3
58 cf3 BUNDLE hello_prefetch_net_friends
60 cf3
61 cf3
62 cf3 + Private classes augmented:
63 cf3
64 cf3 - Private classes diminished:
65 cf3
66 cf3
67 cf3
68 cf3 =========================================================
69 cf3 reports in bundle hello_prefetch_net_friends (1)
70 cf3 =========================================================
71 cf3
72 cf3 Verifying SQL table promises is only available with Cfengine Nova or above
73 cf3 XX Nothing promised here [lock.hello_prefetch_net_friend] (0/1 minutes elapsed)
74 cf3 XX Nothing promised here [lock.hello_prefetch_net_friend] (0/1 minutes elapsed)
75 cf3
76 cf3 + Private classes augmented:
77 cf3
78 cf3 - Private classes diminished:
79 cf3
80 cf3
81 cf3
82 cf3 =========================================================
83 cf3 reports in bundle hello_prefetch_net_friends (2)
84 cf3 =========================================================
85 cf3
86 cf3 Verifying SQL table promises is only available with Cfengine Nova or above
87 cf3
88 cf3 + Private classes augmented:
89 cf3
90 cf3 - Private classes diminished:
91 cf3
92 cf3
93 cf3
94 cf3 =========================================================
95 cf3 reports in bundle hello_prefetch_net_friends (3)
96 cf3 =========================================================
97 cf3
98 cf3 Verifying SQL table promises is only available with Cfengine Nova or above
99 cf3 Outcome of version (not specified) (agent-0): Promises observed to be kept 100%, Promises repaired 0%, Promises not repaired 0%
100 cf3 Estimated system complexity as touched objects = 0, for 2 promises

ets break this down line-by-line on what cf-agent is telling us that happened.

By default, if we execute cf-agent, it will only report back to us the actions it failed to take / problems that it encountered. This may not be the best of examples, but the -I flag (–inform) will instruct cf-agent to report back to us the “good” things it did. It will “inform” us of changes made, commands executed, config files modified, etc. So a common invocation of cf-agent from the CLI when testing newly written policies is:

$ /var/cfengine/bin/cf-agent -f [absolute path to policy file] -I -K

Again, -I will inform us of “successfully executed” actions and -K will allow the policy to execute even if its been less than a minute from the previous run.

This article was posted by Mike on 2010-07-02 14:31:00 -0400 -0400