Targets Overview
Perhaps the most important goal of a Factory is to deliver immutable software updates to devices. This is achieved by using the The Update Framework (TUF). The central piece to TUF is the notion of a Target. A Target defines a cryptographically verifiable description of the software a device should run.
For a simplified example:
"raspberrypi3-64-lmp-42" : {
"hashes" : {"sha256" : "0xdeadbeef"},
"custom" : {
"version" : "42"
"docker_compose_apps" : {
"shellhttpd" : {
"uri" : "hub.foundries.io/andy-corp/shellhttpd@sha256:0xdeadbeef"
}
},
"hardwareIds" : ["raspberrypi3-64"],
"tags" : ["master"],
}
}
This Target specifies some important bits of information:
- This is build
42
- The immutable OSTree hash of the base image is
0xdeadbeef
- The Compose app,
shellhttpd
, is part of the Target.
The Target is the goal. Developers push changes to Git so as to build a Target. Devices look to the OTA system for the latest Target they should run. Operators oversee the intersection of these goals.
The point of a Factory is to create Targets.
The interesting thing about a Factory, is how with a git push
, you can make this all happen.
This is where you can start to visualize a Factory.
The Factory Definition file instructs CI what to build when changes hit source.foundries.io
.
The default factory-config.yml
tells CI:
- If an LmP change (
lmp-manifest.git
ormeta-subscriber-overrides.git
) is made to the default(i.e., “main”) branch, do a platform build and tag it with “default”.- If a container change (
containers.git
) is made to the default branch, do a container build and tag it with “default”.
However, this can grow much more complex.
CI must also take into account that Targets require both an OSTree image and Compose apps. This turns out to be a fairly simple calculation. CI looks at the previous Target for a given tag. In the case of a platform build, it will copy the Compose apps defined for it. In the case of a container build, it will copy the OSTree hash. In this way, there are not “container targets” and “platform targets”; there are only Targets.
Visualizing a Factory
Start with factory-config.yml
.
The tagging
and ref_options
stanzas describe the intent.
Then take a high-level view of the fleet:
$ fioctl status
Total number of devices: 2
TAG DEVICES UP TO DATE ONLINE
--- ------- ---------- ------
master 2 1 1
## Tag: master
TARGET DEVICES DETAILS
------ ------- -------
46 1 `fioctl targets show 46`
112 1 `fioctl targets show 112`
This will show all Targets active in the field. Now take a look at a specific Target:
$ fioctl targets show 46
CI: https://ci.foundries.io/projects/andy-corp/lmp/builds/46/
## Target: intel-corei7-64-lmp-46-master
Created: 2022-03-22T15:23:03Z
Tags: master
OSTree Hash: 8f8a74e0fac31c1c3f43d737246e7320d453c377c6724c398a506b857d224e55
Source:
https://source.foundries.io/factories/andy-corp/lmp-manifest.git/commit/?id=aa36b74580d64f8754d42817e534004c05f80cf7
https://source.foundries.io/factories/andy-corp/meta-subscriber-overrides.git/commit/?id=d56ae6a677316bf1c8544cf9228632a59fe3d991
https://source.foundries.io/factories/andy-corp/containers.git/commit/?id=749aac2cc30c572769b702498373505dac1da7ed
APP HASH
--- ----
shellhttpd sha256:e4a7b3a31c0126d28aaf75e1b8b6e83c7afd160b110267530b8572ce192160da
This command gives the exact details of the Target, including the CI change that produced it.