Skip to content

fix(agentcrd): strip server-managed metadata before ResumeAll re-apply#790

Open
bussyjd wants to merge 1 commit into
mainfrom
fix/agent-resume-strip-metadata
Open

fix(agentcrd): strip server-managed metadata before ResumeAll re-apply#790
bussyjd wants to merge 1 commit into
mainfrom
fix/agent-resume-strip-metadata

Conversation

@bussyjd

@bussyjd bussyjd commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Problem

obol stack up replays persisted Agent CR manifests via internal/agentcrd.ResumeAll. Those manifests are written by PersistManifest as a full yaml.Marshal of the applied object, which can already include server-managed metadata (resourceVersion, uid, creationTimestamp, managedFields, …).

On cluster recreate / re-apply, ResumeAll previously passed those bytes straight to kubectl.Apply. Kubernetes rejects the update with:

metadata.resourceVersion: Invalid value: 0: must be specified for an update

Root cause: replaying a client-side record that still carries server-managed identity fields.

Fix

  1. internal/stackbackup/cluster.go — export the existing unexported stripObject helper as StripServerManagedMetadata(obj map[string]any) (same body). StripK8sJSON continues to call it for JSON dumps; no behavior change for export/import.

  2. internal/agentcrd/manifest.go — in ResumeAll, after reading each persisted YAML file:

    • yaml.Unmarshal into map[string]any
    • call stackbackup.StripServerManagedMetadata
    • yaml.Marshal back to bytes
    • pass the stripped bytes only to kubectl.Apply

Parse/marshal failures warn and continue (best-effort per agent). warnIfWalletWouldRegenerate still receives the original unstripped bytes (it only reads spec.wallet.create).

Diagram

flowchart LR
  A["Persisted Agent YAML<br/>(resourceVersion, uid,<br/>managedFields, …)"] --> B["yaml.Unmarshal"]
  B --> C["StripServerManagedMetadata<br/>(shared stackbackup helper)"]
  C --> D["yaml.Marshal"]
  D --> E["kubectl apply"]
  E --> F["Apply succeeds<br/>(no resourceVersion:0 error)"]
Loading

Validation

gofmt -l internal/stackbackup/cluster.go internal/agentcrd/manifest.go internal/agentcrd/manifest_test.go internal/stackbackup/stackbackup_test.go
# (no output — all files formatted)

go build ./...
# exit 0

go test ./internal/agentcrd/... ./internal/stackbackup/... -count=1 -v
=== RUN   TestValidateName
...
=== RUN   TestManifestStoreRoundTrip
--- PASS: TestManifestStoreRoundTrip (0.00s)
=== RUN   TestStripServerManagedMetadataOnAgentManifest
--- PASS: TestStripServerManagedMetadataOnAgentManifest (0.00s)
PASS
ok  	github.com/ObolNetwork/obol-stack/internal/agentcrd	1.474s
=== RUN   TestSelectDataNamespaces
...
=== RUN   TestStripK8sJSON
--- PASS: TestStripK8sJSON (0.00s)
=== RUN   TestStripK8sJSONEmptyList
--- PASS: TestStripK8sJSONEmptyList (0.00s)
...
PASS
ok  	github.com/ObolNetwork/obol-stack/internal/stackbackup	2.046s

https://claude.ai/code/session_01PnhCQLz7CHuDBUhWd5xF8v

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.

1 participant