Did you know that CFEngine can simply warn about something not being in the desired state?
Traditionally with CFEngine, you define your desired state and CFEngine works towards making that happen. Sometimes you might not want CFEngine to take action and instead warn that a given promise wants to change something. Let’s take a look at a contrived example.
Say we want the file /tmp/feature-friday-22.txt
to exist, we might write a policy that looks like this:
bundle agent __main__
{
files:
"/tmp/feature-friday-22.txt"
create => "true";
}
But, we don’t actually want the file to exist, rather we want a warning. Well, you could implement that using a reports-type promise:
bundle agent __main__
{
reports:
"warning: /tmp/feature-friday-22.txt doesn't exist!"
unless => fileexists("/tmp/feature-friday-22.txt");
}
However, there is a slight difference. A reports
promise will be seen as a promise kept
- yes it will be in your logs - but it’s a bit less visible in general. Instead, we can attach an action
body with the action_policy
attribute set to warn
. Let’s adjust our first example:
bundle agent __main__
{
files:
"/tmp/feature-friday-22.txt"
create => "true",
action => warn_dont_fix,
classes => results( "bundle", "example_warn" );
reports:
example_warn_not_kept:: "My promise to ensure /tmp/feature-friday-22.txt was not kept";
}
body action warn_dont_fix
{
action_policy => "warn";
}
Running the policy we can see that warnings were emitted by the agent and that the files
promise itself was not kept. We even get a bit more detail about the described state of the file, like the fact that it would be created with permissions only allowing it to be read by the owner.
cf-agent -Kf /tmp/feature-friday-22-0.cf
warning: Should create file '/tmp/feature-friday-22.txt', mode '0600', but only warning promised
warning: Warnings encountered when actuating files promise '/tmp/feature-friday-22.txt'
R: My promise to ensure /tmp/feature-friday-22.txt was not kept
Let’s take it a bit further, what if we only want to warn when a specific context is true. For example, let’s warn except on the day of the publication date of this post.
Here the action_policy
is guarded by a class expression targeting any day except the publication date of this post. Unless it’s the publication date, the policy will just warn, otherwise it will have the default behavior and fix the state.
bundle agent __main__
{
files:
"/tmp/feature-friday-22.txt"
create => "true",
action => warn_dont_fix_except_publication,
classes => results( "bundle", "example_warn" );
reports:
example_warn_not_kept:: "My promise to ensure /tmp/feature-friday-22.txt was not kept";
example_warn_repaired:: "My promise to ensure /tmp/feature-friday-22.txt was repaired";
example_warn_kept:: "My promise to ensure /tmp/feature-friday-22.txt needed no action and was kept";
}
body action warn_dont_fix_except_publication
{
action_policy => "warn";
!(Yr2024.August.Day09)::
action_policy => "fix";
}
Running the policy, on any other day than the publication of the post, causes it to fix the state as desired:
cf-agent -Kf /tmp/feature-friday-22-1.cf
R: My promise to ensure /tmp/feature-friday-22.txt was repaired
This sort of logic can be tied to maintenance windows or other classes, allowing you to automatically adjust when a promise warns or takes action.
Happy Friday! 🎉