Repository navigation
fix: keep image resolution sticky while the selector is unchanged - #58
Merged
Merged
Conversation
status.resolvedImages was re-resolved to the newest matching snapshot on every pass, so publishing any snapshot that matched the selector moved the resolution — and the image-selector drift check in #51 would have replaced the whole fleet five minutes later with no spec edit. Resolve now takes an optional preferred image and keeps it while it is still in the match set; the NodeClass controller passes the ID it already recorded. A selector edit (or a deleted/deprecated image) drops it out of the match set, so resolution moves exactly when the operator intended. Transient hcloud failures now keep the recorded images instead of clearing them, which had the same churn-through-a-blip failure mode. Also corrects the imageSelector.version docs: version and selector are AND-combined, not mutually exclusive. Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Reviewing #51 raised a churn risk:
DriftImageSelectorcompares a NodeClaim's booted image againststatus.resolvedImages, but the NodeClass controller re-resolves that field to the newest matching snapshot on every pass (every 5 minutes).So the moment you publish any snapshot that matches your selector,
status.resolvedImagesmoves, and #51's check would replace every running node — with no spec edit, no warning, and nothing in the docs saying so. Resolution was a moving target that drift was about to be pointed at.Fix — resolution becomes sticky
1.
imagefamilygains a preference option.Resolve(ctx, sel, arch, opts ...ResolveOption)now acceptsWithPreferredID(id). After the normal match/sort pass, a preferred image that is still in the match set wins over the newest. A preferred ID that is unknown, or that no longer satisfies the selector, is ignored and resolution falls back to the newest — so stickiness self-heals rather than pinning dead IDs.2. The controller passes what it already recorded.
reconcileImagesbuilds an architecture→ID map fromstatus.resolvedImagesand hands each arch its previous ID. A fresh NodeClass (no entry) resolves to the newest, exactly as before.3. Transient failures stop erasing the status. Previously an hcloud API error cleared
status.resolvedImages; the next healthy pass then re-picked the newest match — the same churn, triggered by a blip. Now only definitive answers clear it (unsupported family, selector matching nothing). An API failure keeps the recorded images and reportsImageResolutionFailed, which still blocksCreatevia the Ready condition.Behaviour after this PR
status.resolvedImagesspec.imageSelectoredited so the recorded image stops matchingAlso in this PR
docs/configuration.mdclaimedimageSelector.versionis "Ignored whenselectoris set". It is not —ResolveAND-combines the label selector (server-side) with the family/version substring match (client-side). Corrected while documenting the stickiness rule.Tests
TestResolve_PreferredIDKeepsResolutionSticky— five cases: newest by default, preferred survives a newer snapshot, unknown preferred falls back, a selector edit excludes the preferred image (re-resolves), a preferred image that no longer matches the family falls back.TestReconcile_ResolutionStickyUntilSelectorChanges— the end-to-end rule: reconcile →{amd64:12, arm64:13}; publish a newer snapshot → still{12,13}; editimageSelector.version→{amd64:14, arm64:13}(the arch whose recorded image still matches stays put).TestReconcile_APIErrorKeepsResolvedImages— 500s after a healthy pass keep the recorded images while flippingImagesReadytoImageResolutionFailed.Scope / ordering
pkg/providers/imagefamily,pkg/controllers/nodeclass,docs/configuration.md. No CRD change (nothing new in status), no provider-behaviour change beyond image selection.Land this before #51 — otherwise #51's image-selector drift check is live against a moving resolution and one snapshot push rolls the fleet. Merge order: #55 → this → #51.
Validation
mise run cigreen: lint 0 issues, vet, race tests (unit + e2e), build, generate-verify.