CFengine3 tip: “Redefinition of a constant variable”

The CFengine3 learning curve is steep and slippery.

Let’s say you want to define a default policy for your hosts, and a more specialized policy for certain hosts. Your implementation might look like this:

  # CFengine3 Test Policy
  body common control
  {
    bundlesequence => { "test" };
  }

  bundle agent test
  {
  vars:

    "base_list" slist => { "one", "two", "three" },
                comment => "All systems can count one-two-three";

  redhat::
    "list" slist => { "@(base_list)", "four" },
           comment => "Red Hat breed systems can count to four.";

  myhost::
    "list" slist => { "zero", "@(base_list)", "four" },
           comment => "My host is special, it starts counting from zero.";

  reports:

  Yr2010::
    "Counting: $(list)";
  }

If you run the above example, you will see error messages like this:

  !! Redefinition of a constant variable "list"

The default behavior for variables is to behave like constants, i.e. to not allow re-definition of that same variable (see CFengine 3.0.5 Reference Guide, section 6.1.7).

If you set the proper “overridable” policy on all instances of the “list” variable, the error messages go away:

  # Test policy
  body common control
  {
    bundlesequence => { "test" };
  }

  bundle agent test
  {
  vars:

    "base_list" slist => { "one", "two", "three" },
                comment => "All systems can count one-two-three";

  redhat::
    "list" slist => { "@(base_list)", "four" },
           comment => "Red Hat breed systems can count to four. Make this overridable.",
           policy => "overridable";

  myhost::
    "list" slist => { "zero", "@(base_list)", "four" },
           comment => "On this host, we start counting from zero.",
           policy => "overridable";

  reports:

  Yr2010::
    "Counting: $(list)";
}