Documentation
¶
Overview ¶
Package override implements user-supplied customization of the Deployments and DaemonSets the operator generates.
Security ¶
Write access to the overrides ConfigMap is equivalent to root on every node in every affected Site, and therefore to cluster-admin. The workloads being patched already run with hostNetwork, hostPID, privileged containers and hostPath mounts of the host root, so changing a container image, its arguments, its environment, or adding a sidecar is arbitrary code execution on every node. Rejecting privileged: true or new hostPath volumes would achieve nothing against pods already in that state.
The restrictions in this package are therefore integrity controls, not a privilege boundary. They stop an authorized operator from accidentally severing the operator's ability to reconcile a workload: detaching it from its selector, its ServiceAccount, or its per-Site node affinity.
Two exceptions are genuine security controls, because they escape the workload rather than merely damaging it: the group, version and kind of the applied object, since the operator holds escalate and bind on ClusterRoleBindings; and serviceAccountName, since retargeting it borrows another identity's API permissions.
Index ¶
- Constants
- func AnyKeyLevel(problems []Problem) bool
- func ComponentKinds(component string) []string
- func Parse(data map[string]string) ([]SourcedEntry, []Problem, error)
- func PermittedPaths() []string
- func ProblemsErr(problems []Problem) error
- func ProblemsError(problems []Problem) error
- func ProtectedPaths() []string
- func UnmatchedSites(entries []SourcedEntry, knownSites []string) []string
- func ValidateErr(entries []SourcedEntry) error
- type Document
- type Entry
- type Problem
- type Report
- type Resolution
- type Source
- type SourcedEntry
- type Target
- type WithheldOperation
- type WorkloadResult
Constants ¶
const ( // HashAnnotation carries the hash of the contributor set merged into this // object. The matching desired hash lives in Site status rather than here, // because writing it would mean touching an object the operator may have // just decided not to apply. HashAnnotation = ReservedPrefix + "override-hash" // SourceAnnotation names the ConfigMap keys and entry indices that shaped // this object. SourceAnnotation = ReservedPrefix + "override-source" // VersionDriftAnnotation is present only when an override changed a // container image, breaking version lockstep with the operator. VersionDriftAnnotation = ReservedPrefix + "version-drift" )
Annotation keys stamped on an overridden workload.
const APIVersion = "overrides.unbounded-cloud.io/v1alpha1"
APIVersion is the only document version this release accepts. It gates the schema so the format can evolve without silently reinterpreting documents written against an older shape.
const ConfigMapName = "unbounded-component-overrides"
ConfigMapName is the ConfigMap the operator reads overrides from.
The operator only ever reads it: it is never created, never seeded and never written, so an absent ConfigMap unambiguously means "no overrides" rather than "not yet initialized".
const ReservedPrefix = unbounded.ReservedPrefix
ReservedPrefix marks labels and annotations the operator owns. They carry config hashes, Site scoping and override visibility, so a patch that wrote them could hide the fact that an override is in effect.
The definition lives in internal/unbounded so the workload watch predicates can share it without an import cycle.
Variables ¶
This section is empty.
Functions ¶
func AnyKeyLevel ¶
AnyKeyLevel reports whether any problem covers a whole key, which is what decides between withholding the workloads a set of entries names and withholding every workload an override could reach.
func ComponentKinds ¶
ComponentKinds returns the kinds a component emits, for the CLI, the documentation and cross-package tests to read rather than restate.
func Parse ¶
func Parse(data map[string]string) ([]SourcedEntry, []Problem, error)
Parse reads every key in a ConfigMap payload as an independent overrides document and returns the entries in deterministic order: sorted ConfigMap key, then position within that key's document.
Keys are independent, and a key that fails does not stop the others being read. That is the whole reason the format is one document per key: splitting by concern or by team is only useful if a mistake in one key is contained to it. The returned problems say which key or which entry failed, so the caller can withhold the workloads that are actually in doubt rather than all of them.
The returned error is reserved for a failure of the payload as a whole, where nothing can be read and no attribution is possible.
Parsing is strict by design. The apiVersion gate is only meaningful if the document that passes it is the document the user wrote, so anything ambiguous is rejected rather than interpreted:
- unknown fields, at every level including inside the patch
- duplicate keys, which most decoders silently resolve to the last value
- more than one YAML document per key, and any trailing content
- YAML merge keys, which would hide content from validation
An empty or whitespace-only value is ignored rather than rejected, because `kubectl create configmap --from-file` on an empty file is a plausible accident rather than an intent.
func PermittedPaths ¶
func PermittedPaths() []string
PermittedPaths returns the permitted paths in sorted order, marking subtrees. It exists so the CLI and documentation can render the surface rather than restating it and drifting.
func ProblemsErr ¶
ProblemsErr joins the underlying errors without the document framing, for callers that want to wrap them in their own message.
func ProblemsError ¶
ProblemsError joins problems into one error, in the shape a user reading a document sees: every problem, sorted, one per line.
Reporting every problem rather than only the first is deliberate. A user fixing a document should see the whole list, not discover the next one on each apply.
func ProtectedPaths ¶
func ProtectedPaths() []string
ProtectedPaths returns the protected paths in sorted order.
func UnmatchedSites ¶
func UnmatchedSites(entries []SourcedEntry, knownSites []string) []string
UnmatchedSites returns the Site names entries select that do not exist, sorted and deduplicated.
It is exported because the CLI reports the same thing before a document is applied, and a second implementation of Site-selector matching is a second place for the semantics to drift.
These are reported rather than fatal. A document may legitimately be written before its Site exists, and deleting a Site must not retroactively invalidate an unrelated override.
func ValidateErr ¶
func ValidateErr(entries []SourcedEntry) error
ValidateErr reports validation as a single error, for callers that only need a yes or no. Attribution is discarded, so anything deciding what to withhold must use Validate.
Types ¶
type Document ¶
Document is one overrides document. Each key in the ConfigMap holds exactly one of these.
type Entry ¶
type Entry struct {
// Component names the component that generates the workload: net, machina,
// gantry or metalman.
Component string `yaml:"component"`
// Kind is Deployment or DaemonSet. Together with Component it identifies
// every workload the operator emits today, so users never have to
// reconstruct a derived per-Site name.
Kind string `yaml:"kind"`
// Sites selects which Sites to affect, for per-Site components only.
//
// A nil slice means every Site. An explicitly empty slice is a validation
// error, because it is far more likely to be a mistake than an intent to
// match nothing. Naming a Site that does not exist is inert and reported,
// not fatal: a document may legitimately be written before its Site.
Sites []string `yaml:"sites,omitempty"`
// AddContainers and AddInitContainers name containers this entry intends to
// create rather than modify.
//
// Strategic merge cannot tell a sidecar from a typo: both are "this name is
// not present", and merging by name silently creates a container either
// way. Entries are therefore modify-only unless a name is listed here, so a
// patch meaning to raise a limit on machina-controller but spelling it
// machina-contoller fails instead of adding an image-less container.
AddContainers []string `yaml:"addContainers,omitempty"`
AddInitContainers []string `yaml:"addInitContainers,omitempty"`
// ExtraArgs appends arguments to a container, keyed by container name.
//
// It exists because args and command carry no patchMergeKey, so strategic
// merge replaces them wholesale: a patch adding one flag drops every
// operator-injected flag and will not receive new ones on upgrade. metalman
// makes that concrete, since its args begin with the serve-pxe subcommand.
ExtraArgs map[string][]string `yaml:"extraArgs,omitempty"`
// Patch is a strategic merge patch applied to the whole workload object, so
// metadata, spec.replicas and the pod template are all reachable through
// one field.
Patch map[string]any `yaml:"patch,omitempty"`
}
Entry targets one workload, or one workload per Site, and describes what to change about it.
type Problem ¶
type Problem struct {
// Key is the ConfigMap key the problem was found in.
Key string
// Source is set for an entry-level problem and nil for a key-level one.
Source *Source
// Component, Kind and Sites describe what the offending entry could have
// targeted, and are only meaningful for an entry-level problem.
//
// An empty Component means the entry could never resolve to a workload at
// all, because resolution matches on component. An empty Kind means every
// kind the component emits. Nil Sites means every Site.
Component string
Kind string
Sites []string
Err error
}
Problem is something wrong with the overrides payload, carrying enough information to work out which workloads it puts in doubt.
The distinction it exists to draw is between a failure whose blast radius is known and one whose is not. An entry that fails validation names the component, kind and Sites it would have targeted, so only those workloads need be withheld; every other workload can reconcile with its own overrides. A key that fails to parse names nothing, because the entries could not be read at all, so every workload an override could reach is in doubt.
Conflating the two is what made a mis-indented line in one ConfigMap key withhold every workload of every component on every Site, and discard the entries in the other keys while it was at it.
func Validate ¶
func Validate(entries []SourcedEntry) []Problem
Validate checks every entry against the schema and the allowlist.
It is a pure function of the parsed document: no cluster state is consulted, so it can run before anything is written and can run offline in the CLI. It deliberately does not resolve entries against real workloads, because whether a container or mountPath exists depends on the workload the running operator renders, and a client cannot answer that correctly under version skew.
Every problem found is reported, rather than only the first, so a user fixing a document sees the whole list. Each is attributed to the entry that caused it and carries what that entry would have targeted, so a caller can withhold those workloads alone rather than every workload an override could reach.
type Report ¶
type Report struct {
// Workloads describes each workload an override resolved to, whether or not
// it succeeded.
Workloads []WorkloadResult
// UnmatchedSites names Sites an entry selected that do not exist. Inert and
// reported, never fatal.
UnmatchedSites []string
// InertEntries are entries that matched no workload in this pass.
InertEntries []Source
// Withheld names the operations removed from the plan because their
// overrides could not be used, attributed to the component and Site that
// planned them.
//
// The running workload is deliberately left as it is, but the component
// did not write what it planned, so it must not report itself reconciled.
// Without this the object was simply absent from the plan and nothing
// downstream could tell that from "never planned".
Withheld []WithheldOperation
}
Report is the outcome of applying overrides to a plan.
func Apply ¶
func Apply(plan *component.Plan, entries []SourcedEntry, knownSites []string) Report
Apply merges validated entries into the overridable operations of a plan.
Failures are scoped to the workload that caused them. A resolution failure, a conflict between contributors, or a merge error drops that operation from the plan entirely rather than applying it un-overridden: the running workload keeps whatever it already has, which is recoverable, where reverting it to defaults would rewrite running infrastructure over a user's mistake.
Entries must already have passed Validate. Apply does the half of validation that needs the rendered workload, which a client cannot do correctly under version skew.
type Resolution ¶
type Resolution struct {
// Targets are the workloads at least one entry resolves to.
Targets []Target
// UnmatchedSites names Sites an entry selected that do not exist.
//
// These are reported rather than fatal. A document may legitimately be
// written before its Site exists, and deleting a Site must not retroactively
// invalidate an unrelated override.
UnmatchedSites []string
// InertEntries are entries that resolved to no workload at all, so a user
// can tell "applied nothing" from "matched nothing".
InertEntries []Source
}
Resolution is the outcome of matching entries against a plan.
func Resolve ¶
func Resolve(plan *component.Plan, entries []SourcedEntry, knownSites []string) *Resolution
Resolve matches entries against the overridable operations in a plan.
Only operations a component marked Overridable are candidates, which is what confines overrides to the Deployments and DaemonSets the operator generates. Entries are matched on component and kind, and for per-Site components on the Site selector; an absent selector matches every Site.
type Source ¶
type Source struct {
// Key is the ConfigMap data key the document was read from.
Key string
// Index is the entry's position in that document's overrides list.
Index int
}
Source identifies where an entry came from, so every error and every applied override can name its origin precisely.
type SourcedEntry ¶
SourcedEntry is an entry paired with where it came from.
type Target ¶
type Target struct {
// Index is the position of the operation within the plan.
Index int
// Ref identifies the workload, for messages and status.
Ref component.ObjectRef
// Site is the Site the workload belongs to, empty for cluster singletons.
// Status is published per Site, so results have to carry it.
Site string
// Contributors are the entries resolving to this workload, ordered by
// sorted ConfigMap key then position within that key's document.
Contributors []SourcedEntry
}
Target is one workload an override applies to, with the entries that contribute to it in deterministic order.
type WithheldOperation ¶
WithheldOperation is one operation removed from a plan before execution.
type WorkloadResult ¶
type WorkloadResult struct {
Ref component.ObjectRef
// Site is the Site the workload belongs to, empty for cluster singletons.
Site string
// Hash is the contributor hash merged into the object.
Hash string
// Sources names the contributing entries.
Sources []Source
// VersionDrift is set when the override changed a container image.
VersionDrift string
// Err is set when this workload could not be overridden. The operation is
// dropped from the plan rather than applied un-overridden, so the running
// workload is left as it is.
Err error
}
WorkloadResult describes what happened to one overridden workload.