This post was syndicated with permission from the original source.
CFEngine 3.12.0 introduced the augments key to the Augments file format. If you are not already familiar with Augments, check it out. It’s a very easy way to define classes and variables very early during agent execution, before policy.
The new augments key allows you to merge additional data in the augments format on top of the base augments. I However, there is, I think, still a simple way to accomplish this. This can provide a flexible way of providing different data to different sets of machines.
Since augments are loaded very early during policy evaluation.
Currently, only special
variables
like the sys
vars
can be used to select additional augments. The question arises …
How can I extend augments from custom policy?
The short answer is that you can’t, at least not directly, but there are a couple of things that you can do to achieve the same result.
Customize /etc/os-release
In 3.11.0 CFEngine began parsing /etc/os-release
during system
discovery into
sys.os_release.
I think that /etc/os-release
is perhaps a good place for you to encode
this DEVICE_TYPE
. It’s a simple key=value
format, and according to
the docs on freedesktop.org the file format may be extended by
vendors.
It’s highly recommended to prefix new fields with an OS specific name in
order to avoid name clashes.
So, let’s edit /etc/os-release
and define CUSTOM_DEVICE_TYPE
. This
is /etc/os-release
on my workstation, after I have edited it to add my
new key value.
NAME="Ubuntu"
VERSION="18.10 (Cosmic Cuttlefish)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.10"
VERSION_ID="18.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=cosmic
UBUNTU_CODENAME=cosmic
CUSTOM_DEVICE_TYPE=laptop
This way, when the agent initializes, it will have
sys.os_release[CUSTOM_DEVICE_TYPE]
available for use. This could be
set during initial provisioning, or of course CFEngine policy could
manage the extra file content.
Here is a small example:
def.json:
{
"vars":
{
"my_var": "I am RED"
},
"augments":
[
"$(sys.os_release[CUSTOM_DEVICE_TYPE]).json"
]
}
Here is my data file that is used when CUSTOM_DEVICE_TYPE
is set to
laptop
.
laptop.json:
{
"vars":
{
"my_var": "I am BLUE"
}
}
Here is the simple policy to illustrate the point.
promises.cf:
bundle agent main
{
reports:
"def.my_var is $(def.my_var)";
"My device type is $(sys.os_release[CUSTOM_DEVICE_TYPE])";
}
Output:
> $ cf-agent -KIf ./promises.cf
R: def.my_var is I am BLUE
R: My device type is laptop
In the above output, note that def.my_var
is BLUE
, what happens if
you change the CUSTOM_DEVICE_TYPE
?
Download device type specific data to a stable location
An alternate methodology to achieve similar results would be to reference a stable location, but use a files promise to ensure that the proper device type specific data is there.
For example, instead of shipping device_type1.json
and
devices_type2.json
as part of the policy, you can download it to
device.json
.
This copy_from files promise illustrates what I mean:
bundle agent device_type_data
{
files:
"/var/cfengine/inputs/device.json"
copy_from => remote_dcp( "/var/cfengine/data/devices/$(my_common.device_type).json",
$(sys.policy_hub) );
}
Then the base augments would look like this:
def.json:
{
"vars":
{
"my_var": "I am RED"
},
"augments":
[
"device.json"
]
}