When you first told me that this change was coming I was astonished because I know that normal order, the normal ordering is very intentional like a lot of thought went into it right and it’s not configurable, again on purpose, right!?
In this episode, Nick is joined by long-time CFEngine user and trainer, Aleksey Tsalolikhin. It was a conversation with Aleksey at a LISA conference in 2010 that set Nick on his CFEngine journey, asking, “What do you want from your configuration management tooling?”. Nick knew immediately that the tool he was using, while great, didn’t fit the characteristics he was looking for.
Today, they reunite to discuss a significant new feature in CFEngine 3.27: file-specific evaluation order. For years, CFEngine’s “normal” evaluation order has been a cornerstone of its predictable, convergent behavior. But what happens when you need a more procedural, top-down approach for a specific part of your policy? Now, with evaluation_order => "top_down"; in body file control, you can have the best of both worlds. We explore how this feature works, why it’s useful for logging and for simplifying policy for new users, and how to use it safely alongside your existing policy.
Notes
One of the most discussed aspects of learning CFEngine is its evaluation order. The “normal” order is carefully designed for convergence, ensuring that dependencies are typically met before they are needed (e.g., files are promised before packages that might own them). However, this can sometimes be counter-intuitive for those accustomed to procedural scripting.
With CFEngine 3.27, you can now control this behavior on a per-file basis using body file control.
Normal (Classic) Evaluation Order
By default, CFEngine evaluates promises in a specific order, regardless of where they appear in the bundle. For example, commands promises are evaluated before reports promises.
bundle agent reports_normal
{
reports: "Hello world:";
commands: "/bin/echo hi";
reports: "bye:";
}
bundle agent __main__
{
methods: "reports_normal";
}Running this bundle results in the command executing first:
notice: Q: ".../bin/echo hi": hi
R: Hello world:
R: bye:Top-Down Evaluation Order
By adding a body file control with evaluation_order ==> "top_down";, you can force CFEngine to evaluate the promises in the order they are written in the file.
body file control
{
evaluation_order => "top_down";
}
bundle agent reports_top_down
{
reports: "Hello world:";
commands: "/bin/echo hi";
reports: "bye:";
}
bundle agent __main__
{
methods: "reports_top_down";
}Now, the output respects the written order:
R: Hello world:
notice: Q: ".../bin/echo hi": hi
R: bye:This is particularly useful for:
- Logging and Debugging: Easily print messages at the beginning and end of a bundle.
- On-boarding New Policy Writers: Provides a more familiar, procedural execution model for specific tasks.
- Complex Sequences: When you need to enforce a strict, linear sequence of operations without relying on
depends_onor multiple bundle calls.
You can safely mix and match evaluation orders by using the inputs key in body file control, allowing you to adopt this new feature gradually and only where it makes sense.
Video
The video recording is available on YouTube:
At the end of every webinar, we stop the recording for a nice and relaxed, off-the-record chat with attendees. Join the next webinar to not miss this discussion.
Links
- Connect w/ Cody, Craig, Herman, or Nick
- All Episodes