Remove Cincinnati upgrade-graph validation for nodepool upgrades - #5153
Conversation
There was a problem hiding this comment.
Pull request overview
Removes Cincinnati upgrade-graph validation from the backend nodepool version controller so nodepool upgrades are validated only via static Kubernetes/OpenShift version skew constraints (no downgrades, nodepool ≤ control plane, no minor skipping), aligning with the HCP nodepool Replace upgrade strategy.
Changes:
- Removed Cincinnati client initialization/caching and upgrade-edge checks from
nodepool_version_controller. - Updated unit tests to drop Cincinnati mocks and assert static validation behavior instead.
- Adjusted the nodepool version upgrade E2E test wording/comments to reflect that backend validation no longer depends on Cincinnati edges (while still using Cincinnati for test version discovery).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| test/e2e/nodepool_version_upgrade.go | Updates test comments/log messages around version selection for nodepool upgrades. |
| backend/pkg/controllers/upgradecontrollers/nodepool_version_controller.go | Removes Cincinnati upgrade-edge validation and related client/cache code; keeps static version-skew validation. |
| backend/pkg/controllers/upgradecontrollers/nodepool_version_controller_test.go | Removes Cincinnati mocking and updates/rewrites tests to validate new static-only behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| syncer := &nodePoolVersionSyncer{ | ||
| cooldownChecker: &alwaysSyncCooldownChecker{}, | ||
| clusterManagementClusterContentLister: newValidHostedClusterContentLister(t), | ||
| cosmosClient: mockDB, | ||
| clusterServiceClient: mockCS, | ||
| clusterToCincinnatiClient: lru.New(100), | ||
| cooldownChecker: &alwaysSyncCooldownChecker{}, | ||
| cosmosClient: mockDB, | ||
| clusterServiceClient: mockCS, | ||
| } |
| // --- Phase 2: Change version to a downgrade, should fail, desired should NOT change --- | ||
|
|
||
| // Update the HCPNodePool with a new desired version | ||
| // Update the HCPNodePool with a version that is a downgrade from the active version (4.19.10) | ||
| nodePool, err := mockDB.HCPClusters(testSubscriptionID, testResourceGroupName). | ||
| NodePools(testClusterName).Get(ctx, testNodePoolName) |
Simon Wiencki (swiencki)
left a comment
There was a problem hiding this comment.
Three comments inline. Substance-only review across rubber-duck + GPT-5.5 + Opus 4.7 1M; the headline finding is the test-coverage gap vs ARO-26792 AC #2.
|
|
||
| // Validate the customer's desired version before setting it | ||
| if err := c.validateDesiredNodePoolVersion(ctx, &customerDesiredVersion, existingServiceProviderNodePool, existingServiceProviderCluster, subscription, nodePool.Properties.Version.ChannelGroup, clusterKey, clusterUUID); err != nil { | ||
| if err := c.validateDesiredNodePoolVersion(ctx, &customerDesiredVersion, existingServiceProviderNodePool, existingServiceProviderCluster, subscription); err != nil { |
There was a problem hiding this comment.
Cincinnati was also implicitly checking the version exists in the channel. After this PR a non-existent version like 4.20.999 passes the static gate. Is CS the authoritative availability check now? Worth being explicit so we don't regress into the same "ARM Succeeded, never progresses" shape for a different reason.
There was a problem hiding this comment.
CS checks that the version exists but we so also check it in here. Otherwise we will have the same issue, as this validation will pass for a well formed but not existed version (4.20.999) but fail "silently" to the user in CS.
So, we need to make a call here to Cincinnati to check that the version exists.
There was a problem hiding this comment.
Not sure what we do for deployment/install but why not just use the same validation as we do there? Is that different from this flow? I would expect that this would prevent both of those situations
There was a problem hiding this comment.
We don't have this for install. The creation of the nodepool is not yet done in the backend, and adding the cincinnati call to the frontend will increase our time response. Let's add it here, and once we have the node pool creation call in the backend we can add the same validation there.
Manyanda Chitimbo (machi1990)
left a comment
There was a problem hiding this comment.
- I personally still on the fence about this change and I'd have kept the validation and give customer two options:
- Either they recreate their node pool if they don't care about "validated" upgradeability
- Or they do hops from v1, v2...vDesired
I understand that these might not always be better UX but I personally feel like they are better options that doesn't bypass upgrades gates.
If this use case gets an approval from BU & David Eads (@deads2k) I won't stand on the way of it. Please let's get that approval from them. Also I am looping in Alba Hita (@ahitacat) for review as well.
- CS component is also involved in the upgrade and has the upgradeability check; can you double check if there is anything that needs to be done on the CS component as well?
Alba Hita (ahitacat)
left a comment
There was a problem hiding this comment.
In addition to Manyanda Chitimbo (@machi1990) review #5153 (review)
In CS when creating the upgrade policy we also check that the version has an upgradepath. That should be change before this, so otherwise we could have the same issue, as the controller that creates these policies (trigger_nodepool_upgrade_controller) will fail.
|
|
||
| // Validate the customer's desired version before setting it | ||
| if err := c.validateDesiredNodePoolVersion(ctx, &customerDesiredVersion, existingServiceProviderNodePool, existingServiceProviderCluster, subscription, nodePool.Properties.Version.ChannelGroup, clusterKey, clusterUUID); err != nil { | ||
| if err := c.validateDesiredNodePoolVersion(ctx, &customerDesiredVersion, existingServiceProviderNodePool, existingServiceProviderCluster, subscription); err != nil { |
There was a problem hiding this comment.
CS checks that the version exists but we so also check it in here. Otherwise we will have the same issue, as this validation will pass for a well formed but not existed version (4.20.999) but fail "silently" to the user in CS.
So, we need to make a call here to Cincinnati to check that the version exists.
64d2e24 to
53170ec
Compare
|
per David Eads (@deads2k) suggestion this change was split into two parts (part 2 in #5184)
The previous comments were addressed in this PR. Both PRs are pending on the update on CS (MR 322) FYI Manyanda Chitimbo (@machi1990) Alba Hita (@ahitacat) |
Simon Wiencki (swiencki)
left a comment
There was a problem hiding this comment.
Reviewed, code looks good, no blockers from my side. Concerns in #5153 (review) should be addressed. Reviewed the CS MR too (https://gitlab.cee.redhat.com/service/aro-hcp-clusters-service/-/merge_requests/322) with one non-blocking note.
|
/approve I'll leave lgtm to another reviewer. |
There was a problem hiding this comment.
After this is merged we can remove the check of the upgrade path. I.e. so we don't skip this.
https://github.com/Azure/ARO-HCP/blob/main/test/e2e/nodepool_version_upgrade.go#L184
Also, I think is worth it to test this with an e2e. Right now from 4.20.8 -> 4.20.9 there is no upgrade path. We could have an e2e that checks in cincinnati a case like this and upgrades succesfully. Can you add it (it should be skipped before this gets merge but we can test it)
53170ec to
b5d396a
Compare
I also addressed your comments on CS 322; pending on your approval. |
|
/retest 53 minutes waiting for a free identity container |
|
/retest |
|
/lgtm |
|
/retest |
|
/retest due to container identity exhaustion (tests passed, clean ups failed) |
|
/retest |
2 similar comments
|
/retest |
|
/retest |
… check for nodepool upgrades HCP nodepools use the Replace upgrade strategy — nodes are destroyed and recreated at the target version, not upgraded in-place. Cincinnati upgrade edges are irrelevant; only version existence and Kubernetes version skew constraints apply. Per @deads2k suggestion, this work is split into two PRs: 1/2: Remove edge requirement, keep version existence check (this PR) 2/2: Remove downgrade restriction for nodepool versions Replaces validateUpgradePathAvailable (which required a Cincinnati edge from current to desired version) with validateVersionExistsInCincinnati (which only verifies the desired version exists in the Cincinnati graph). Static validation remains: no downgrade, ≤ CP version, within minor+1. Depends on CS MR !322: https://gitlab.cee.redhat.com/service/aro-hcp-clusters-service/-/merge_requests/322 Fixes: ARO-26792 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add GetVersionPairWithoutUpgradeEdge helper to find version pairs without Cincinnati upgrade edges for E2E testing - Add pending E2E test for forward upgrade without Cincinnati edge, exercising the actual bug scenario (e.g. 4.20.8 -> 4.20.9) - Rename UpgradePathExistsSucceeds to ValidUpgradeSucceeds to reflect that the test validates static version checks, not edge existence Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add HyperShift Replace strategy docs link - Rename ErrNoNoEdgePairFound to ErrNoEdgePairFound (duplicated "No") - Build Cincinnati channel from parsed major.minor to handle X.Y.Z input - Return clearer error when fewer than 2 parseable versions in minor Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6224f84 to
e91841c
Compare
| channel := fmt.Sprintf("%s-%d.%d", channelGroup, requestedMinor.Major, requestedMinor.Minor) | ||
| graphURL := fmt.Sprintf("https://api.openshift.com/api/upgrades_info/v1/graph?channel=%s", url.QueryEscape(channel)) | ||
|
|
||
| req, err := http.NewRequestWithContext(ctx, http.MethodGet, graphURL, nil) | ||
| if err != nil { | ||
| return semver.Version{}, semver.Version{}, fmt.Errorf("create graph request for %s: %w", channel, err) | ||
| } | ||
|
|
||
| client := &http.Client{Timeout: graphAPIRequestTimeout} |
| DescribeTable("should upgrade a nodepool to a version without Cincinnati upgrade edge", | ||
| func(ctx context.Context, minor string) { | ||
| Skip("skipped until PR #5184 is merged and deployed") | ||
|
|
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: adalrsjr1, deads2k, geoberle The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
…st coverage Absorb main (PRs #5153, #5239), then apply downgrade-specific changes: - Remove downgrade guard from admission webhook - Rename ValidateNodePoolUpgrade → ValidateNodePoolVersionChange - Add downgrade E2E tests (z-stream, y-stream at N-2 boundary) - Add multi-element activeVersions unit tests - Add cross-major downgrade path tests (4.21, 4.23, 5.1, 5.2) - Align doc comments across validators, admission, and controller Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes: ARO-26792
(updated)
What
Replace Cincinnati upgrade-edge validation with a version existence check in the nodepool version controller. The backend now verifies the desired version exists in
Cincinnati but no longer requires an upgrade edge from the current version. Static Kubernetes version skew constraints remain enforced (nodepool ≤ CP version, no downgrade,
within minor+1).
Per David Eads (@deads2k) suggestion, this work is split into two PRs:
Why
HCP nodepools use the Replace upgrade strategy — nodes are destroyed and recreated at the target version, not upgraded in-place. Cincinnati upgrade edges are irrelevant for
this strategy.
The controller was querying Cincinnati for every nodepool upgrade and requiring an edge from the current to the desired version. When no edge existed (e.g. 4.20.8 →
4.21.1), it entered a permanent error-retry loop. ARM reported
Succeededwhile the upgrade never progressed, leaving customers with no visibility into the failure.Testing
SucceedsWithoutCincinnatiEdge(version exists but no edge → succeeds) andVersionNotInCincinnatiFails(version doesn't exist → fails). UpdatedDesiredVersionUnchangedOnFailureto test VersionNotFound instead of missing edges.4.21.14 successfully.
Special notes for your reviewer
Depends on CS MR !322 — CS also validates upgrade edges via
AvailableUpgradesin
ValidateNodePoolUpgradeVersion(). Without the CS change, the backend accepts the version but CS blocks the upgrade policy. Safe to deploy in any order — neither changealone creates a regression.
A rationale comment in
validateDesiredNodePoolVersionnotes that if an InPlace upgrade strategy is introduced in the future, strategy-specific upgrade validation shouldbe added.