Skip to content

trident-acl-agent: add storm trident-acl-agent E2E test harness, test images, and pipeline - #731

Draft
bfjelds wants to merge 4 commits into
user/bfjelds/acl-agent-rollback-grpc-rustfrom
user/bfjelds/acl-agent-rollback-grpc-storm
Draft

trident-acl-agent: add storm trident-acl-agent E2E test harness, test images, and pipeline#731
bfjelds wants to merge 4 commits into
user/bfjelds/acl-agent-rollback-grpc-rustfrom
user/bfjelds/acl-agent-rollback-grpc-storm

Conversation

@bfjelds

@bfjelds bfjelds commented Aug 5, 2026

Copy link
Copy Markdown
Member

Summary

Adds the storm-trident E2E scenario that validates trident-acl-agent end-to-end against real tridentd (while mocking kubelet/Nebraska) on a VM, testing update, rollback, reboot, and commit.

Includes storm code, pipeline, test images, and development documentation on how to run these tests locally.

Context

This is the last step in enabling trident-acl-agent to run updates and rollbacks. Related PRs:

Validation

PR details

Storm code

  • proxies/ — fake apiserver (serves the Node annotation protocol the agent watches/patches, including a real K8s-compatible watch stream), fake Nebraska/image servers, a minimal kubelet API shim, and an RP client used to drive scenarios and poll status annotations.
  • tests/update.go (stage/finalize/commit against a real reboot), rollback.go (rollback stage/finalize/commit against a real reboot, plus a regression test that a second rollback against an empty rollback chain is detected as a no-op via servicing_kind rather than reporting a false Success and rebooting again), vm.go/logs.go (VM lifecycle and log collection helpers).
  • trident.go, utils/config — scenario wiring and config plumbing specific to the aclagent suite.
  • README.md — usage instructions for running the suite locally.

Registered in tools/cmd/storm-trident/main.go alongside storm-trident's other scenarios.

Test images (tests/images)

  • baseimg-acl-agent.yaml / updateimg-acl-agent.yaml — VM image configurations for the base and post-update ACL test images.
  • testimages.py — wires the update image into the existing COSI-based image build path (the base qcow2 is built via the Makefile target below, not testimages.py, since the qcow2 tooling differs from COSI).

Build tooling

New artifacts/trident-vm-acl-agent-testimage.qcow2 Makefile target for the base image.

Pipeline

New trident-acl-agent-test.yml stage wired into e2e-template.yml, running the aclagent storm scenario in CI.

Docs

docs/Development/Testing/TridentAclAgent-Tests.md documents the suite; Testing.md links to it.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@bfjelds
bfjelds force-pushed the user/bfjelds/acl-agent-rollback-grpc-storm branch from bafab91 to 9b47495 Compare August 5, 2026 20:13
@bfjelds bfjelds changed the title storm/aclagent: add trident-acl-agent E2E test harness, test images, and pipeline trident-acl-agent: add storm trident-acl-agent E2E test harness, test images, and pipeline Aug 5, 2026
@bfjelds
bfjelds force-pushed the user/bfjelds/acl-agent-rollback-grpc-rust branch from 6598fdd to c3dfd8d Compare August 5, 2026 20:34
@bfjelds
bfjelds force-pushed the user/bfjelds/acl-agent-rollback-grpc-storm branch from 9b47495 to b94993f Compare August 5, 2026 20:34
@bfjelds
bfjelds requested a lite review from Copilot August 5, 2026 20:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Storm E2E scenario to validate trident-acl-agent end-to-end against a real tridentd on a VM (with fake Kubernetes apiserver + Nebraska/image server), along with the VM test images, CI pipeline stage wiring, and developer docs to run the suite locally.

