Show notes: The agent is in - Episode 18 - Policy examples

Posted by Nick Anderson
October 27, 2022

Do you know how to use every function available in CFEngine?

Join Cody, Craig, Herman to see how Nick uses org-mode, org-roam, and ob-cfengine3 to manage his personal collection of CFEngine Function Examples.

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.

Notes

Live coded examples for the following functions:

  • regline( regex, filename )
    • Returns whether the anchored regular expression regex matches a line in filename.
  • reglist( list, regex )
    • Returns whether the anchored regular expression regex matches any item in list.
      • Very similar to some( regex, list ) but it differs in reversed parameters and the regular expression is unanchored.
  • parseyaml( 'inline-yaml' )
    • Parses YAML data directly from a string and returns the result as a data variable.
      • Not to be confused with readyaml() which is for parsing a YAML file, a much more common use case.

regline()

Look to see if quiet is a boot option.

bundle agent __main__
{
  classes:
    "have_quiet_boot"
      expression => regline("$(anchored_regex)", $(file));

  vars:

    # e.g. BOOT_IMAGE=/vmlinuz-5.15.0-52-generic root=/dev/mapper/vgkubuntu-root ro quiet splash vt.handoff=7
    "anchored_regex"
      string => ".*\s+quiet\s*.*";

    "file"
      string => "/proc/cmdline";

  reports:
    have_quiet_boot::
      "Have quiet in body cmdline args";
      "$(file)" printfile => cat($(file));
}
R: Have quiet in body cmdline args
R: /proc/cmdline
R: BOOT_IMAGE=/vmlinuz-5.15.0-52-generic root=/dev/mapper/vgkubuntu-root ro quiet splash vt.handoff=7

reglist()

Determine if at least one element of a list starts with c (case insensitive).

bundle agent __main__
{
  vars:
    "names"
      slist => {"Cody", "Craig", "Herman", "Nick"};

    # This regex is unanchored, because the function itself anchors it.
    "anchored_regex"
      string => "(?i)c.*";

  reports:
    # Emit report if at least one element starts with c or C
    "$(this.namespace):$(this.bundle).names has at least one element matching '$(anchored_regex)'"
      if => reglist(names, $(anchored_regex));

    "names: $(with)"
      with => join(", ", names);
}
R: default:main.names has at least one element matching '(?i)c.*'
R: names: Cody, Craig, Herman, Nick

parseyaml()

Demonstrate how to parse inline YAML and access different parts of the data structure.

bundle agent __main__
{
  vars:
    "some_yaml"
      data => parseyaml('
mykey: myvalue
domain:
  name: example.com
  subdomain: asdf
nesting:
  levelzero:
    levelone: levelone');

    "top_level_keys"
      slist => getindices(some_yaml);
    "nesting_keys"
      slist => getindices("some_yaml[nesting]");
    "nesting_levelzero_keys"
      slist => getindices("some_yaml[nesting][levelzero]");

  reports:
    "$(with)"
      with => storejson(some_yaml);
}
R: {
  "domain": {
    "name": "example.com",
    "subdomain": "asdf"
  },
  "mykey": "myvalue",
  "nesting": {
    "levelzero": {
      "levelone": "levelone"
    }
  }
}
Variable name                            Variable value                                               Meta tags                                Comment
default:main.nesting_keys                 {"levelzero"}                                               source=promise
default:main.nesting_levelzero_keys       {"levelone"}                                                source=promise
default:main.some_yaml                   {"domain":{"name":"example.com","subdomain":"asdf"},"mykey":"myvalue","nesting":{"levelzero":{"levelone":"levelone"}}} source=promise
default:main.top_level_keys               {"mykey","domain","nesting"}                                source=promise

Note: In the above example output, the cf-agent was executed with --show-evaluated-vars=main\. which outputs variables, their values, tags, and comments.