First slice of the device-commands.* protocol from fleet/requests_over_nats.md. Lands `Verb::Ping` plus the harness that proves it works against a real in-cluster agent. Wire types (`harmony-reconciler-contracts::commands`): - `Verb::Ping`, `CommandRequest`, `PingReply`, `ErrorReply`/`ErrorKind` - `device_command_subject` / `device_command_subscription` helpers - `X-Harmony-*` header constants Agent: - `command_server.rs` subscribes on `device-commands.<id>.>` and dispatches verbs; ping handler replies with `PingReply` - New `[agent].runtime_enabled` config flag (default true). When false, podman init + reconciler loop are skipped so the agent can run as a Pod on containerd-only k3d nodes; command server + heartbeat still run - `Dockerfile`: canonical multi-stage build for production registries Operator: - `commands::FleetCommandsClient` with typed `CommandError` (`DeviceOffline` via `no_responders`, `Timeout`, `BadReply`, `Nats`) E2E harness (`harmony-fleet-e2e`): - Library crate + integration test. `Stack::bring_up` provisions a fresh `e2e-<uuid8>` namespace in a shared `fleet-e2e` k3d cluster, deploys NATS (UserPass auth, JetStream on) + the agent Pod, returns a connected admin NATS client, and tears the namespace down on Drop - v1 ships `AuthMode::UserPass` only; the `Callout` variant is reserved on the public API for the follow-up PR that adds the mock OIDC fixture + NatsAuthCalloutScore deployment - Operator pod deployment is also follow-up — for ping the test process drives `FleetCommandsClient` directly against the cluster's NATS NodePort - `HARMONY_FLEET_E2E=1` gates the integration test so default `cargo test --workspace` runs don't depend on k3d/podman - Image build + sideload mirrors the `fleet_auth_callout` pattern: host `cargo build --release` → single-stage Dockerfile → `podman build` → `k3d image import`. ~12s warm bring-up, ~80s cold
50 lines
1.9 KiB
Docker
50 lines
1.9 KiB
Docker
# Multi-stage container build for harmony-fleet-agent.
|
|
#
|
|
# Build context is the workspace root (the agent's Cargo.toml has
|
|
# `path = "../../harmony"` deps that only resolve when the whole
|
|
# workspace is in scope). Invoke from the repo root:
|
|
#
|
|
# docker build -f fleet/harmony-fleet-agent/Dockerfile \
|
|
# -t hub.nationtech.io/harmony/harmony-fleet-agent:<tag> .
|
|
#
|
|
# Both stages are pinned to bookworm for a matched glibc — the
|
|
# rust:slim image follows Debian's latest stable, and a binary built
|
|
# against trixie's glibc 2.40 fails to start on a bookworm runtime
|
|
# (`GLIBC_2.39 not found`). This is the same lesson the operator
|
|
# Dockerfile encodes; keep the two pinned to the same Debian release.
|
|
#
|
|
# The e2e harness uses a faster host-build + single-stage path
|
|
# (`fleet/harmony-fleet-e2e/src/images.rs`); this Dockerfile is the
|
|
# canonical recipe for production registries.
|
|
|
|
FROM docker.io/rust:1.94-slim-bookworm AS builder
|
|
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
pkg-config \
|
|
ca-certificates \
|
|
libssl-dev \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
WORKDIR /app
|
|
COPY . .
|
|
|
|
RUN cargo build --release --locked -p harmony-fleet-agent
|
|
|
|
FROM docker.io/library/debian:bookworm-slim
|
|
|
|
# ca-certificates: outbound TLS to NATS over wss:// when the agent is
|
|
# configured against a TLS-terminated NATS endpoint. kube-rs is not
|
|
# used at runtime on the agent; async-nats uses rustls.
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
ca-certificates \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
COPY --from=builder /app/target/release/harmony-fleet-agent /usr/local/bin/harmony-fleet-agent
|
|
|
|
# Non-root runtime. 65532 is the `nonroot` UID convention from
|
|
# distroless. Pairs with `securityContext.runAsNonRoot: true` in
|
|
# whatever Pod spec the harness or production helm chart applies.
|
|
USER 65532:65532
|
|
|
|
ENTRYPOINT ["/usr/local/bin/harmony-fleet-agent"]
|