Changes:

  • Introduces storm-trident run aclagent scenario with test cases for deploy, update (stage/finalize/reboot/commit), rollback, log collection, and cleanup.
  • Adds fake in-process infrastructure (apiserver, Omaha/Nebraska proxy, image server) used by the scenario to drive and observe Node annotation state transitions.
  • Adds new ACL-agent VM image configs + Makefile target(s), plus a new CI stage to build images and run the scenario.

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tools/storm/utils/vm/qemu/qemu.go Adds configurable qcow2 image selection regex for QEMU VM deployment.
tools/storm/aclagent/utils/config/config.go Defines Storm scenario configuration/flags for the ACL-agent suite.
tools/storm/aclagent/trident.go Registers the new aclagent Storm scenario and test case sequencing.
tools/storm/aclagent/tests/vm.go VM deploy/check/cleanup wrappers for QEMU/Azure platforms.
tools/storm/aclagent/tests/update.go Implements the A/B update E2E flow, including fake services and post-reboot commit validation.
tools/storm/aclagent/tests/rollback.go Implements rollback E2E flow and regression coverage for no-op rollback.
tools/storm/aclagent/tests/logs.go Hooks into existing VM log-fetch helper for the scenario.
tools/storm/aclagent/README.md Scenario usage and behavior documentation.
tools/storm/aclagent/proxies/scenario.go Scenario YAML schema + validation for driving test steps.
tools/storm/aclagent/proxies/rp.go “RP client” to patch requests / poll status via the fake apiserver.
tools/storm/aclagent/proxies/nebraska.go Fake Nebraska/Omaha endpoint for update availability + package metadata.
tools/storm/aclagent/proxies/kubelet.go Kubelet-ish helper for simulated ready/reboot signaling (currently unused by the main flow).
tools/storm/aclagent/proxies/imageserver.go Simple HTTP server to serve a real update artifact (e.g. .cosi).
tools/storm/aclagent/proxies/constants.go Shared constants for annotations/labels and marker defaults.
tools/storm/aclagent/proxies/apiserver.go Minimal fake Kubernetes apiserver with LIST/WATCH/PATCH support for Node.
tools/go.mod Adds Kubernetes API dependencies required by the fake apiserver/client types.
tools/go.sum Updates module sums to reflect new Kubernetes-related dependencies.
tools/cmd/storm-trident/main.go Registers the aclagent scenario with the storm-trident binary.
tests/images/trident-vm-testimage/README.md Documents the new ACL-agent VM image variant.
tests/images/trident-vm-testimage/base/updateimg-acl-agent.yaml MIC config for the ACL-agent update image (.cosi) that enables the agent.
tests/images/trident-vm-testimage/base/baseimg-acl-agent.yaml MIC config for the ACL-agent base qcow2 image (agent installed, not enabled).
tests/images/testimages.py Wires the ACL-agent update image into the test-image build plumbing.
Makefile Adds a new qcow2 build target for the ACL-agent base test image.
docs/Development/Testing/TridentAclAgent-Tests.md Adds developer documentation for building/running the ACL-agent Storm scenario.
docs/Development/Testing/Testing.md Links to the new ACL-agent testing documentation.
.pipelines/templates/stages/testing_acl_agent/trident-acl-agent-test.yml Adds CI stages/jobs to build images and run the ACL-agent Storm scenario.
.pipelines/templates/e2e-template.yml Wires the new ACL-agent test stage into the E2E template.
Suppressed comments (1)

