feat/iot-operator-helm-chart #272

Closed
johnride wants to merge 2 commits from feat/iot-operator-helm-chart into feat/iot-walking-skeleton

2 Commits

Author SHA1 Message Date
92150da12a feat(iot): label-selector targeting (replace target_devices with targetSelector)
All checks were successful
Run Check Script / check (pull_request) Successful in 2m23s
DeploymentSpec.target_devices (flat string list) is gone. In its
place, DeploymentSpec.target_selector is a minimal
LabelSelector-shaped struct (matchLabels only for now, matchExpressions
deferred until there's a real need). Devices publish a labels map
in every AgentStatus heartbeat; operator resolves the selector
against the current fleet snapshot on each reconcile + aggregator
tick.

No legacy shim — the CRD is v1alpha1 and not yet deployed in the wild.

Aggregator consequences:
  - controller and aggregator now share a StatusSnapshots map so
    selector resolution sees the same data on both sides.
  - unreported is dropped: a device that has never heartbeated is
    invisible to the selector machinery, so the field no longer
    has clean semantics. "device went dark" can come back as a
    staleness metric later if needed.
  - controller's MissingTargets error is gone: zero matches is a
    legitimate state (devices may not have joined yet). The
    controller logs and fast-requeues (15s/30s) so a just-joining
    device picks the deployment up without needing a
    cross-task subscription.

Agent + setup Score:
  - Agent config grows a [labels] section (BTreeMap); the flat
    [agent].group field is gone. group becomes just one label.
  - IotDeviceSetupConfig takes a BTreeMap<String, String> instead
    of a String group. TOML render iterates the BTreeMap (ordered)
    so idempotent change detection still works cleanly.

CLI-facing:
  - example_iot_apply_deployment: --target-device -> --to, accepts
    comma-separated key=value pairs.
  - example_iot_vm_setup: --group -> --labels, same grammar.
  - smoke-a4.sh: VM publishes group=$GROUP,device=$DEVICE_ID;
    deploys target --to device=$DEVICE_ID so single-device smoke
    behavior is preserved while exercising the selector path.

CRD regenerated via chart/regen-crd.sh. 7 contract tests + 6
operator tests pass.
2026-04-22 11:13:42 -04:00
99e661ce4d feat(iot-operator): helm chart + gen-chart-crd subcommand
All checks were successful
Run Check Script / check (pull_request) Successful in 2m44s
Chapter 3 scaffolding. Chart layout mirrors the CloudNativePG
convention after reviewing the CRD-in-chart vs CRD-as-hook
tradeoff: CRDs live inside templates/ (so helm upgrade re-applies
schema changes) with helm.sh/resource-policy: keep so
helm uninstall never deletes them. Chart publication target is
hub.nationtech.io.

CRD yaml is generated at chart-release time by a new
`iot-operator-v0 gen-chart-crd` subcommand reading
Deployment::crd() — the runtime install path remains the typed
Score; only the chart deliverable uses generated yaml. Wrapped
with the helm conditional + annotations by templates/crds.yaml
via .Files.Get so the generated yaml stays pure.

Install / upgrade / uninstall-preserves-CRD validated against a
scratch k3d cluster; the operator pod naturally stays pending
because the hub.nationtech.io image hasn't been published yet.
2026-04-21 23:33:06 -04:00