fix(operator): reject a DHCHAP pool created with no allowed nodes - #498
Merged
Merged
Conversation
A StoragePool created with dhchap: true and an empty allowedNodes can never enforce them. createStorageClassIfNotExists decides the gate once, from DHCHAP && len(AllowedNodes) > 0, and only then writes dhchap_node_selector. StorageClass parameters are immutable and the class is create-only, so populating allowedNodes later syncs the node labels and the backend allowed hosts but never adds the parameter: no PersistentVolume from that pool ever gets a nodeAffinity. Recreating the pool was the only way out. Reject the combination instead of repairing it. dhchap is immutable, so it can only be set at creation, which makes this the one place the state can arise. Replacing the class to add the parameter was the alternative and is worse: it would discard anything a user put on the class, including is-default-class, and leave a window with no class at all. Growing or shrinking a non-empty allowedNodes is untouched and needs no class change, because the parameter holds the pool's label key rather than the node list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
noctarius
approved these changes
Sep 8, 2026
boddumanohar
added a commit
that referenced
this pull request
Sep 10, 2026
handleStoragePoolDeletion cleared spec.allowedNodes on the object it then wrote back to drop the finalizer. The StoragePool CRD rejects that shape for a DHCHAP pool — "dhchap requires a non-empty allowedNodes", added in #498 — so the rejection landed on the very update that removes the finalizer, and the CR stayed in Terminating for as long as the reconciler kept retrying. syncNodeLabels does need an empty allowed-nodes list to clear the labels, so it now gets one on a copy, and the finalizer comes off through a patch that carries nothing but the finalizer list. The regression spec runs against envtest rather than a fake client because the rule lives in the CRD: a fake client validates nothing and would pass either way. Driving the mock control plane from a Ginkgo spec needed NewSpecServerFromFile to take an interface, since testing.TB cannot be implemented outside the standard library. Also deletes the commented-out pool-update block this file carried: the quality gate checks the prose of a changed file, and dead code is not worth rewording. Regression: 2026-09-09-dhchap-pool-delete-frozen Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
boddumanohar
added a commit
that referenced
this pull request
Sep 10, 2026
handleStoragePoolDeletion cleared spec.allowedNodes on the object it then updated to drop the finalizer, and the StoragePool CRD rejects that shape for a DHCHAP pool — "dhchap requires a non-empty allowedNodes", added in #498. The rejection landed on the very update that removes the finalizer, so the CR stayed in Terminating for as long as the reconciler kept retrying, and no DHCHAP pool could be deleted at all. syncNodeLabels reads Spec.AllowedNodes, so clearing the labels still needs an empty list. It now gets one on a copy, and the object written back keeps the spec the CRD accepts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
boddumanohar
added a commit
that referenced
this pull request
Sep 10, 2026
handleStoragePoolDeletion cleared spec.allowedNodes on the object it then updated to drop the finalizer, and the StoragePool CRD rejects that shape for a DHCHAP pool — "dhchap requires a non-empty allowedNodes", added in #498. The rejection landed on the very update that removes the finalizer, so the CR stayed in Terminating for as long as the reconciler kept retrying, and no DHCHAP pool could be deleted at all. syncNodeLabels reads Spec.AllowedNodes, so clearing the labels still needs an empty list. It now gets one on a copy, and the object written back keeps the spec the CRD accepts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
noctarius
pushed a commit
that referenced
this pull request
Sep 10, 2026
handleStoragePoolDeletion cleared spec.allowedNodes on the object it then updated to drop the finalizer, and the StoragePool CRD rejects that shape for a DHCHAP pool — "dhchap requires a non-empty allowedNodes", added in #498. The rejection landed on the very update that removes the finalizer, so the CR stayed in Terminating for as long as the reconciler kept retrying, and no DHCHAP pool could be deleted at all. syncNodeLabels reads Spec.AllowedNodes, so clearing the labels still needs an empty list. It now gets one on a copy, and the object written back keeps the spec the CRD accepts. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.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
A
StoragePoolcreated withdhchap: trueand an emptyallowedNodescan never enforce them.createStorageClassIfNotExistsdecides the gate once:Storage class parameters once set, cannot be modified later. So initially when a storage class is created without
allowedNodes,dhchap_node_selectorparameter is not set. And the later when allowedHosts is specified, they cannot be updated.