You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Run the existing operator-agent chainsaw test suite under k8s-tests/operator-agent/ against the new agent-go container image from #220, in CI, alongside the existing Python runs. This is the parity safety net for the cutover: every behavior the operator e2e tests pin down — log format, flag file shape, history file format, interrupt idempotence, log retention, the dont_write_logs mode — must work identically against the Go agent before #222 deletes the Python source.
Depends on #220 (the agent-go image must exist and be pullable).
Motivation
Unit tests in #213–#219 cover each module in isolation, but they can't catch:
A log line format change that breaks an operator-side log scraper.
A flag file path drift that causes the operator to think no step has run.
A history file shape change that confuses an upgrade.
A subtle env var leak between the chrooted step and the host.
An exit code that's -15 in Python but 255 in Go and breaks the NodeRestart path.
The five existing chainsaw scenarios (simple, interrupt, reap_old_logs, dont_write_logs, check_node) collectively exercise these surfaces against a real kind cluster with a real operator. If the Go image passes them, we have high confidence the cutover is safe.
Feature description
A new CI job in .github/workflows/agent-go-ci.yaml that:
Spins up a kind cluster with the operator (matching the existing operator-agent-tests job in .github/workflows/agent-ci.yaml lines 266–335).
Keep the existing Python operator-agent-tests job in place — both run, both must pass. Until cutover, the operator is built and tested against both images on every relevant PR.
2. Expect divergences; fix forward in this PR
Run the suite locally first against the Go image and expect failures. Each failure is a parity bug — fix it in this PR (not by amending #213–#219), so the diff that closes the gap is visible to the reviewer alongside the test that caught it.
dont_write_logs scenario: SKYHOOK_AGENT_WRITE_LOGS=false must produce no log files but still stream to stdout. [FEA]: tee streaming and run_step #217 territory.
If a fix is large enough that it changes the shape of one of the earlier PRs' modules, prefer landing it as a small follow-up (not amending the merged PR). Note this in the PR description.
3. Log capture for diagnostics
Configure the chainsaw run to dump:
All agent pod logs (both Python and Go) on failure.
The contents of /etc/skyhook/flags/, /etc/skyhook/history/, /var/log/skyhook/ from a target node.
This is the difference between "this scenario failed" being actionable vs. unhelpful. Add a dump-on-fail step to the job.
4. Don't gate the cutover prematurely
This PR does not flip the operator default to the Go image. Operator-side make targets and the Python image continue to be the production path until #222 explicitly cuts over. This PR only proves we could cut over without regression.
All five also still pass against the Python agent image (regression guard — make sure splitting the workflow didn't break anything).
Scope boundaries
In scope:
New CI job running existing chainsaw suite against the Go image.
Parity bug-fixes that the suite uncovers (small, surgical).
Log dump on failure.
Out of scope:
Editing the chainsaw scenarios themselves — they are the contract. If a scenario is wrong (asserts on something that shouldn't be a contract), open a separate issue.
New operator-agent-go-tests job exists and passes.
All five chainsaw scenarios pass against the Go image.
All five chainsaw scenarios still pass against the Python image (no regression).
Failure dumps are captured for both jobs.
No changes to operator code or Helm chart.
No changes to chainsaw scenarios themselves (or, if any, justified in the PR with a separate small issue link).
Open questions
Is the kind cluster shared across the two operator-agent-tests jobs (faster) or per-job (cleaner isolation)? Per-job is safer; faster is fine if both pass reliably. Start per-job.
Should this PR also run the suite against an upgrade scenario — Python agent ran first, Go agent takes over mid-rollout? That's the most realistic cutover risk. Recommend yes — add a sixth scenario agent-upgrade that uses the Python image for apply and the Go image for apply-check/subsequent stages, and asserts no flag/history/log drift.
If the operator-agent suite reveals a parity bug that isn't fixable without rework, what's the escalation? Recommend opening a small follow-up issue per bug rather than blocking the whole rewrite on a single PR.
Summary
Run the existing
operator-agentchainsaw test suite under k8s-tests/operator-agent/ against the newagent-gocontainer image from #220, in CI, alongside the existing Python runs. This is the parity safety net for the cutover: every behavior the operator e2e tests pin down — log format, flag file shape, history file format, interrupt idempotence, log retention, thedont_write_logsmode — must work identically against the Go agent before #222 deletes the Python source.Depends on #220 (the
agent-goimage must exist and be pullable).Motivation
Unit tests in #213–#219 cover each module in isolation, but they can't catch:
-15in Python but255in Go and breaks the NodeRestart path.The five existing chainsaw scenarios (
simple,interrupt,reap_old_logs,dont_write_logs,check_node) collectively exercise these surfaces against a real kind cluster with a real operator. If the Go image passes them, we have high confidence the cutover is safe.Feature description
A new CI job in
.github/workflows/agent-go-ci.yamlthat:operator-agent-testsjob in .github/workflows/agent-ci.yaml lines 266–335).AGENT_IMAGEto theagent-goimage tag from [FEA]:agent-goDockerfile and container CI #220.make setup-kind-cluster operator-agent-testsfromoperator/.Proposed direction
1. CI job
Mirror the existing
operator-agent-testsjob almost line-for-line. The only differences:needs:now includes thecreate-manifestjob for the Go image (from [FEA]:agent-goDockerfile and container CI #220), not the Python one.AGENT_IMAGEenv points at the Go image tag.Keep the existing Python
operator-agent-testsjob in place — both run, both must pass. Until cutover, the operator is built and tested against both images on every relevant PR.2. Expect divergences; fix forward in this PR
Run the suite locally first against the Go image and expect failures. Each failure is a parity bug — fix it in this PR (not by amending #213–#219), so the diff that closes the gap is visible to the reviewer alongside the test that caught it.
Common categories to anticipate:
[out]/[err]prefix, timestamp precision, line-by-line newline handling. [FEA]:teestreaming andrun_step#217 territory.MakeFlagPathmarker reproduction. [FEA]: Filesystem helpers (paths, flags, log paths) + history file #215 territory.SUCEEDED:typo: presence required (e2e greps for it). [FEA]:teestreaming andrun_step#217 territory.-15exit code: [FEA]:teestreaming andrun_step#217 + [FEA]:do_interruptwith NodeRestart-15special case #218 territory.dont_write_logsscenario:SKYHOOK_AGENT_WRITE_LOGS=falsemust produce no log files but still stream to stdout. [FEA]:teestreaming andrun_step#217 territory.reap_old_logsscenario: log retention keeps current + 4 previous. [FEA]: Filesystem helpers (paths, flags, log paths) + history file #215 territory.interruptscenario: idempotence under repeated reconciles. [FEA]:do_interruptwith NodeRestart-15special case #218 territory.check_nodescenario:check_resultsfile format and_ALL_CHECKEDflag. [FEA]: Controllermain/agent_main/ SIGTERM + CLI parsing and entrypoint banner #219 territory.If a fix is large enough that it changes the shape of one of the earlier PRs' modules, prefer landing it as a small follow-up (not amending the merged PR). Note this in the PR description.
3. Log capture for diagnostics
Configure the chainsaw run to dump:
/etc/skyhook/flags/,/etc/skyhook/history/,/var/log/skyhook/from a target node.This is the difference between "this scenario failed" being actionable vs. unhelpful. Add a
dump-on-failstep to the job.4. Don't gate the cutover prematurely
This PR does not flip the operator default to the Go image. Operator-side
maketargets and the Python image continue to be the production path until #222 explicitly cuts over. This PR only proves we could cut over without regression.5. Tests
The PR is itself a test job. Specific assertions:
agent-go.agentimage (regression guard — make sure splitting the workflow didn't break anything).Scope boundaries
In scope:
Out of scope:
Acceptance criteria
operator-agent-go-testsjob exists and passes.Open questions
operator-agent-testsjobs (faster) or per-job (cleaner isolation)? Per-job is safer; faster is fine if both pass reliably. Start per-job.agent-upgradethat uses the Python image forapplyand the Go image forapply-check/subsequent stages, and asserts no flag/history/log drift.References (codebase)
setup-kind-cluster,operator-agent-teststargets.Alternatives considered
Code of Conduct