pub fn kube_spec(value: &Value) -> Option<&Mapping>Expand description
Read the top-level spec: sub-mapping on a K8s custom resource YAML
document as Option<&serde_yaml::Mapping> — the sub-mapping-arity
accessor peer on the sibling top-level spec: sub-block, structural
mirror of the recently-lifted kube_metadata_labels (f3d9fcd) on
the sub-metadata.labels sub-block. Where kube_metadata_labels
closes the two-hop metadata → labels → as_mapping readback on the
per-CR labels-selector sub-mapping, this closes the one-hop
spec → as_mapping readback on the per-CR body sub-mapping every
K8s API-machinery CustomResource pins as the sibling load-bearing
per-CR sub-block. Body folds the two-hop
.get(KUBE_KEY_SPEC).and_then(|s| s.as_mapping()) chain onto one
substrate-primitive method call the caller reads as intent
(kube_spec(<value>) — “read this K8s CR’s spec: sub-mapping”).
Returns None on either short-circuit arm the underlying inline
chain closes: the outer spec: block is absent (a legally-omitted
per-CR body sub-block on List-shaped documents or otherwise
spec-less CRs), or the spec: value is present but carries a non-
Mapping YAML type (a schema-invalid body shape per the K8s API-
machinery contract that pins the per-CR body sub-block as a
Mapping, but tolerated here as None so the readback stays a total
function). The returned &Mapping borrows into the input Value
— the caller decides whether to enumerate (for (k, v) in spec { ... }), further-navigate (spec.get(CILIUM_KEY_INGRESS)),
or clone.
Structural peer to sibling kube_metadata_labels on the sub-
mapping-arity readback axis: both accessors gate on Mapping shape
(folding the trailing .as_mapping() closure onto the helper),
pin their respective canonical sub-block axis-key inside the
helper (KUBE_KEY_LABELS for kube_metadata_labels,
KUBE_KEY_SPEC for this accessor), and return
Option<&serde_yaml::Mapping> — together they bracket the two
canonical top-level sub-mapping readbacks every K8s CR document
the emit-side kube_resource_skeleton renders carries
(metadata.labels for the per-CR selector surface via the sibling
sub-metadata: accessor’s composition, spec for the per-CR body
surface via this accessor’s direct navigation).
The canonical shape ≥30 test-side per-CR readback sites across
caixa-mesh previously carried inline as the two-token
composition
value
.get(KUBE_KEY_SPEC)
.and_then(|s| s.get(<SUB_FIELD>))
...around a one-token semantic payload (the <SUB_FIELD> axis-key —
CILIUM_KEY_INGRESS on the per-CNP ingress-rules readback,
GATEWAY_API_KEY_PARENT_REFS on the per-HTTPRoute parent-Gateway
readback, GATEWAY_API_KEY_LISTENERS on the per-Gateway
listener-set readback). After this lift, every routed consumer
folds the outer navigation onto kube_spec(value).and_then(|s| s.get(<SUB_FIELD>)) — the two-hop spec → as_mapping outer walk
happens once inside the helper, and the trailing Mapping::get
stays composition-symmetric with the sibling Value::get shape the
unlifted chain carried (Mapping::get(&str) and
Value::get(&str) both return Option<&Value> in serde_yaml 0.9,
so the fold is a drop-in for every routed callback body).
Every future per-CR body-sub-block readback (the future
per-:politicas CiliumClusterwideEnvoyConfig emitter’s per-
policy spec.rules[] readback, MESH-COMPOSITION §III.2 #3; the
app-operator’s per-Aplicacao mesh.pleme.io/v1alpha1/Aplicacao
CR materializer’s spec.membros/spec.contratos navigation,
§III.2 #5; the future caixa-otel per-Servico OTel-Collector CR’s
spec.receivers readback; every future test-side spec.* probe
the M3.x + M4 renderer set adds) reaches through this one accessor
by construction — no per-consumer two-hop chain re-inline, no
per-consumer KUBE_KEY_SPEC axis-key drift, no coordinated rewrite
across every per-CR body-sub-block readback on a future K8s API-
machinery rebrand of the top-level spec: axis (a schema-migration
to a wrapped specV2: sub-block under a versioned CRD evolution
axis, a per-tenant migration to a nested spec.tenant.* scoped
sub-namespace under Server-Side-Apply’s per-field ownership
annotations).