Examples and Tutorials
Links to Examples
- Example Snippets: This section is divided into topical areas and includes many examples of policy and promises. Each of the snippets can be easily copied or downloaded to a policy server and used as is.
Note: CFEngine also includes a small set of examples by default, which can be
found in /var/cfengine/share/doc/examples
.
See Also:
Tutorial for Running Examples
In this tutorial, you will perform the following:
- Create a simple "Hello World!" example policy file
- Make the example a standalone policy
- Make the example an executable script
- Add the example to the main policy file (
promises.cf
)
Note if your CFEngine administrator has enabled continuous deployment of the policy from a Version Control System, your changes may be overwritten!
"Hello World" Policy Example
Policies contain bundles, which are collections of promises. A promise is a declaration of intent. Bundles allow related promises to be grouped together, as illustrated in the steps that follow.
Following these steps, you will login to your policy server via the SSH protocol, use the vi command line editor to create a policy file named hello_world.cf, and create a bundle that calls a promise to display some text.
- Log into a running server machine using ssh (PuTTY may be used if using Windows).
- Type
sudo su
for super user (enter your password if prompted). - To get to the masterfiles directory, type
cd /var/cfengine/masterfiles
. - Create the file with the command:
vi hello_world.cf
In the vi editor, enter
i
for "Insert" and enter the following content (ie. copy and paste from a text editor):bundle agent hello_world { reports: any:: "Hello World!"; }
Exit the "Insert" mode by pressing the "esc" button. This will return to the command prompt.
Save the changes to the file by typing
:w
then "Enter".Exit vi by typing
:q
then "Enter".
In the policy file above, we have defined an agent bundle named hello_world
. Agent
bundles are only evaluated by cf-agent, the agent component of CFEngine.
This bundle promises to report on any class of hosts.
Activate a Bundle Manually
Activate the bundle manually by executing the following command at prompt:
/var/cfengine/bin/cf-agent --no-lock --file ./hello_world.cf --bundlesequence hello_world
This command instructs CFEngine to ignore locks, load
the hello_world.cf
policy, and activate the hello_world
bundle. See the output below:
# /var/cfengine/bin/cf-agent --no-lock --file ./hello_world.cf --bundlesequence hello_world
2013-08-20T14:03:43-0500 notice: R: Hello World!
As you get familiar with CFEngine, you'll probably start shortening this command to this equivalent:
/var/cfengine/bin/cf-agent -Kf ./hello_world.cf -b hello_world
Note the full path to the binary in the above command. CFEngine stores its binaries in /var/cfengine/bin on Linux and Unix systems. Your path might vary depending on your platform and the packages your are using. CFEngine uses /var because it is one of the Unix file systems that resides locally. Thus, CFEngine can function even if everything else fails (your other file systems, your network, and even system binaries) and possibly repair problems.
Make the Example Stand Alone
Instead of specifying the bundle sequence on the command line (as it was above), a body common
control section can be added to
the policy file. The body common control refers to those promises that are hard-coded into
all CFEngine components and therefore affect the behavior of all components. Note that only
one body common control
is allowed per agent activation.
Go back into vi by typing "vi" at the prompt. Then type i
to insert
body common control to hello_world.cf
. Place it above bundle agent hello_world, as
shown in the following example:
body common control
{
bundlesequence => { "hello_world" };
}
bundle agent hello_world
{
reports:
any::
"Hello World!";
}
Now press "esc" to exit the "Insert" mode, then type :w
to save the file changes and "Enter".
Exit vi by typing :q
then "Enter." This will return to the prompt.
Execute the following command:
console
/var/cfengine/bin/cf-agent --no-lock --file ./hello_world.cf
The output is shown below:
# /var/cfengine/bin/cf-agent --no-lock --file ./hello_world.cf
2013-08-20T14:25:36-0500 notice: R: Hello World!
Note: It may be necessary to add a reference to the standard library within the body common control section, and remove the bundlesequence line. Example:
body common control {
inputs => {
"libraries/cfengine_stdlib.cf",
};
}
Make the Example an Executable Script
Add the #!
marker ("shebang") to hello_world.cf
in order to invoke CFEngine policy as an executable script:
Again type "vi" then "Enter" then i
to insert the following:
#!/var/cfengine/bin/cf-agent --no-lock
Add it before body common control, as shown below:
#!/var/cfengine/bin/cf-agent --no-lock
body common control
{
bundlesequence => { "hello_world" };
}
bundle agent hello_world
{
reports:
any::
"Hello World!";
}
Now exit "Insert" mode by pressing "esc". Save file changes by typing :w
then "Enter"
then exit vi by typing :q
then "Enter". This will return to the prompt.
Make the policy file executable, and then run it, by typing the following two commands:
chmod +x ./hello_world.cf
Followed by:
./hello_world.cf
See the output below:
# chmod +x ./hello_world.cf
# ./hello_world.cf
2013-08-20T14:39:34-0500 notice: R: Hello World!
Integrating the Example into your Main Policy
Make the example policy part of your main policy by doing the following on your policy server:
Ensure the example is located in
/var/cfengine/masterfiles
.If the example contains a
body common control
section, delete it. That section will look something like this:body common control { bundlesequence => { "hello_world" }; }
You cannot have duplicate control bodies (i.e. two agent control bodies, one in the main file and one in the example) as CFEngine won't know which it should use and they may conflict.
To resolve this, copy the contents of the control body section from the
example into the identically named control body section in the main policy
file /var/cfengine/masterfiles/promises.cf
and then remove the control body
from the example.
Insert the example's bundle name in the
bundlesequence
section of the main policy file/var/cfengine/masterfiles/promises.cf
:bundlesequence => { ... "hello_world", ... };
Insert the policy file name in the
inputs
section of the main policy file/var/cfengine/masterfiles/promises.cf
:inputs => { ... "hello_world.cf", ... };
You must also remove any inputs section from the example that includes the external library:
inputs => { "libraries/cfengine_stdlib.cf" };
This is necessary, since
cfengine_stdlib.cf
is already included in the inputs section of the master policy.The example policy will now be executed every five minutes along with the rest of your main policy.
Notes: You may have to fill the example with data before it will work.
For example, the LDAP query in active_directory.cf
needs a domain name.
In the variable declaration, replace "cftesting" with your domain name:
vars:
# NOTE: Edit this to your domain, e.g. "corp"
"domain_name" string => "cftesting";