Skip to content

Commit dfcbec0

Browse files
authored
kind testing, rset graph (#207)
Signed-off-by: Daniel Guns <danbguns@gmail.com>
1 parent ecfbfd0 commit dfcbec0

17 files changed

Lines changed: 782 additions & 65 deletions

File tree

.github/workflows/live-tests.yml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
name: Live Cluster Tests
2+
3+
# Runs the #[ignore]d live regression suite (tests/live_tests.rs) against
4+
# real kind clusters built by scripts/dev-clusters.sh. Catches what unit CI
5+
# can't: API discovery, watch/list/log wire behavior, and upstream
6+
# flux-operator condition-message formats drifting under flux9s.
7+
#
8+
# Weekly rather than per-PR: the failure mode being guarded is upstream
9+
# drift (new Flux/flux-operator releases), not PR regressions.
10+
11+
on:
12+
schedule:
13+
# Mondays 06:00 UTC
14+
- cron: "0 6 * * 1"
15+
workflow_dispatch:
16+
inputs:
17+
clusters:
18+
description: "Dev clusters to build (dev-clusters.sh mode)"
19+
type: choice
20+
options:
21+
- ci # simple + legacy — everything the live suite asserts against
22+
- simple
23+
- legacy
24+
- all
25+
default: ci
26+
27+
permissions:
28+
contents: read
29+
30+
concurrency:
31+
group: live-tests
32+
cancel-in-progress: false
33+
34+
env:
35+
KIND_VERSION: v0.30.0
36+
# kind pulls images and starts controllers from cold — give the script's
37+
# readiness waits CI-appropriate headroom (defaults are tuned for warm
38+
# local Docker).
39+
FLUX9S_DEV_DEPLOY_WAIT_TIMEOUT: 180s
40+
FLUX9S_DEV_CRD_WAIT_RETRIES: "30"
41+
FLUX9S_DEV_CRD_WAIT_SLEEP_SECONDS: "5"
42+
43+
jobs:
44+
live-tests:
45+
name: Live regression suite (kind)
46+
runs-on: ubuntu-latest
47+
timeout-minutes: 45
48+
steps:
49+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
50+
51+
- name: Install Rust
52+
uses: dtolnay/rust-toolchain@stable
53+
54+
- name: Cache cargo registry
55+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
56+
with:
57+
path: |
58+
~/.cargo/bin/
59+
~/.cargo/registry/index/
60+
~/.cargo/registry/cache/
61+
~/.cargo/git/db/
62+
target/
63+
key: ${{ runner.os }}-cargo-live-${{ hashFiles('Cargo.lock') }}
64+
restore-keys: |
65+
${{ runner.os }}-cargo-live-
66+
${{ runner.os }}-cargo-
67+
68+
- name: Install kind
69+
run: |
70+
# ubuntu-latest ships a root-owned kind at /usr/local/bin — sudo so
71+
# our pinned version deterministically replaces it.
72+
sudo curl -fsSLo /usr/local/bin/kind \
73+
"https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-linux-amd64"
74+
sudo chmod +x /usr/local/bin/kind
75+
kind version
76+
# kubectl, helm, and envsubst ship on ubuntu-latest runners
77+
kubectl version --client
78+
helm version --short
79+
80+
- name: Compile live tests (before spending cluster time)
81+
run: cargo test --test live_tests --no-run
82+
83+
- name: Build dev clusters
84+
run: ./scripts/dev-clusters.sh "${{ inputs.clusters || 'ci' }}"
85+
86+
- name: Run live regression suite
87+
run: cargo test --test live_tests -- --ignored --test-threads=1 --nocapture
88+
89+
- name: Dump cluster diagnostics on failure
90+
if: failure()
91+
run: |
92+
for ctx in kind-flux9s-simple kind-flux9s-legacy; do
93+
kubectl config get-contexts -o name | grep -qx "$ctx" || continue
94+
echo "════ $ctx ════"
95+
kubectl --context "$ctx" get fluxinstance,resourcesets,resourcesetinputproviders,kustomizations,gitrepositories,ocirepositories -A 2>/dev/null || true
96+
kubectl --context "$ctx" get events -n flux-resources --sort-by=.lastTimestamp 2>/dev/null | tail -30 || true
97+
echo "──── flux-operator logs ────"
98+
kubectl --context "$ctx" logs -n flux-system deploy/flux-operator --tail=50 2>/dev/null || true
99+
done

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
- Graph view no longer flashes when the focused node is taller than the
12+
viewport (e.g. a FluxInstance's workload group): the focus auto-scroll now
13+
pins oversized nodes to their top edge instead of oscillating between
14+
showing their top and bottom on alternating frames.
15+
1016
### Added
17+
- Graph view downstream discovery for ResourceSet and FluxInstance (#204):
18+
their `status.inventory` now renders like a Kustomization's — Flux resources
19+
produced by a ResourceSet become individual navigable nodes, Deployments and
20+
other workloads get the workload group with live status, and arbitrary kinds
21+
(Namespaces, CRDs, custom resources) aggregate into the resource group.
1122
- Controller pod log viewer (#192): `:logs` opens a submenu of the discovered
1223
Flux controller pods (`:logs <pod|prefix>` streams one directly). Logs are
1324
tailed and followed live in a bounded buffer; scrolling up pauses following
@@ -66,6 +77,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6677
mismatches are visible instead of just confusing.
6778

6879
### Internal
80+
- New live-cluster regression suite (`tests/live_tests.rs`, all `#[ignore]`d):
81+
exact assertions against the dev kind clusters' planted fixtures — graph
82+
inventory, describe events, the operator's step-failure message format, pod
83+
log streaming, and legacy v1beta2 version-fallback discovery. Run locally
84+
with `just test-live` after `./scripts/dev-clusters.sh ci`, or via the new
85+
weekly/dispatch `live-tests.yml` workflow.
6986
- New generic `AsyncTask<K, T>` owns the request/dispatch/poll lifecycle for
7087
view fetches, replacing the five copy-pasted `*_pending`/`*_fetched`/`*_rx`
7188
field triplets and their hand-rolled trigger/poll methods.

Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,13 @@ path = "tests/field_extraction.rs"
180180
name = "trace_tests"
181181
path = "tests/trace_tests.rs"
182182

183+
# Live-cluster regression tests — every test is #[ignore]d; run via
184+
# `just test-live` after `./scripts/dev-clusters.sh ci`, or by the
185+
# live-tests.yml workflow (weekly / manual dispatch).
186+
[[test]]
187+
name = "live_tests"
188+
path = "tests/live_tests.rs"
189+
183190
[[test]]
184191
name = "snapshot_tests"
185192
path = "tests/snapshot_tests.rs"

docs/content/user-guide/_index.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,11 @@ Visualize resource relationships and dependencies. Shows upstream sources and do
215215
The graph view displays:
216216

217217
- **Upstream sources** (GitRepository, HelmRepository, etc.)
218-
- **Managed resources** (workloads, ConfigMaps, Services, etc.)
218+
- **Managed resources** (workloads, ConfigMaps, Services, etc.) — for
219+
Kustomizations, HelmReleases, ResourceSets, and FluxInstances alike; a
220+
ResourceSet's produced Flux resources appear as individual navigable nodes,
221+
and arbitrary kinds (Namespaces, CRDs, custom resources) aggregate into
222+
the resource group
219223
- **Resource groups** (aggregated by type)
220224
- **Workload groups** (aggregated workloads with status)
221225

justfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ test:
2020
test-integration:
2121
cargo test --test crd_compatibility --test resource_registry --test model_compatibility --test field_extraction --test trace_tests --test graph_tests
2222

23+
# Run live-cluster regression tests against the dev kind clusters
24+
# (build them first: ./scripts/dev-clusters.sh ci)
25+
test-live:
26+
cargo test --test live_tests -- --ignored --test-threads=1
27+
2328
# Run cargo-audit to check for CVEs (ignores unmaintained warnings)
2429
audit:
2530
# RUSTSEC-2026-0002 is currently pulled in transitively via ratatui 0.29's lru dependency.

scripts/dev-clusters.sh

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#
44
# Creates three clearly-named clusters:
55
#
6-
# flux9s-simple — Flux 2.8.x (current repo CRD baseline); day-to-day dev testing
7-
# flux9s-stress — Flux 2.5.x; 40+ resources of every kind for page-scroll / large lists
6+
# flux9s-simple — Flux 2.9.x + source-watcher; day-to-day dev testing (steps, AG, events)
7+
# flux9s-stress — Flux 2.7.x; 40+ resources of every kind for page-scroll / large lists
88
# flux9s-legacy — Flux 2.2.x with OCIRepository/Bucket at v1beta2; tests the
99
# version-fallback logic (flux9s tries v1 first, then v1beta2)
1010
#
@@ -16,6 +16,7 @@
1616
# ./scripts/dev-clusters.sh simple # build flux9s-simple only
1717
# ./scripts/dev-clusters.sh stress # build flux9s-stress only
1818
# ./scripts/dev-clusters.sh legacy # build flux9s-legacy only
19+
# ./scripts/dev-clusters.sh ci # build simple + legacy (live-test set)
1920
# ./scripts/dev-clusters.sh all # build all three clusters
2021
# ./scripts/dev-clusters.sh delete # delete all kind clusters and exit
2122

@@ -37,7 +38,7 @@ STRESS_CLUSTER="flux9s-stress"
3738
LEGACY_CLUSTER="flux9s-legacy"
3839

3940
FLUX_OPERATOR_CHART="oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator"
40-
FLUX_OPERATOR_VERSION="0.48.0"
41+
FLUX_OPERATOR_VERSION="0.55.0"
4142
DEPLOY_WAIT_TIMEOUT="${FLUX9S_DEV_DEPLOY_WAIT_TIMEOUT:-5s}"
4243
CRD_WAIT_RETRIES="${FLUX9S_DEV_CRD_WAIT_RETRIES:-5}"
4344
CRD_WAIT_SLEEP_SECONDS="${FLUX9S_DEV_CRD_WAIT_SLEEP_SECONDS:-3}"
@@ -302,7 +303,7 @@ run_build() {
302303
# ── cluster builders ───────────────────────────────────────────────────────────
303304

304305
build_simple_cluster() {
305-
header "Building $SIMPLE_CLUSTER (Flux 2.8.x — current repo CRD baseline)"
306+
header "Building $SIMPLE_CLUSTER (Flux 2.9.x + source-watcher — current repo CRD baseline)"
306307

307308
kind create cluster --name "$SIMPLE_CLUSTER" --wait 60s
308309
local ctx="kind-${SIMPLE_CLUSTER}"
@@ -311,6 +312,21 @@ build_simple_cluster() {
311312
apply_fluxinstance "$ctx" "${MANIFEST_DIR}/fluxinstance.yaml"
312313
wait_for_flux_crds "$ctx"
313314

315+
# source-watcher CRDs (simple cluster only — the medium/legacy instances
316+
# don't run the source-watcher component)
317+
info "Waiting for source-watcher CRDs …"
318+
for crd in \
319+
artifactgenerators.source.extensions.fluxcd.io \
320+
externalartifacts.source.toolkit.fluxcd.io; do
321+
local retries="$CRD_WAIT_RETRIES"
322+
while ! kubectl --context "$ctx" get crd "$crd" &>/dev/null; do
323+
retries=$((retries - 1))
324+
[ $retries -le 0 ] && { warn "Timed out waiting for $crd – skipping"; break; }
325+
sleep "$CRD_WAIT_SLEEP_SECONDS"
326+
done
327+
success " $crd"
328+
done
329+
314330
apply_simple_manifests "$ctx" "flux-resources"
315331

316332
success "Cluster $SIMPLE_CLUSTER is ready"
@@ -320,7 +336,7 @@ build_simple_cluster() {
320336
}
321337

322338
build_stress_cluster() {
323-
header "Building $STRESS_CLUSTER (Flux 2.5.x — stress/page-scroll testing)"
339+
header "Building $STRESS_CLUSTER (Flux 2.7.x — stress/page-scroll testing)"
324340

325341
kind create cluster --name "$STRESS_CLUSTER" --wait 60s
326342
local ctx="kind-${STRESS_CLUSTER}"
@@ -407,13 +423,19 @@ main() {
407423
run_build "$SIMPLE_CLUSTER" build_simple_cluster
408424
run_build "$STRESS_CLUSTER" build_stress_cluster
409425
;;
426+
# The live-test set (.github/workflows/live-tests.yml): the clusters
427+
# tests/live_tests.rs asserts against, skipping the heavy stress cluster.
428+
ci)
429+
run_build "$SIMPLE_CLUSTER" build_simple_cluster
430+
run_build "$LEGACY_CLUSTER" build_legacy_cluster
431+
;;
410432
all)
411433
run_build "$SIMPLE_CLUSTER" build_simple_cluster
412434
run_build "$STRESS_CLUSTER" build_stress_cluster
413435
run_build "$LEGACY_CLUSTER" build_legacy_cluster
414436
;;
415437
*)
416-
die "Unknown mode '$mode'. Use: both | simple | stress | legacy | all | delete"
438+
die "Unknown mode '$mode'. Use: both | simple | stress | legacy | ci | all | delete"
417439
;;
418440
esac
419441

@@ -422,10 +444,10 @@ main() {
422444
echo " Available clusters:"
423445
kind get clusters 2>/dev/null | sed 's/^/ • kind-/'
424446
echo
425-
echo " Day-to-day dev (Flux 2.8.x, current repo CRDs):"
447+
echo " Day-to-day dev (Flux 2.9.x, current repo CRDs):"
426448
echo " kubectl config use-context kind-${SIMPLE_CLUSTER} && cargo run"
427449
echo
428-
echo " Page-scroll stress testing (Flux 2.5.x):"
450+
echo " Page-scroll stress testing (Flux 2.7.x):"
429451
echo " kubectl config use-context kind-${STRESS_CLUSTER} && cargo run"
430452
echo " → Press Ctrl+f / Ctrl+b to page through the list"
431453
echo

scripts/dev-manifests/fluxinstance-medium.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ metadata:
88
spec:
99
distribution:
1010
# Pin to a mid-series release band where OCIRepository/Bucket/Helm* are stable,
11-
# but the cluster still represents an older CRD surface than the repo baseline.
12-
version: "2.5.x"
11+
# but the cluster still represents an older (yet supported) CRD surface than the repo baseline.
12+
version: "2.7.x"
1313
registry: "ghcr.io/fluxcd"
1414
components:
1515
- source-controller

scripts/dev-manifests/fluxinstance.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ spec:
99
distribution:
1010
# Pin to the current Flux release line represented by this repo's generated CRDs.
1111
# This keeps the "simple" dev cluster aligned with the latest API surface flux9s targets.
12-
version: "2.8.x"
12+
version: "2.9.x"
1313
registry: "ghcr.io/fluxcd"
1414
components:
1515
- source-controller
@@ -18,6 +18,8 @@ spec:
1818
- notification-controller
1919
- image-reflector-controller
2020
- image-automation-controller
21+
# source-watcher provides ArtifactGenerator + ExternalArtifact (both watched by flux9s)
22+
- source-watcher
2123
cluster:
2224
type: kubernetes
2325
multitenant: false

scripts/dev-manifests/simple/kustomize.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,21 @@ spec:
6262
sourceRef:
6363
kind: Bucket
6464
name: terraform-state
65+
---
66+
# Deliberate failure case: the path doesn't exist in the repo, so this
67+
# Kustomization emits ReconciliationFailed Warning events on every retry —
68+
# feed for the :events view, describe Events section, and unhealthy filter.
69+
apiVersion: kustomize.toolkit.fluxcd.io/v1
70+
kind: Kustomization
71+
metadata:
72+
name: broken-path-demo
73+
namespace: flux-resources
74+
labels: {app.kubernetes.io/managed-by: flux9s-dev}
75+
spec:
76+
interval: 5m
77+
retryInterval: 2m
78+
path: ./does-not-exist
79+
prune: true
80+
sourceRef:
81+
kind: GitRepository
82+
name: flux-system

0 commit comments

Comments
 (0)