Skip to content

Commit ca9c69c

Browse files
committed
Make sure binary for the spotSchedule controller is added to 5-spot image
Signed-off-by: Erick Bourgeois <erick@jeb.ca>
1 parent ebf6e38 commit ca9c69c

12 files changed

Lines changed: 144 additions & 12 deletions

File tree

.claude/CHANGELOG.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,56 @@ The format is based on the regulated environment requirements:
99

1010
---
1111

12+
## [2026-06-23 11:45] - Ship the spot-schedule provider binaries in the image (ADR 0009 providers were unrunnable)
13+
14+
**Author:** Erick Bourgeois
15+
16+
### Changed
17+
- `Cargo.toml`: added explicit `[[bin]]` entries for `spot-schedule-time-based`
18+
(`src/bin/spot_schedule_time_based.rs`) and `spot-schedule-capital-markets`
19+
(`src/bin/spot_schedule_capital_markets.rs`). They were previously only
20+
auto-discovered under their underscore file-stem names, which did not match the
21+
hyphenated `command:` in their deploy manifests.
22+
- `Dockerfile`, `Dockerfile.chainguard`: also `COPY` `spot-schedule-time-based` and
23+
`spot-schedule-capital-markets` into the image (alongside `/5spot`). The main image
24+
is now multi-binary; `ENTRYPOINT` stays `/5spot` and providers select via `command:`.
25+
- `Makefile` (`prepare-binaries-linux-amd64`, `-arm64`): copy the two provider binaries
26+
into `binaries/<arch>/` so the Docker build can pick them up.
27+
- `.github/workflows/build.yaml` (Build job): the artifact upload (PR/push + release)
28+
now includes `spot-schedule-time-based` and `spot-schedule-capital-markets` — CI
29+
uploads only the named binary, so without this the providers never reach the Docker
30+
job (the multi-arch build failed with `binaries/arm64/spot-schedule-time-based: not
31+
found`). `cargo build --release` already builds all `[[bin]]`s.
32+
- `.github/actions/prepare-docker-binaries/action.yaml`: copy the two provider binaries
33+
from the downloaded artifacts into `binaries/<arch>/` for both arches (the local
34+
`make prepare-binaries` is not used by CI — this composite action is).
35+
- `deploy/spot-schedule-providers/{time-based,capital-markets}/deployment.yaml`:
36+
`command` changed to absolute paths (`/spot-schedule-time-based`,
37+
`/spot-schedule-capital-markets`) — the distroless image has no PATH entry for a bare
38+
name; the binaries live at `/`.
39+
- `docs/src/guides/time-based-schedule.md`, `docs/src/guides/capital-markets-schedule.md`,
40+
`docs/src/installation/controller.md`: documented that each provider is a separate,
41+
**required** Deployment shipped inside the main image (selected by `command:`), and
42+
that without a provider running no `ScheduledMachine` referencing a schedule activates.
43+
44+
### Why
45+
The spot-schedule providers (ADR 0009) had source and deploy manifests but were never
46+
wired into the build: the binaries were not declared with their deployed names, were
47+
not copied by `prepare-binaries`, and were not in the Dockerfiles. The published image
48+
therefore could not run them — a deployed provider crash-looped with
49+
`exec: "spot-schedule-time-based": executable file not found`, leaving every
50+
`ScheduledMachine` stuck (no `status.active` is ever written). Surfaced while bringing
51+
up the k0smotron workshop tier on a v1beta1 image.
52+
53+
### Impact
54+
- [ ] Breaking change
55+
- [x] Requires cluster rollout
56+
- [ ] Config change only
57+
- [ ] Documentation only (code + docs)
58+
59+
Note: the next image build is required before the provider Deployments can run; their
60+
`:v0.1.0` placeholder tags are pinned at release by `make set-image-version`.
61+
1262
## [2026-06-22 12:00] - CAPI Machine API version: passthrough from bootstrapSpec + mandatory discovery (no hardcoded version)
1363

1464
**Author:** Erick Bourgeois

