Feature Friday #24: Augments - host_specific.json

Posted by Nick Anderson
August 23, 2024

You probably know about the def.json Augments file. However, are you familiar with host_specific.json?

The def.json Augments file is read, if it’s adjacent to the policy entry. As such, this file is generally distributed as part of the policy set. Its settings apply to all hosts that receive and run the policy. The host_specific.json Augments file, is on the other hand loaded from the $(sys.workdir)/data/ directory. And it is expected to be independent from the policy.

host_specific.json has some notable differences from def.json:

  • $(sys.workdir/data/host_specific.json is loaded first, if it exists.
  • Variables and classes, when processed, will have a source=cmdb meta tag instead of source=augments_file.
  • Variables defined with the same name in host_specific.json have precedence over variables defined in def.json.
  • Variables are defined in the variables bundle scope of the data namespace instead of the def bundle of the default namespace by default.
  • Classes are defined in the data namespace instead of the default namespace by default.
  • Classes are defined without constraint, you can not specify a list of regular expressions or class expressions to determine if the class is defined.

Let’s take a look at some of this behavior:

First we have a def.json file with the following contents:

{
    "variables": {
        "var1": {
            "value": "default:def.var1 - Defined in def.json",
            "comment": "A similar, but different variable data:variables.var1 is defined in def.json."
        },
        "data:variables.var2": {
            "value": "data.variables.var2 - Defined in def.json",
            "comment": "This same variable is defined in host_specific.json with a different value."
        },
        "var3": {
            "value": "default:def.var3 - Defined in def.json",
            "comment": "This same variable is defined in host_specific.json with a different value."
        }
    },
    "classes": {
        "from_def_json_testing": {
            "class_expressions": [ "any::" ]
        }
    }
}

Next, we have a host_specific.json file with the following contents:

{
    "variables": {
        "var1": {
            "value": "data:variables.var1 - Defined in host_specific.json",
            "comment": "A similar, but different variable default:def.var1 is defined in def.json."
        },
        "var2": {
            "value": "data:variables.var2 - Defined in host_specific.json",
            "comment": "This same variable is defined in def.json with a different value."
        },
        "default:def.var3": {
            "value": "default:def.var3 - Defined in host_specific.json",
            "comment": "This same variable is defined in def.json with a different value."
        }
    },
    "classes": {
        "from_host_specific_data_testing": {
            "class_expressions": []
        }
    }
}

Looking at the variables and classes defined that end in testing we see that the namespace differs based on the source of the definition and that when the same variable, in this case var2 and var3, is defined in both def.json and host_specific.json the value from host_specific.json wins:

[root@hub data]# cf-promises --show-vars=var\\d$ --show-classes=testing$
Class name                                                   Meta tags                                Comment
data:from_host_specific_data_testing                         source=cmdb
from_def_json_testing                                        source=augments_file
Variable name                            Variable value                                               Meta tags                                Comment
data:variables.var1                      data:variables.var1 - Defined in host_specific.json          source=cmdb                              A similar, but different variable default:def.var1 is defined in def.json.
data:variables.var2                      data:variables.var2 - Defined in host_specific.json          source=cmdb                              This same variable is defined in def.json with a different value.
default:def.var1                         default:def.var1 - Defined in def.json                       source=augments_file                     A similar, but different variable data:variables.var1 is defined in def.json.
default:def.var3                         default:def.var3 - Defined in host_specific.json             source=cmdb                              This same variable is defined in def.json with a different value.

Remember, a variable defined by either def.json or host_specific.json may be overwritten by the policy. If you have a promise to define a variable but you want to respect the value set from Augments you need to adjust the promise to the appropriate constraints, perhaps using isvariable(), and/or getvariablemetatags().

In CFEngine Enterprise, this file is generated on the Hub, and stored in a directory named after the host’s public key digest. Furthermore, the file is copied into place by the update.cf policy. This provides an easy path for changing data related to a host without necessarily having access to or modifying the policy itself. While community agents can leverage the file, there is no prescription for managing or distributing the files. However, we encourage you to consider how you can leverage this functionality to better integrate with your own existing data sources.

Happy Friday! 🎉