tools/storm/aclagent/proxies/scenario.go:81

  • Validate() currently counts assert-failure-reason as a valid mutually-exclusive step kind, but that step kind is not runnable. If removing assert-failure-reason, update the validation error accordingly so invalid scenarios fail fast with a correct message.
		if step.AssertFailureReason != "" {
			kinds++
		}
		if kinds != 1 {
			return fmt.Errorf("scenario step %d must set exactly one of patch/expect/assert-failure-reason", index)

Comment thread tools/storm/aclagent/tests/update.go Outdated
Comment thread tools/storm/aclagent/tests/update.go
Comment thread tools/storm/aclagent/proxies/scenario.go
Comment thread tools/storm/aclagent/README.md Outdated
Comment thread docs/Development/Testing/TridentAclAgent-Tests.md Outdated
Comment thread tests/images/trident-vm-testimage/README.md Outdated
Comment thread tools/storm/aclagent/proxies/rp.go
@bfjelds
bfjelds force-pushed the user/bfjelds/acl-agent-rollback-grpc-storm branch 2 times, most recently from e7f33e9 to b26b5a0 Compare August 5, 2026 22:22
@bfjelds
bfjelds requested a lite review from Copilot August 5, 2026 22:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (8)

docs/Development/Testing/TridentAclAgent-Tests.md:176

  • The "Reboot Choice" section describes shim-based reboot interception, but the harness code treats finalize as a real reboot and waits for SSH to go down/up. The docs should describe the real reboot flow, or the implementation should be updated to actually use a reboot shim.
## Reboot Choice

This scenario uses shim-based reboot interception rather than a full VM
reboot: a `reboot`/`systemctl reboot` shim on `PATH` inside the VM signals the
scenario's controller and exits the agent process instead of actually
rebooting. The scenario then restarts `trident-acl-agent` fresh, exercising
its post-reboot resume logic without tearing down the SSH session or the
in-process fake services. This is less realistic than a full reboot, but it
keeps the test deterministic and fast.

tests/images/trident-vm-testimage/README.md:21

  • This section says the ACL-agent image "enables trident-acl-agent.service" and that the scenario writes "localhost" tunnel endpoints, but the base qcow2 config (baseimg-acl-agent.yaml) leaves the service disabled, and the storm harness configures endpoints via --host-endpoint-ip (not localhost reverse tunnels). Updating the README will keep the image docs consistent with the scenario and image configs.
For both, a set of corresponding update images is available. The ACL-agent
variant reuses the servicing-style VM image layout but additionally installs
`trident-acl-agent` and enables `trident-acl-agent.service` so storm ACL-agent
scenarios can drive a real in-guest agent talking to `tridentd`. The image does
not preseed /etc/trident/trident-acl-agent.conf with runner-specific tunnel
ports; the test scenario should SSH in after boot and write the real localhost
proxy endpoints for Nebraska and the Kubernetes API server.

tools/storm/aclagent/README.md:89

  • The "Reboot choice" section says the scenario uses a reboot shim to avoid a full reboot, but run-ab-update/run-rollback explicitly wait for SSH to drop and come back, and describe a real systemctl reboot triggered by the agent. The docs should match the harness's real-reboot behavior.
## Reboot choice

This scenario keeps the shim-based reboot interception from the old tester.
That is less realistic than a full VM reboot, but it keeps the test deterministic
and lets the storm runner hold the reverse SSH tunnels and in-process fake services
steady while the agent drives the finalize path.

tools/storm/aclagent/proxies/apiserver.go:285

  • handlePatch calls Decoder.DisallowUnknownFields(), but the body is decoded into map[string]any, so unknown fields are never rejected. This can hide mismatches between what the harness expects and what the agent actually patches.

Decode directly into metadataPatch (with DisallowUnknownFields) before applying the patch.

	defer r.Body.Close()
	body := json.NewDecoder(r.Body)
	body.DisallowUnknownFields()
	var raw map[string]any
	if err := body.Decode(&raw); err != nil {
		http.Error(w, fmt.Sprintf("invalid patch body: %v", err), http.StatusBadRequest)
		return
	}

tools/storm/aclagent/README.md:46

  • This README describes prepareVmForAclAgent as using localhost:<port> via reverse-SSH-forwarded tunnels and running enable --now, but the harness configures the agent to talk to http://<host-endpoint-ip>:<port> and does an explicit restart (to reconnect between test cases). Keeping the README aligned with the actual harness behavior will reduce confusion when running locally.
`prepareVmForAclAgent` writes `/etc/trident/trident-acl-agent.conf` pointing
at the `localhost:<port>` endpoints storm reverse-SSH-forwards into the VM,
then runs `systemctl enable --now trident-acl-agent.service`. Before that
runs, the service simply isn't started -- no crash-looping, no log noise.

docs/Development/Testing/TridentAclAgent-Tests.md:153

  • The "Test Cases" list is out of sync with the current harness: config/service setup happens in run-ab-update/run-rollback (not check-deployment), the scenario includes run-rollback, and the harness performs a real reboot (SSH goes down/up) rather than a shim-based simulated reboot.
1. **deploy-vm** — Copies the base qcow2 image and creates a QEMU VM
2. **check-deployment** — Verifies the VM booted and is accessible via SSH;
   writes `/etc/trident/trident-acl-agent.conf` pointing at the
   `localhost:<port>` endpoints storm reverse-SSH-forwards into the VM, then
   runs `systemctl enable --now trident-acl-agent.service`
3. **run-ab-update** — Starts the fake apiserver and fake Nebraska/Omaha
   endpoints in-process, seeds bootstrap node labels, patches the desired
   update-image label, and waits for `trident-acl-agent` to drive a real
   Trident A/B update to completion (including the shim-based simulated
   reboot)

docs/Development/Testing/TridentAclAgent-Tests.md:159

  • The flags table lists --artifacts-dir default as /tmp, but the scenario's TestConfig sets ArtifactsDir default to .. This mismatch can cause local runs to look in the wrong directory by default.
| Flag | Description | Default |
|------|-------------|---------|
| `--artifacts-dir` | Directory containing VM images | `/tmp` |
| `--output-path` | Output directory for logs | `./output` |
| `--platform` | `qemu` or `azure` | `qemu` |
| `--ssh-private-key-path` | Path to SSH private key | `~/.ssh/id_rsa` |
| `--api-server-port` | Port for the fake Kubernetes API server | `18080` |

tools/storm/aclagent/proxies/rp.go:63

  • ScenarioStep supports assert-failure-reason (and Scenario.Validate allows it), but RPClient.runStep never handles AssertFailureReason. Any scenario YAML that uses assert-failure-reason will currently fail with "no recognized action" instead of performing the assertion.

Either implement assert-failure-reason handling in the runner, or remove the field (and its validation path) until it’s supported.

func (c *RPClient) runStep(ctx context.Context, index int, step ScenarioStep) (*StepReport, error) {
	switch {
	case step.Patch != nil:
		if err := c.patchNodeRequest(ctx, step.Patch); err != nil {
			return nil, err
		}
		return &StepReport{Index: index, Kind: "patch", Passed: true, Message: "patched fake Node request annotation"}, nil
	case step.Expect != nil:
		return c.expectStatus(ctx, index, step.Expect)
	default:
		return nil, fmt.Errorf("step %d had no recognized action", index)
	}

bfjelds added a commit that referenced this pull request Aug 5, 2026
- use grep -qF for literal IP:port config checks (avoid regex-dot false match)
- waitForVmRebootAndSshBack now fails if SSH never goes down, instead of
  silently passing when no reboot occurred
- remove unimplemented assert-failure-reason scenario field
- fix ExpectTimeout step message to not claim a timeout when a match
  actually occurred (the real failure case)
- correct stale docs describing shim-based reboot interception; scenario
  does a real VM reboot + SSH reachability wait
- correct trident-vm-testimage README: only the update image enables
  trident-acl-agent.service by default, base image leaves it disabled

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8c06585d-a82d-475f-a802-83fdfa012d86
bfjelds and others added 4 commits August 5, 2026 23:37
…and pipeline

Adds the storm-trident E2E scenario that validates trident-acl-agent
end-to-end against real tridentd/kubelet/Nebraska on a VM, exercising
stage, finalize, rollback, and the post-reboot commit path.

Go test harness (tools/storm/aclagent):
- proxies/: fake apiserver (serves the Node annotation protocol the agent
  watches/patches, including a real K8s-compatible watch stream), fake
  Nebraska/image servers, a minimal kubelet API shim, and an RP client
  used to drive scenarios and poll status annotations.
- tests/: update.go (stage/finalize/commit against a real reboot),
  rollback.go (rollback stage/finalize/commit against a real reboot, plus
  a regression test that a second rollback against an empty rollback
  chain is detected as a no-op via servicing_kind rather than reporting a
  false Success and rebooting again), vm.go/logs.go (VM lifecycle and log
  collection helpers).
- trident.go, utils/config: scenario wiring and config plumbing specific
  to the aclagent suite.
- README.md: usage instructions for running the suite locally.

Registered in tools/cmd/storm-trident/main.go alongside storm-trident's
other scenarios.

Test images (tests/images):
- baseimg-acl-agent.yaml / updateimg-acl-agent.yaml: VM image
  configurations for the base and post-update ACL test images.
- testimages.py: wires the update image into the existing COSI-based
  image build path (the base qcow2 is built via the Makefile target
  below, not testimages.py, since the qcow2 tooling differs from COSI).

Build tooling (Makefile): new
artifacts/trident-vm-acl-agent-testimage.qcow2 target for the base image.

Pipeline (.pipelines): new trident-acl-agent-test.yml stage wired into
e2e-template.yml, running the aclagent storm scenario in CI.

Docs: docs/Development/Testing/TridentAclAgent-Tests.md documents the
suite; Testing.md links to it.

Depends on the trident-acl-agent Rust implementation in the parent
branch (user/bfjelds/acl-agent-rollback-grpc-rust).

This is the final branch in the stack and, combined with its two parent
branches, contains the full set of changes from
user/bfjelds/acl-agent-rollback-grpc.

Verified: go build ./... and gofmt clean under tools/; go vet ./...
clean except one pre-existing, unrelated warning in
storm/servicing/tests/update.go (confirmed present on main, untouched by
this change); storm-trident binary builds; full local
`storm-trident run aclagent` suite passes (6/6: deploy-vm,
check-deployment, run-ab-update, run-rollback, collect-logs,
cleanup-vm), rebuilt end-to-end from this branch's HEAD.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8c06585d-a82d-475f-a802-83fdfa012d86
A prior commit (37b479e, retiring the old bin/trident-acl-agent-tester
target) removed that targets one dependency from go-tools via an
imprecise line-range deletion, which wiped the entire go-tools
dependency list instead of just the appended trident-acl-agent-tester
token - go-tools has been building nothing (make go-tools was a no-op)
since. The same deletion also left an orphaned "@mkdir -p bin" line
dangling where the removed targets recipe used to be.

Restored the dependency list to its pre-regression contents (minus the
retired trident-acl-agent-tester entry, which no longer exists) and
removed the orphaned mkdir line.

Verified: "make -n go-tools" now correctly expands to build all 7
tools (netlaunch, netlisten, miniproxy, virtdeploy, isopatch, mkcosi,
storm-trident, rcp-agent); "make bin/storm-trident" builds
successfully.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8c06585d-a82d-475f-a802-83fdfa012d86
GoalSource::Labels was renamed to GoalSource::Annotations (TOML value
"labels" -> "annotations") in the parent branch. The VM config
template this harness writes to /etc/trident/trident-acl-agent.conf
still had the old value, which would now fail to deserialize since
"labels" is no longer a valid GoalSource variant.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8c06585d-a82d-475f-a802-83fdfa012d86
- use grep -qF for literal IP:port config checks (avoid regex-dot false match)
- waitForVmRebootAndSshBack now fails if SSH never goes down, instead of
  silently passing when no reboot occurred
- remove unimplemented assert-failure-reason scenario field
- fix ExpectTimeout step message to not claim a timeout when a match
  actually occurred (the real failure case)
- correct stale docs describing shim-based reboot interception; scenario
  does a real VM reboot + SSH reachability wait
- correct trident-vm-testimage README: only the update image enables
  trident-acl-agent.service by default, base image leaves it disabled

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8c06585d-a82d-475f-a802-83fdfa012d86
@bfjelds
bfjelds force-pushed the user/bfjelds/acl-agent-rollback-grpc-storm branch from 1eeda78 to 5a5ecce Compare August 5, 2026 23:38
@bfjelds
bfjelds requested a lite review from Copilot August 5, 2026 23:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (5)

tools/storm/aclagent/utils/config/config.go:4

  • ArtifactsDir default is "." here, but other storm scenarios default it to "/tmp" (e.g. tools/storm/servicing/utils/config/config.go:4 and tools/storm/rollback/utils/config/config.go:4). Keeping this consistent avoids surprising behavior when running different scenarios locally and matches the docs’ stated default.
	ArtifactsDir          string `help:"Directory containing artifacts for the VM" default:"."`

tools/storm/utils/vm/qemu/qemu.go:24

  • ImagePattern is compiled as a regex (tools/storm/utils/file/file.go:13) and the default pattern contains an unescaped . before qcow2, so it will also match names like ...testimageXqcow2 and can accidentally match unexpected files (or trigger the "multiple files found" error). Escaping the dot makes the default behave as intended.
	SecureBoot   bool   `help:"Enable secure boot for the VM" default:"false"`
	SerialLog    string `help:"Path to the serial log file" default:"/tmp/trident-vm-verity-test.log"`
	ImagePattern string `help:"Regex pattern used to find the base VM image (.qcow2) in the artifacts directory" default:"^trident-vm-.*-testimage.qcow2$"`

tools/storm/aclagent/README.md:46

  • This describes prepareVmForAclAgent as using localhost:<port> via reverse-SSH tunnels and running enable --now, but the implementation writes host-IP endpoints (see tools/storm/aclagent/tests/update.go:262-277) and does systemctl enable + systemctl restart (update.go:360-366). Updating this keeps the doc aligned with the actual harness behavior (and the rationale about tunnels not surviving reboot).
`prepareVmForAclAgent` writes `/etc/trident/trident-acl-agent.conf` pointing
at the `localhost:<port>` endpoints storm reverse-SSH-forwards into the VM,
then runs `systemctl enable --now trident-acl-agent.service`. Before that
runs, the service simply isn't started -- no crash-looping, no log noise.

tools/storm/aclagent/README.md:89

  • This section still says the scenario uses shim-based reboot interception and depends on reverse SSH tunnels, but the tests wait for a real reboot by polling SSH reachability (tools/storm/aclagent/tests/update.go:403-429) and explicitly avoid tunnels for the fake endpoints (update.go:124-127). This mismatch will confuse anyone debugging reboot-related failures.
This scenario keeps the shim-based reboot interception from the old tester.
That is less realistic than a full VM reboot, but it keeps the test deterministic
and lets the storm runner hold the reverse SSH tunnels and in-process fake services
steady while the agent drives the finalize path.

docs/Development/Testing/TridentAclAgent-Tests.md:142

  • The check-deployment description says the config points at localhost:<port> via reverse-SSH forwarding and that it runs enable --now, but the harness uses a host-reachable IP/port (tests/update.go:262-277) and performs systemctl enable + systemctl restart (update.go:360-366). Aligning this documentation matters because it affects how people reason about connectivity across the real reboot.
1. **deploy-vm** — Copies the base qcow2 image and creates a QEMU VM
2. **check-deployment** — Verifies the VM booted and is accessible via SSH;
   writes `/etc/trident/trident-acl-agent.conf` pointing at the
   `localhost:<port>` endpoints storm reverse-SSH-forwards into the VM, then
   runs `systemctl enable --now trident-acl-agent.service`

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (10)

tools/storm/aclagent/proxies/rp.go:83

  • Issue: decodeStatus() errors are ignored, so a malformed acl.azure.com/update-status annotation will be silently treated as “no status yet” and the step will just time out, hiding the real failure.

Evidence: status, _ := decodeStatus(node) drops the error.

Suggestion: handle the error explicitly and fail the step with the decode error + raw annotation value so the scenario report is self-diagnosing.

		node, err := c.getNode(ctx)
		if err != nil {
			return nil, err
		}
		status, _ := decodeStatus(node)

tools/storm/aclagent/tests/update.go:128

  • Issue: The fake apiserver binds to 0.0.0.0, which exposes the unauthenticated test endpoint on all host interfaces. This is avoidable (and can be surprising on developer machines) since the VM only needs it reachable via HostEndpointIP.

Evidence: ListenAndServe(..., "0.0.0.0:<port>").

Suggestion: bind to testConfig.HostEndpointIP (or another explicit listen address) so the server is only exposed where needed.

	// Bind on all interfaces (not 127.0.0.1) so the VM can reach the fake
	// apiserver directly over the libvirt NAT network at testConfig.HostEndpointIP,
	// instead of relying on reverse SSH tunnels. Tunnels don't survive a real
	// VM reboot; a real host IP does.
	if _, err := apiServer.ListenAndServe(ctx, fmt.Sprintf("0.0.0.0:%d", testConfig.APIServerPort)); err != nil {

tools/storm/aclagent/tests/update.go:158

  • Issue: The fake image server binds to 0.0.0.0, exposing a local artifact over unauthenticated HTTP on all host interfaces.

Evidence: imageServer.ListenAndServe(..., "0.0.0.0:<port>").

Suggestion: bind to testConfig.HostEndpointIP so it’s only reachable on the interface the VM uses.

			return fmt.Errorf("failed to hash image %s: %w", imagePath, err)
		}
		imageServer := &stormproxies.ImageServer{ImagePath: imagePath}
		if _, err := imageServer.ListenAndServe(ctx, fmt.Sprintf("0.0.0.0:%d", testConfig.ImageServerPort)); err != nil {
			return fmt.Errorf("failed to start fake image server: %w", err)

tools/storm/aclagent/tests/update.go:173

  • Issue: The fake Nebraska endpoint binds to 0.0.0.0, exposing an unauthenticated update server mock on all host interfaces.

Evidence: nebraska.ListenAndServe(..., "0.0.0.0:<port>").

Suggestion: bind to testConfig.HostEndpointIP so it’s only reachable on the interface the VM uses.

		SHA384:      nebraskaSHA384,
		PackageName: nebraskaPackageName,
	}}
	if _, err := nebraska.ListenAndServe(ctx, fmt.Sprintf("0.0.0.0:%d", testConfig.NebraskaPort)); err != nil {
		return fmt.Errorf("failed to start fake Nebraska endpoint: %w", err)

tools/storm/aclagent/tests/rollback.go:42

  • Issue: The fake apiserver in rollback binds to 0.0.0.0, exposing an unauthenticated test endpoint on all host interfaces.

Evidence: ListenAndServe(..., "0.0.0.0:<port>").

Suggestion: bind to testConfig.HostEndpointIP (or another explicit listen address) to limit exposure to the interface the VM uses.

	nodeStore := stormproxies.NewNodeStore(stormproxies.NewSeedNode(testConfig.NodeName, map[string]string{}))
	apiServer := stormproxies.NewAPIServer(testConfig.NodeName, nodeStore)
	if _, err := apiServer.ListenAndServe(ctx, fmt.Sprintf("0.0.0.0:%d", testConfig.APIServerPort)); err != nil {
		return fmt.Errorf("failed to start fake apiserver: %w", err)
	}

tools/storm/aclagent/trident.go:72

  • Issue: On error paths, runTestCase calls tc.FailFromError(err) but then continues and unconditionally logs the test as “passed”. That makes logs misleading and can mask follow-on errors after a known failure.

Evidence: after tc.FailFromError(err) the function falls through to logrus.Infof("test case '%s' passed"...).

Suggestion: return immediately after FailFromError, and only log “passed” when there was no error.

	if testCaseSpecificConfig.OutputPath != "" {
		testCaseSpecificConfig.OutputPath = filepath.Join(testCaseSpecificConfig.OutputPath, tc.Name())
		if err := os.MkdirAll(testCaseSpecificConfig.OutputPath, 0o755); err != nil {
			tc.FailFromError(err)
		}

docs/Development/Testing/TridentAclAgent-Tests.md:142

  • Issue: The doc says check-deployment writes config pointing at localhost:<port> via reverse SSH tunnels, but the harness now configures the VM to talk directly to the test runner at HostEndpointIP:<port> (and avoids tunnels specifically because they don’t survive a real reboot).

Evidence: RunABUpdate binds the fake apiserver on 0.0.0.0 and advertises http://<HostEndpointIP>:<port> to the VM.

Suggestion: update this step description to match the actual networking model (host-reachable IP/port, no reverse tunnels).

2. **check-deployment** — Verifies the VM booted and is accessible via SSH;
   writes `/etc/trident/trident-acl-agent.conf` pointing at the
   `localhost:<port>` endpoints storm reverse-SSH-forwards into the VM, then
   runs `systemctl enable --now trident-acl-agent.service`

docs/Development/Testing/TridentAclAgent-Tests.md:157

  • Issue: Documented default for --artifacts-dir doesn’t match the scenario’s flag default.

Evidence: docs list /tmp, but TestConfig.ArtifactsDir defaults to ..

Suggestion: update the doc table default (or the flag default) so they stay consistent.

| `--artifacts-dir` | Directory containing VM images | `/tmp` |

tools/storm/aclagent/README.md:46

  • Issue: This README says the scenario uses localhost:<port> endpoints via reverse SSH forwarding, but the harness configures the VM to reach the fake services directly on HostEndpointIP:<port> (and intentionally avoids tunnels for reboot survival).

Evidence: prepareVmForAclAgent writes endpoints using HostEndpointIP.

Suggestion: update the README wording to match the actual networking model.

`prepareVmForAclAgent` writes `/etc/trident/trident-acl-agent.conf` pointing
at the `localhost:<port>` endpoints storm reverse-SSH-forwards into the VM,
then runs `systemctl enable --now trident-acl-agent.service`. Before that
runs, the service simply isn't started -- no crash-looping, no log noise.

tests/images/trident-vm-testimage/README.md:25

  • Issue: This README says the scenario should write “localhost proxy endpoints”, but the harness configures the VM to talk to the test runner over a host-reachable IP (HostEndpointIP) rather than SSH-tunneled localhost.

Evidence: prepareVmForAclAgent uses HostEndpointIP for the apiserver/Nebraska endpoints.

Suggestion: update this text to describe writing <host-endpoint-ip>:<port> endpoints (reachable from the VM) instead of localhost.

into it there is no test harness left to `systemctl enable --now` it. Neither
image preseeds /etc/trident/trident-acl-agent.conf with runner-specific
tunnel ports; the test scenario should SSH in after boot and write the real
localhost proxy endpoints for Nebraska and the Kubernetes API server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants