FoundriesFactory Device Groups

At the dawn of 2021 Foundries.io delivered a new simple yet powerful way to manage your FoundriesFactory devices. We call it "device groups" and as a name suggests it basically allows to categorize devices belonging to a single Factory into user defined groups.

Trivia

Device Groups in essence solve two major tasks. The first one is quite naive - it allows a user to assign a group (aka a label) to a device. However, we at Foundries.io wanted to give this intuitive mechanism more power. Thus, the second task it solves is an ability to provision a specific configuration to a dedicated group of devices, complementing a previously existing ability to define factory-wide or per-device configurations.

Defining groups

Device Groups can be defined in your Factory using a newly added set of fioctl commands: fioctl config device-group [command]. For example, fioctl config device-group create canary "Canary tests" will create a new Device Group named "canary", that can later be used in other commands.

A device can be added into an existing group using a new fioctl device config group <device-name> <group-name> command; and it can be removed from a group using a fioctl device config group <device-name> --unset command.

A natural limitation of Device Groups is that a device can only belong to at most one group, that makes a lot of sense when thinking about the next topic.

Managing per-Group Configuration

As you might already know from a previous post our fioconfig tool allows to securely provision a device configuration; and there is a set of commands in Fioctl to manage a Factory-wide (fioctl config) or a per-device (fioctl device config) configuration.

Now, a new Device Groups feature adds one more element into this equation: an ability to define a per-Group configuration using fioctl config -g <group> set of commands. This configuration overrides Factory-wide and is overridden by a per-device one.

As a practical example lets assume that a user has configured a factory-wide updates config like this: fioctl config updates --tags=master. Now, lets assume that a user wants canary builds to accept updates from development branch which were specially tagged as "canary". Re-using a "canary" group from above this can be done using this simple command: fioctl config updates -g canary --tags=canary. Furthermore, if there is a single device "test-device" which a user wants to permanently switch to update to development builds - that can be done like this: fioctl device config updates test-device --tags=devel.

An above simple 3-level configuration hierarchy allows our Foundries.io users to build quite powerful configuration management patterns solving contemporary business needs.

Pro Tips

How configuration layering works

Lets try to answer this question: how does Fioconfig know how to merge together a factory-wide, a per-group, and a per-device configuration?

Internally, we store all configuration as so-called files. Those files' names can be set explicitly in one case e.g. as a parameter to a fioctl config set <filename>=<config value> command, or might be specified implicitly in the other case e.g. a fioctl config updates --tags=master internally creates a file named "z-50-fioctl.toml". Now it should be apparent that we used the most simple yet the most reliable form of a configurations merge algorithm: rewrite files in higher-level configs with files in lower-level configs.

For example, lets assume the following:

  • There are "foo.cfg", "bar.cfg" and "baz.cfg" files defined Factory-wide;
  • There are "bar.cfg" and "baz.cfg" files defined for a Device Group "canary";
  • There are "baz.cfg" and "dev.cfg" files defined for a device "canary-dev";

Now, when a device "canary-dev" is added into a Device Group "canary" - it will receive the following configuration files:

  • "foo.cfg" from a Factory-wide configuration;
  • "bar.cfg" from a "canary" Device Group configuration;
  • "baz.cfg" and "dev.cfg" from a "canary-dev" device configuration;

As one can see, it's indeed a simple overlay where lower-level config files overwrite higher-level config files where file names match.

How to remove a configuration

Now, another interesting question is this: what happens if I remove specific config files from per-group or per-device configuration(s)?

Well, an answer might be unexpected albeit logical: in this case a configuration for this specific file falls back to a Factory-wide or per-Group configuration respectively (i.e. taken from higher layers). If ones intention is to really override e.g. a Factory-wide config file at per-Group or per-device level - that file must be specified per-Group (or per-device). And if one wants to "remove" that file - need to supply an empty file instead, because a literal file removal means "fall back to default" as described above.

Future

In the next blog post I will talk about other interesting use cases for Device Groups we envision here at Foundries.io.

Keep up to date with Foundries.io