Documentation
¶
Overview ¶
Package applycheck implements the apply-time safety gates: extracting host-resource references from a rendered Talos MachineConfig, evaluating disk selectors against a host snapshot, and diffing two MachineConfig snapshots by (kind, name) identity. The walker is YAML-only; no Talos machinery types leak through its surface, so the package can be exercised from contract tests without standing up a Talos client.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FormatChange ¶
FormatChange returns a one-line, grep-friendly representation of one Change. Used by the preflight hook to write the drift preview to stderr; tests pin the format.
Types ¶
type Change ¶
type Change struct {
ID DocID
Op ChangeOp
Fields []FieldChange
}
Change is one entry in the per-doc diff between two MachineConfig snapshots. Fields is non-empty only when Op == OpUpdate.
func Diff ¶
Diff parses current and desired MachineConfig bytes and returns every per-document difference. Equal documents are included as OpEqual so callers can render an unchanged section if they want; pass FilterChanged to drop them.
The diff is doc-structural, not byte-level: re-serializing either side with different key ordering or whitespace produces the same Diff output. Talos-mutated leaf fields (cert hashes etc.) currently land as OpUpdate entries with FieldChange path pinpointing what differs; an allowlist for Talos-mutated leaf fields will be layered on later.
func FilterChanged ¶
FilterChanged returns the subset of changes whose op is not OpEqual. Useful when the operator only wants to see drift, not pinned doc counts.
type ChangeOp ¶
type ChangeOp int
ChangeOp classifies a per-document diff between two MachineConfig snapshots.
const ( // OpAdd: doc present in desired, absent in current. OpAdd ChangeOp = iota // OpRemove: doc present in current, absent in desired (the leftover // class — eth1 lingering after migration to eth0). OpRemove // OpUpdate: doc present on both sides with field-level differences. OpUpdate // OpEqual: doc present on both sides, structurally identical. OpEqual )
type DiskInfo ¶
type DiskInfo struct {
DevPath string // /dev/sda
Model string
Serial string
WWID string
Modalias string
UUID string
Transport string // sata / nvme / scsi / mmc / virtio / ...
BusPath string
Size uint64 // bytes
Rotational bool
Readonly bool
CDROM bool
Symlinks []string
}
DiskInfo describes one host block device. Fields mirror Talos's block.Disk COSI resource shape verbatim — InstallDiskSelector.type (an enum: ssd/hdd/nvme/sd) is NOT a stored field but a derived predicate over Transport + Rotational, mirrored in matchSelector. CDROM and Readonly devices are excluded by Talos's install-disk resolution; matchSelector mirrors that exclusion.
Symlinks captures the alternate path forms Talos exposes for the same device (/dev/disk/by-id/wwn-…, /dev/disk/by-path/pci-…, /dev/disk/by-diskseq/…); RefKindDiskLiteral validation accepts any of these as equivalent to DevPath, because by-id paths are the recommended stable form for `machine.install.disk` and an operator using them is doing the right thing.
type DiskSelector ¶
type DiskSelector struct {
Size string `yaml:"size,omitempty"`
Name string `yaml:"name,omitempty"`
Model string `yaml:"model,omitempty"`
Serial string `yaml:"serial,omitempty"`
Modalias string `yaml:"modalias,omitempty"`
UUID string `yaml:"uuid,omitempty"`
WWID string `yaml:"wwid,omitempty"`
Type string `yaml:"type,omitempty"`
BusPath string `yaml:"busPath,omitempty"`
}
DiskSelector mirrors the Talos v1alpha1 InstallDiskSelector schema (also used by UserVolumeConfig provisioning). Fields are left as raw strings so the walker stays YAML-only; the evaluator interprets each.
func (*DiskSelector) IsZero ¶
func (s *DiskSelector) IsZero() bool
IsZero reports whether the selector has no fields set; the walker uses this to avoid emitting empty selector refs.
type DocID ¶
DocID is the structural identity used to pair up documents across the current/desired snapshots. v1.12 multi-doc keys by (kind, name). v1.11 nested form is collapsed into a synthetic DocID{Kind: "MachineConfig", Name: ""} so the root config doc participates in the diff.
type FieldChange ¶
FieldChange describes a single leaf-level difference between matched documents. Only populated for ChangeOp.OpUpdate. Path is the YAML dotted accessor inside the document.
HasOld / HasNew distinguish "field missing on this side" from "field present with literal nil/null value": a YAML leaf with value `~` (or `null`) is a legitimate value, not a missing field, and the diff has to be able to render it differently.
type Finding ¶
Finding is one validation result for one Ref. ValidateRefs returns one Finding per Ref; clean refs produce no findings.
func ValidateRefs ¶
func ValidateRefs(refs []Ref, snapshot HostSnapshot) []Finding
ValidateRefs checks each Ref against the host snapshot:
- RefKindLink: name must match an entry in snapshot.Links exactly. Mismatch is a blocker.
- RefKindDiskLiteral: name must equal a DiskInfo.DevPath in snapshot.Disks. Mismatch is a blocker.
- RefKindDiskSelector: selector must match >= 1 disk. Zero matches is a blocker. Multiple matches is a warning (install picks the first match — operators usually want to narrow the selector).
ValidateRefs collects every finding in a single pass; callers can show them all at once instead of one-at-a-time.
func WalkNetAddrFindings ¶
WalkNetAddrFindings parses the rendered MachineConfig bytes and returns a Finding for every malformed net-addr field in the three kinds registered above. Pure syntactic — no host snapshot required — so the walker runs in Phase 1 alongside (not inside) the Ref-based walker.
Empty input and YAML decode of a nil document are no-ops; an actual YAML parse error is wrapped and returned. Unknown kinds are ignored so future Talos kinds and vendor extensions do not trip the gate.
type HostSnapshot ¶
HostSnapshot captures the host-side resource inventory the validator compares declared refs against. Fields are populated from COSI `links` and `disks` reads at apply time; tests construct fakes directly.
type Ref ¶
type Ref struct {
Kind RefKind
Name string // populated for RefKindLink and RefKindDiskLiteral
Selector DiskSelector // populated for RefKindDiskSelector (zero value otherwise)
Source string // human-readable JSONPath pointing at the offending field
}
Ref is a host-side reference the walker found in the rendered MachineConfig.
func WalkRefs ¶
WalkRefs parses the rendered MachineConfig bytes and returns every host-resource reference it contains. Both the v1.11 nested machine.network.interfaces[] form and the v1.12 multi-doc form (LinkConfig / BondConfig / VLANConfig / BridgeConfig / Layer2VIPConfig plus UserVolumeConfig.provisioning.diskSelector) are supported. Unknown documents are ignored.
type RefKind ¶
type RefKind int
RefKind classifies a host-resource reference extracted from a rendered MachineConfig.
const ( // RefKindLink is a host network link by name (eth0, bond0, vlan tag, ...). RefKindLink RefKind = iota // RefKindDiskLiteral is an install/extra disk identified by a literal // device path (machine.install.disk: /dev/sda). RefKindDiskLiteral // RefKindDiskSelector is an install/user-volume disk identified by a // selector (size, model, serial, wwid, modalias, type, busPath). RefKindDiskSelector )