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:
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.
Did you know you can find variables by name and tag?
Like the ability to find currently defined classes (as described in Feature Friday #13: classesmatching()) that match a name or tag, you can find variables by name and tag. It’s a nifty capability. variablesmatching() returns a list of variable names that match the name and tag criteria.1 variablesmatching_as_data() returns a data container of the matching variables along with their values2.
Did you know you can find classes by name and tag?
classesmatching() dynamically sources information from the current state. For example, let’s say you have classes representing a system’s role. Furthermore, let’s say that we want a host to only have a single role class defined. Finally, if we have more than one role class defined, then we don’t want to proceed.
To achieve this without classesmatching(), we might have a policy file that looks like this (/tmp/feature-friday-13/tags-on-classes-0.cf)
Are you familiar with CFEngines special variables?
Probably you are familiar with sys variables like sys.fqhost (the fully qualified host name) and sys.policy_hub (the IP address of the machine the host is bootstrapped to) but I want to highlight a few other special variables you may not be so familiar with.
sys Sys variables are derived from the system discovery done by the agent as it initializes.
sys.os_release - A data structure derived from /etc/os-release /etc/os-release, introduced by systemd provides a nice record of the current distributions release information.1 CFEngine prefers information from this file for determining system classification like the definition of the redhat and debian classes. The file can also be extended with custom keys, like I have done on my system to set NORTHERN_TECH_OWNER=Nick Anderson. Since files information is exposed as a data container in this sys variable it can be useful for influencing policy behavior, like selecting additional Augments to load.2
Did you know that CFEngine has namespaces? Let’s see how they can facilitate policy sharing while avoiding “duplicate definitions of bundle” errors.
Most of the Masterfiles Policy Framework (MPF) and policy examples for CFEngine use the default namespace. However, body file control allows you to specify a namespace that applies for the rest of the file or until it’s set again by another body file control.
Let’s consider a contrived example. Say we have two policy files (policy-1.cf, policy-2.cf) for different services. In each policy file, we want to have a bundle where we store settings related to that policy. Traditionally this would be handled by using some bundle naming convention, so we might have bundle agent policy_1_settings and bundle agent policy_2_settings. Using namespaces you can keep your bundle names brief and use different namespaces to avoid “duplicate definitions of bundle” errors.
Found a bug, asking for help? Use cf-support to collect info quickly.
cf-support was born from interactions supporting Enterprise customers to streamline data collection and was introduced in late 2022 with the release of 3.18.31 and 3.21.02. Furthermore, it was featured on The Agent is In3 episode 21 Troubleshooting with cf-support. It gathers various details about the system and creates an archive that you can attach to your ticket. While its inception was geared towards Enterprise customers, it’s still both useful and available for community users as well.
Did you know you can include one policy file from another?
Traditionally you specify the files you want to make up a policy set using inputs in body common control found in your policy entry (promises.cf by default).
body common control { # Paths are relative to $(sys.policy_entry_dirname) if not # fully qualified inputs => { "path/to/policy-1.cf", "path/to/policy-2.cf", }; } body file control lets you specify additional inputs from any file that’s included in the policy and those files can include other files.
Ever want to run just a one or a few select bundles from your policy?
While developing policy it’s common to run cf-agent -KI so that you can quickly iterate on changes and the run the policy without locks. But if you are focused on select bundles you may not need the full policy to run, you can use the --bundlesequence option to specify one or more bundles overriding the bundlesequence defined in body common control.
Ever wanted to make sure a promise only runs if some other promise has succeeded?
Consider this contrived example with two reports type promises, It's Friday! and I love CFEngine Feature Friday. Per normal ordering1, these two promises will be emitted in the written order.
/tmp/feature-friday-7.cf bundle agent feature_friday { reports: "It's Friday, Friday"; "Gotta get down on Friday"; } command cf-agent --no-lock --bundlesequence feature_friday --file /tmp/feature-friday-7.cf output R: It's Friday! R: I love CFEngine Feature Friday. If we want them in the opposite order, we could either change the order or define classes based on the results of the promises. But today’s feature, depends_on, lets us influence the ordering using a more lightweight method via handle.