Feature Friday #1: ifelse()

Posted by Nick Anderson
March 15, 2024

Looking for a way to concisely set a variable conditionally? Have you heard of ifelse()?

In CFEngine, traditionally class expressions are used to constrain promises to different contexts. Setting a variable to different values based on context might look like this:

/tmp/feature-friday-1.cf
bundle agent __main__
{
  vars:
    "MyVariable" string => "My Default value";

    redhat_8|centos_8|rocky_8::
      "MyVariable" string => "My value for EL 8";

    ubuntu_22::
      "MyVariable" string => "My value for Ubuntu 22";

    any::
      "MyVariable"
        string => "My value on Friday",
        if => "Friday";

  reports:
    "It's $(sys.date) and I am running on $(sys.os_release[PRETTY_NAME])";

    "MyVariable is '$(MyVariable)'";
}
command
cf-agent --no-lock --log-level info --file /tmp/feature-friday-1.cf
output
R: It's Mon Mar 11 12:36:41 2024 and I am running on Ubuntu 22.04.4 LTS
R: MyVariable is 'My value for Ubuntu 22'

That’s great, lots of flexibility, but with an increasing number of options the policy can get quite long and it’s easier for a human interpreter to lose track of the context. The same can be achieved in a single statement using ifelse().

From the documentation for ifelse()

The ifelse() function is like a multi-level if-else statement. It was inspired by Oracle’s DECODE function. It must have an odd number of arguments (from 1 to N). The last argument is the default value, like the else clause in standard programming languages. Every pair of arguments before the last one are evaluated as a pair. If the first one evaluates true then the second one is returned, as if you had used the first one in a class expression. So the first item in the pair can be more than just a class name, it’s a whole context like Tuesday.linux.!verbose).

Using ifelse() the above example can be distilled into something like this:

/tmp/feature-friday-1-1.cf
bundle agent __main__
{
  vars:
    "MyVariable"
      string => ifelse(
        "Friday", "My value on Friday",
        "ubuntu_22", "My value for Ubuntu 22",
        "redhat_8|centos_8|rocky_8", "My value for EL8",
        "My Default value" );
  reports:
    "It's $(sys.date) and I am running on $(sys.os_release[PRETTY_NAME])";

    "MyVariable is '$(MyVariable)'";
}
command
cf-agent --no-lock --log-level info --file /tmp/feature-friday-1-1.cf
output
R: It's Mon Mar 11 12:36:57 2024 and I am running on Ubuntu 22.04.4 LTS
R: MyVariable is 'My value for Ubuntu 22'

Happy Friday! 🎉