Labels and matchers¶
Labels classify a host. Matchers decide which layers apply to it. Between them they are the only mechanism by which configuration reaches a machine, so there is no inheritance hierarchy, no include directive, and no host list to maintain alongside them.
Labels are declared in the repository¶
A host's labels come from its Host document and nowhere else.
datum: v1alpha1
type: Host
name: web-001
labels:
environment: production
site: london
role: web
architecture: amd64
Labels are strings on both sides. There are no typed values, no lists as values, and no nesting, because a label whose value needs structure is a sign that the structure belongs in a resource rather than in classification.
Security consideration
A host never supplies its own labels. Reading classification from the machine
would let a compromised host relabel itself as environment: production and
receive configuration intended for production, which is why labels come from
the repository and a host only proves which machine it is.
Reserved labels¶
The resolver injects one label derived from the Host document.
| Label | Value |
|---|---|
datum/host |
The host's name |
This exists so that host-specific configuration needs no special mechanism. A layer targeting one machine is an ordinary layer with an ordinary matcher.
The datum/ prefix is reserved. A Host document setting a label under it is
an error, so that injected values cannot be shadowed.
Open question
Facts observed on the host, such as the distribution and version reported by
/etc/os-release, are not available as labels. Making them available would
let a layer target Debian hosts without anybody declaring which hosts run
Debian, and it would also mean desired state could no longer be resolved
without reaching the machine. The current position is that a host needing
distribution-specific treatment carries a declared label saying so, and that
provider selection handles the rest.
Matcher semantics¶
A matcher is a match block with five optional forms, each testing labels a
different way.
match:
labels:
role: web
environment: production
oneOf:
site: [london, frankfurt]
noneOf:
tier: [legacy]
has:
- monitoring
missing:
- decommissioned
| Form | Matches when |
|---|---|
labels |
Each named label is present with exactly that value. |
oneOf |
Each named label is present with one of the listed values. |
noneOf |
Each named label is absent, or present with a value not listed. |
has |
Each named label is present, whatever its value. |
missing |
Each named label is absent. |
Every form present has to hold, and every term within a form has to hold, so a
matcher is one large conjunction. Most layers need only labels, and the other
four exist for cases that would otherwise need several near-identical layers.
There is no way to express alternation between whole matchers. A layer that
should apply to web hosts or to cache hosts uses oneOf with both values
instead of two matchers combined with an or.
That omission is deliberate. Matchers that can be nested arbitrarily become expressions to debug, and the cases that appear to need them are usually better served by giving the hosts a label describing what they have in common.
The empty matcher¶
A layer with no match block matches every host in the fleet.
Matching everything has to be written out, instead of happening by omission somewhere else, which is why resource documents are required to sit under a layer. The one place an empty matcher is normal is a fleet-wide base layer, and the base layer is exactly the case where applying to everything is the intent.
What matchers do not do¶
Matchers choose layers. They do not choose resources within a layer, filter fields, or apply conditionally at reconciliation time.
A resource that should only exist on some of the hosts a layer matches belongs in a different layer with a narrower matcher. Pushing conditions down into resources would put the decision about whether a resource applies into two places at once, and answering why a resource reached a host would then mean reading both.
Matching is evaluated once per pass¶
The set of layers applying to a host is determined during resolution, before the host is read and before any plan exists. Nothing later in the pipeline can change it.
That ordering is what makes the question of which layers applied answerable from the repository alone, and it means a change in a host's observed state never changes which configuration applies to it.