Who cares about that promise?
Today, I want to highlight one of the lightweight knowledge management features in CFEngine. That is, Promisees, also known as Stakeholders. Promisees are references to things that might care about a specific promise. And they can be attached to any promise. Let’s take a look at a contrived example:
bundle agent __main__ { methods: "example_promisees" -> { "Feature Friday #21" }; } bundle agent example_promisees { reports: "Happy Friday!"; } From the example above, we can see that the methods promise - promising to run the example_promisees bundle - has Feature Friday #21 defined as the only promisee. It provides us with a hint that Feature Friday #21 cares that the bundle will be run. Promisees have no effect on the execution of the policy. However, they provide breadcrumbs that can be useful when the policy is re-visited.
Did you know CFEngine has Macros?
They were first introduced in CFEngine 3.7 (back in 2015), and more have been introduced since then. Macros are convenient for preventing the parsing of a section of the policy. It is handy for protecting older binaries from getting tripped up on newer syntax the agent does not understand. Let’s take a look.
Currently there are 8 macros.
minimum_version - Prevent the section of policy from being parsed unless the agent meets a minimum version. maximum_version - Prevent the section of policy from being parsed when the agent exceeds a maximum version. at_version - Prevents the section of policy from being parsed unless the agent is of a specific version. between_versions - Prevents a section of policy from being parsed unless the agent is between (inclusive) a minimum and maximum version. before_version - Prevents a section of policy from being parsed unless the agent is below a specified version (not inclusive). after_version - Prevents a section of policy from being parsed unless the agent is above a specified version (not inclusive). else - Allows the agent to parse a section of policy only if the preceding macro is not applicable. feature - Prevents a section of policy from being parsed based on feature availability. You can find examples of use within the Masterfiles Policy Framework. For example, body action fresh_systemd_state uses the minimum_version macro to control the setting of ifelapsed => "0" to versions 3.18.1 and higher since versions below might produce a warning.
Ever want to manage subvalues in a configuration file? In episode 39 we talk about using field_edits in edit_line bundles.
Cody and Craig join Nick as he prototypes and iterates on some policy showing how to manage subvalues in KEY = quoted values. A question raised during one of our recent post show discussions.
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.
Do you know how to quickly see what variables and classes are defined?
Often, while developing CFEngine policy it’s convenient to emit a variable value or a report based on the presence of a class. For example:
bundle agent main { reports: "Unqualified hostname = '$(sys.uqhost)'"; linux:: "I am running on linux"; } In some cases, this is because you are exploring what classes are available. In other cases, it might be DEBUG-related reports helping you understand how a variable is resolved during policy evaluation. Often, you can get this information without writing CFEngine policy to emit it by using the --show-vars or --show-classes options to cf-promises.
Ever want to get some data into CFEngine? Have you heard about the def.json Augments file?1
Augments are JSON data files that allow you to define classes and variables very early during agent initialization, before policy. Augments are practical in a variety of ways. Perhaps most notably for overriding policy defaults.
Let’s look at a simple example.
Here we have a policy /tmp/feature-friday/18-0.cf
/tmp/feature-friday/18-0.cf bundle agent main { reports: "MyVariable $(with) defined '$(MyVariable)'" with => ifelse( isvariable( MyVariable ), "is", "is not" ); } Running it, we can see that MyVariable isn’t defined
Let’s talk about tags and how they can be useful for Inventory and Reporting.
If you have been following along with the Feature Friday series you already heard about using tags to find currently defined classes, variables and bundles, but they are also very useful for reporting. In CFEngine Enterprise the inventory and attribute_name tags are special. A variable or class tagged with inventory becomes visible in the Inventory subsystem in Mission Portal with the name given in the attribute_name tag.
Did you know the Masterfiles Policy Framework (MPF) ships with a host info report?
That’s right, you can simply run cf-agent --bundlesequence host_info_report and a report will be generated.
command cf-agent --bundlesequence host_info_report output R: Host info report generated and available at '/var/cfengine/reports/host_info_report.txt' It’s packed with information about the specific host.
Let’s peek:
command head -n 9 /var/cfengine/reports/host_info_report.txt output # Host Information Generated: Fri Feb 23 19:54:13 2024 ## Identity Fully Qualified Hostname: hub.example.com Host ID: SHA=41ebb680d136f82c57af6ee1a7b938c093fe8d773bf320213eae1c476dad4fb0 ## CFEngine Version: CFEngine Enterprise 3.21.4 Here are the section headers:
Interested to see what’s new in the next LTS version (3.24) of CFEngine?
Nick joins Craig and Cody to see what’s coming in 3.24. From the new groups feature which allows you to assign data to a group of hosts to improvements in filtering and new functionality in Build and other changes in behavior, checkout the video for all the details.
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.
Did you know bundles can have tags too?
That’s right! You can tag a bundle by defining tags as a meta promise on a bundle.
For example:
bundle agent example_bundle_tag { meta: "tags" slist => { "tag_1", "tag_2" }; } You’ve likely encountered bundles tagged with autorun. These tags trigger automatic execution of bundles in lexical order whenever the services_autorun class is defined. However, you’re not limited to autorun. You can create custom tags to suite your specific needs. Perhaps you want to tag bundles associated with a particular compliance framework or identify the primary developer/team responsible for maintenance.
You may see a new warning in the upcoming releases of 3.21.5 and 3.24.0. A new warning was introduced with a fix to the behavior of depth_search when combined with a copy_from source targeting a file:
depth_search (recursion) is promised for a base object '<filename>' that is not a directory Prior to versions 3.21.5 and 3.24.0 CFEngine would copy the file initially but would subsequently avoid updating the file providing only debug log message about the fact that the file was being skipped (because it’s not possible to descend into a file). Beginning with 3.21.5 and 3.24.0 CFEngine will copy the file and properly update the file but will also emit a warning that recursion was promised for something that was not a directory.