.github/actions/prepare-docker-binaries/action.yaml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@ runs:
4848
exit 1
4949
fi
5050
51+
# Copy the spot-schedule provider binaries. The main image is multi-binary —
52+
# the provider Deployments select them via `command:` — so the Dockerfile
53+
# COPYs them alongside /5spot. Without this they are absent from the artifacts
54+
# and the build fails ("binaries/<arch>/spot-schedule-time-based: not found").
55+
for arch_dir in amd64 arm64; do
56+
art="artifacts/5spot-linux-$arch_dir"
57+
for prov in spot-schedule-time-based spot-schedule-capital-markets; do
58+
PROV_BIN=$(find "$art" -type f -name "$prov" | head -1)
59+
if [ -n "$PROV_BIN" ] && [ -f "$PROV_BIN" ]; then
60+
cp "$PROV_BIN" "binaries/$arch_dir/$prov"
61+
chmod +x "binaries/$arch_dir/$prov"
62+
echo "Copied $prov ($arch_dir) from $PROV_BIN"
63+
else
64+
echo "ERROR: $prov ($arch_dir) not found in $art"
65+
find "$art" -ls || echo "Directory does not exist"
66+
exit 1
67+
fi
68+
done
69+
done
70+
5171
# Verify binaries
52-
ls -lh binaries/amd64/5spot binaries/arm64/5spot
72+
ls -lh binaries/amd64/* binaries/arm64/*
5373
file binaries/amd64/5spot binaries/arm64/5spot

.github/workflows/build.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ jobs:
287287
name: ${{ matrix.platform.artifact_name }}
288288
path: |
289289
target/release/${{ matrix.platform.binary_name }}
290+
target/release/spot-schedule-time-based
291+
target/release/spot-schedule-capital-markets
290292
target/release/*.cdx.json
291293
retention-days: 1
292294

@@ -298,6 +300,8 @@ jobs:
298300
name: ${{ matrix.platform.artifact_name }}
299301
path: |
300302
target/release/${{ matrix.platform.binary_name }}
303+
target/release/spot-schedule-time-based
304+
target/release/spot-schedule-capital-markets
301305
target/release/*.cdx.json
302306
303307
# ─────────────────────────────────────────────────────────────────────────────

Cargo.toml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "five_spot"
3-
version = "0.1.1"
3+
version = "0.3.0"
44
edition = "2021"
55
rust-version = "1.90"
66
authors = ["Erick Bourgeois<erick.bourgeois@rbccm.com>"]
@@ -28,6 +28,17 @@ path = "src/bin/auto_vex_presence.rs"
2828
name = "auto-vex-reachability"
2929
path = "src/bin/auto_vex_reachability.rs"
3030

31+
# First-party spot-schedule providers (ADR 0009). Declared explicitly so the binary
32+
# names are hyphenated (matching the `command:` in their deploy manifests) rather than
33+
# the auto-discovered underscore names. Shipped IN the main 5-Spot image.
34+
[[bin]]
35+
name = "spot-schedule-time-based"
36+
path = "src/bin/spot_schedule_time_based.rs"
37+
38+
[[bin]]
39+
name = "spot-schedule-capital-markets"
40+
path = "src/bin/spot_schedule_capital_markets.rs"
41+
3142
[dependencies]
3243
# `unstable-runtime` is opt-in for `Controller::reconcile_on`, which we
3344
# use in main.rs to feed per-child-cluster Node-watch events into the

Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ LABEL org.opencontainers.image.source="https://github.com/finos/5-spot" \
3737
# Copy the pre-built binary for the target architecture
3838
COPY --chmod=755 binaries/${TARGETARCH}/5spot /5spot
3939

40+
# First-party spot-schedule providers (ADR 0009). Shipped in the same image; their
41+
# deploy manifests select them with `command: ["/spot-schedule-<provider>"]`. Without
42+
# a provider running, ScheduledMachines never see status.active and never activate.
43+
COPY --chmod=755 binaries/${TARGETARCH}/spot-schedule-time-based /spot-schedule-time-based
44+
COPY --chmod=755 binaries/${TARGETARCH}/spot-schedule-capital-markets /spot-schedule-capital-markets
45+
4046
USER nonroot
4147

4248
EXPOSE 8080

Dockerfile.chainguard

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ LABEL org.opencontainers.image.source="https://github.com/finos/5-spot" \
4848
# TARGETARCH is automatically set by BuildKit (amd64 or arm64)
4949
COPY --chmod=755 binaries/${TARGETARCH}/5spot /5spot
5050

51+
# First-party spot-schedule providers (ADR 0009). Shipped in the same image; their
52+
# deploy manifests select them with `command: ["/spot-schedule-<provider>"]`. Without
53+
# a provider running, ScheduledMachines never see status.active and never activate.
54+
COPY --chmod=755 binaries/${TARGETARCH}/spot-schedule-time-based /spot-schedule-time-based
55+
COPY --chmod=755 binaries/${TARGETARCH}/spot-schedule-capital-markets /spot-schedule-capital-markets
56+
5157
USER 65532:65532
5258

5359
EXPOSE 8080

Makefile

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,19 +134,23 @@ build-linux-arm64: ## Build for Linux ARM64 (requires cross toolchain)
134134
exit 1; \
135135
fi
136136

137-
prepare-binaries-linux-amd64: build-linux-amd64 ## Build and prepare Linux x86_64 binary
138-
@echo "Preparing Linux x86_64 binary for Docker build..."
137+
prepare-binaries-linux-amd64: build-linux-amd64 ## Build and prepare Linux x86_64 binaries
138+
@echo "Preparing Linux x86_64 binaries for Docker build..."
139139
@mkdir -p binaries/amd64
140140
@cp target/x86_64-unknown-linux-gnu/release/5spot binaries/amd64/
141-
@echo "✓ Binary ready: binaries/amd64/5spot"
142-
@ls -lh binaries/amd64/5spot
141+
@cp target/x86_64-unknown-linux-gnu/release/spot-schedule-time-based binaries/amd64/
142+
@cp target/x86_64-unknown-linux-gnu/release/spot-schedule-capital-markets binaries/amd64/
143+
@echo "✓ Binaries ready: 5spot, spot-schedule-time-based, spot-schedule-capital-markets"
144+
@ls -lh binaries/amd64/
143145

144-
prepare-binaries-linux-arm64: build-linux-arm64 ## Build and prepare Linux ARM64 binary
145-
@echo "Preparing Linux ARM64 binary for Docker build..."
146+
prepare-binaries-linux-arm64: build-linux-arm64 ## Build and prepare Linux ARM64 binaries
147+
@echo "Preparing Linux ARM64 binaries for Docker build..."
146148
@mkdir -p binaries/arm64
147149
@cp target/aarch64-unknown-linux-gnu/release/5spot binaries/arm64/
148-
@echo "✓ Binary ready: binaries/arm64/5spot"
149-
@ls -lh binaries/arm64/5spot
150+
@cp target/aarch64-unknown-linux-gnu/release/spot-schedule-time-based binaries/arm64/
151+
@cp target/aarch64-unknown-linux-gnu/release/spot-schedule-capital-markets binaries/arm64/
152+
@echo "✓ Binaries ready: 5spot, spot-schedule-time-based, spot-schedule-capital-markets"
153+
@ls -lh binaries/arm64/
150154

151155
test: ## Run all tests
152156
cargo test --all

deploy/spot-schedule-providers/capital-markets/deployment.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ spec:
4141
# Pin to a released version tag — NEVER use :latest (Trivy KSV-0013).
4242
image: ghcr.io/finos/5-spot:v0.1.0
4343
imagePullPolicy: IfNotPresent
44-
command: ["spot-schedule-capital-markets"]
44+
command: ["/spot-schedule-capital-markets"]
4545
env:
4646
- name: RUST_LOG
4747
value: "info"

deploy/spot-schedule-providers/time-based/deployment.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ spec:
4141
# Pin to a released version tag — NEVER use :latest (Trivy KSV-0013).
4242
image: ghcr.io/finos/5-spot:v0.1.0
4343
imagePullPolicy: IfNotPresent
44-
command: ["spot-schedule-time-based"]
44+
command: ["/spot-schedule-time-based"]
4545
env:
4646
- name: RUST_LOG
4747
value: "info"

docs/src/guides/capital-markets-schedule.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ kubectl apply -f deploy/crds/capitalmarketsschedule.yaml
4343
kubectl apply -k deploy/spot-schedule-providers/capital-markets/
4444
```
4545

46+
!!! important "The provider is a separate, required Deployment"
47+
Like every spot-schedule provider, this is its **own controller**
48+
(`spot-schedule-capital-markets`) — the only writer of
49+
`CapitalMarketsSchedule.status.active`. If it is not running, no
50+
`ScheduledMachine` referencing a `CapitalMarketsSchedule` activates. The binary
51+
ships **inside the main 5-Spot image** (multi-binary); the Deployment uses the
52+
`ghcr.io/finos/5-spot` image with `command: ["/spot-schedule-capital-markets"]`.
53+
4654
The provider runs with a least-privilege ClusterRole: `get;list;watch` on
4755
`capitalmarketsschedules` and `update;patch` on **only** their `/status`
4856
subresource — it never writes the spec (operators own the calendar) and reads

0 commit comments

Comments
 (0)