Implement the A1 task from the IoT walking-skeleton roadmap:
- CRD (kube-derive): `iot.nationtech.io/v1alpha1/Deployment`, namespaced,
with `targetDevices`, `score {type, data}`, `rollout.strategy`, and a
status subresource carrying `observedScoreString`.
- Controller: `kube::runtime::Controller` + `finalizer` helper. On Apply,
writes `<device_id>.<deployment_name>` into NATS KV bucket
`desired-state` and patches `.status.observedScoreString` via
server-side apply. Skips KV write + status patch when the score is
unchanged to avoid reconcile-loop churn. On Cleanup, removes the
per-device keys before releasing the finalizer.
- CLI: `gen-crd` subcommand prints the CRD YAML from the Rust types;
`run` (default) starts the controller. `deploy/crd.yaml` is generated
by that subcommand — single source of truth, no drift.
- Deploy manifests: `deploy/operator.yaml` (Namespace, SA, ClusterRole,
ClusterRoleBinding, Deployment) and generated `deploy/crd.yaml`.
Agent fixes surfaced while aligning with the operator's key layout:
- Watch filter: was `starts_with("desired-state.<id>.")` on
`watch_all()`; bucket name is not a key prefix, so it never matched.
Now uses `bucket.watch("<id>.>")` with the NATS wildcard and handles
`Put`/`Delete`/`Purge` distinctly.
- Multi-server connect: was joining `nats.urls` with `","` into a single
malformed URL. Pass the `Vec<String>` to `ConnectOptions::connect`.
- `credentials.type` is now validated (rejects unknown discriminators)
so a v0.2 `zitadel` config doesn't silently fall back to shared creds.
Verification on feat/iot-walking-skeleton:
- cargo clippy --no-deps -D warnings: clean (agent + operator).
- cargo fmt --check: clean.
- x86_64 + aarch64 cross-compile: both build.
- podman module unit tests: pass.
21 lines
536 B
TOML
21 lines
536 B
TOML
[package]
|
|
name = "iot-operator-v0"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
rust-version = "1.85"
|
|
|
|
[dependencies]
|
|
kube = { workspace = true, features = ["runtime", "derive"] }
|
|
k8s-openapi.workspace = true
|
|
async-nats = { workspace = true }
|
|
serde.workspace = true
|
|
serde_json.workspace = true
|
|
serde_yaml.workspace = true
|
|
schemars = "0.8.22"
|
|
tokio.workspace = true
|
|
tracing = { workspace = true }
|
|
tracing-subscriber = { workspace = true }
|
|
anyhow.workspace = true
|
|
clap.workspace = true
|
|
futures-util = { workspace = true }
|
|
thiserror.workspace = true |