Skip to content

feat: Close validation gap with AKS checking supported Ubuntu version - #1895

Open
Bevan Arps (theunrepentantgeek) wants to merge 16 commits into
mainfrom
theunrepentantgeek-solid-potato
Open

feat: Close validation gap with AKS checking supported Ubuntu version#1895
Bevan Arps (theunrepentantgeek) wants to merge 16 commits into
mainfrom
theunrepentantgeek-solid-potato

Conversation

@theunrepentantgeek

Copy link
Copy Markdown
Member

Description

This pull request introduces improved validation logic for image family and Kubernetes version compatibility in the Azure cloud provider, along with comprehensive test coverage for these scenarios. The main focus is to ensure that when a NodeClass specifies an incompatible image family for the discovered Kubernetes version, appropriate errors are surfaced early, and no disruptive drift or resource creation occurs. The changes also clarify that such validation failures do not cause drift for already-launched nodes.

How was this change tested?

make presubmit

Does this change impact docs?

  • Yes, PR includes docs updates
  • Yes, issue opened: #
  • No

Release Note

Validation will now block early for unsupported combinations of Kubernetes and Ubuntu instead of failing to reconcile.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Only validate Kubernetes version compatibility when spec.imageFamily
explicitly pins an Ubuntu version (Ubuntu2204 or Ubuntu2404). The generic
Ubuntu family and an unset image family are a contract to run an
AKS-supported Ubuntu, resolved per Kubernetes version and potentially
resolved differently by different provisioning modes, so they must never be
rejected based on what the resolver happens to pick.

Add a typed ImageFamilyKubernetesVersionIncompatibleError carrying the
requested family, discovered version and applied bounds, and match on it with
errors.As in the status reconciler so only that error latches
ValidationSucceeded=False with ImageFamilyKubernetesVersionIncompatible.
Malformed and otherwise unexpected errors are returned for retry instead.

Because a pinned-family incompatibility is static, stop requeueing it every
minute: the NodeClass spec watch and the Kubernetes version reconciliation
already drive reevaluation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a status controller regression that reconciles a NodeClass pinning
Ubuntu2404 against a stubbed Kubernetes 1.31 cluster and asserts the
aggregate Ready condition ends up False because of ValidationSucceeded,
with the companion case at 1.32.0 showing the same NodeClass becomes Ready.
This closes the chain the cloudprovider suites only characterize with a
hand-set condition.

Align the hand-set condition message in the VM and AKS Machine API
cloudprovider cases with the message the reconciler now produces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ValidationReconciler called GetKubernetesVersion() unconditionally, so a
generic/unset Ubuntu or AzureLinux NodeClass failed reconciliation and skipped
Disk Encryption Set validation whenever the Kubernetes version was not ready
yet, even though no image family compatibility policy applies to it.

Add imagefamily.RequiresKubernetesVersionCompatibility() as the single source of
truth for which spec.imageFamily values are explicitly version pinned, use it in
ValidateImageFamilyCompatibility(), and gate the version lookup on it in the
status validation path so unpinned families proceed straight to DES validation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A NodeClass whose image family is incompatible with the discovered Kubernetes
version has ValidationSucceeded=False, which makes its aggregate Ready condition
false. Nodes that were already launched must not be disrupted for that: the
incompatibility is a forward-looking provisioning constraint, so treating it as
drift would replace healthy nodes with nodes that cannot be provisioned.

Cover both provisioning families by extending the existing VM and AKS Machine
API drift suites, asserting Ready goes false and IsDrifted still reports no
drift. No production drift logic changed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the separate pinned-family list and per-family bounds switch with a
single kubernetesVersionPinnedImageFamilies registry that both
RequiresKubernetesVersionCompatibility and ValidateImageFamilyCompatibility
derive from, so the predicate and the enforced bounds cannot disagree. Add an
internal test that walks every registered policy and checks the predicate, the
accepted and rejected versions, and the bounds reported on the typed error all
match the registry.

Also narrow the drift test comments to what they actually prove, restore an
unrelated blank line, reuse newAuthorizationError across the DES cases, and
cover the unset image family in the DES authorization failure table.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 7, 2026 00:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The compatibility policy is centralized, the controller wiring is straightforward, and the PR adds thorough tests covering validation, readiness, create-blocking, and drift behavior across provisioning paths.

Pull request overview

Adds a centralized image-family/Kubernetes-version compatibility policy for explicitly version-pinned Ubuntu families, and wires it into the NodeClass status validation path so incompatible combinations fail early (without attempting Azure resource reads/creates) and do not induce drift for already-launched nodes.

Changes:

  • Introduces imagefamily.ValidateImageFamilyCompatibility + typed errors, backed by a single pinned-family policy registry.
  • Updates the NodeClass status ValidationReconciler to gate pinned families on the discovered Kubernetes version and latch a stable condition reason for static incompatibilities.
  • Adds unit/integration coverage across imagefamily validation, NodeClass readiness, CloudProvider create blocking, and drift non-behavior.
File summaries
File Description
pkg/providers/imagefamily/compatibility.go Adds pinned Ubuntu family compatibility policy and validation helpers with typed errors.
pkg/providers/imagefamily/compatibility_unit_test.go Verifies the policy registry is the single source of truth for bounds/behavior.
pkg/providers/imagefamily/compatibility_test.go Black-box tests for parsing, boundary behavior, and typed error reporting.
pkg/controllers/nodeclass/status/validation.go Enforces pinned-family compatibility during validation and sets a stable condition reason on static incompatibility.
pkg/controllers/nodeclass/status/validation_test.go Ensures validation condition behavior, DES-call suppression on static incompatibility, and status-controller readiness outcomes.
pkg/cloudprovider/suite_test.go Ensures Create fails fast with NodeClassNotReadyError and no instance creation when validation is latched false.
pkg/cloudprovider/suite_drift_test.go Asserts ValidationSucceeded=false due to incompatibility does not create drift for already-launched NodeClaims (VM path).
pkg/cloudprovider/suite_aksmachineapi_offerings_test.go Mirrors fast-fail/no-create coverage for AKS Machine API offering path.
pkg/cloudprovider/suite_aksmachineapi_drift_test.go Asserts no drift for already-launched NodeClaims in AKS Machine API path when ValidationSucceeded=false.
Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@theunrepentantgeek

Copy link
Copy Markdown
Member Author

Copilot resolve the merge conflicts in this pull request

…lid-potato

# Conflicts:
#	pkg/controllers/nodeclass/status/validation.go
#	pkg/controllers/nodeclass/status/validation_test.go

Co-authored-by: theunrepentantgeek <1272094+theunrepentantgeek@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 7, 2026 02:47

Copilot AI commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Copilot resolve the merge conflicts in this pull request

Resolved the conflicts by merging main and retaining both validation paths and their tests in 9fecfb1.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A unit test assertion uses ContainSubstring with a format string, which prevents it from validating the computed expected range correctly.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread pkg/providers/imagefamily/compatibility_unit_test.go Outdated
#1897)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Comment thread pkg/providers/imagefamily/compatibility.go
Comment thread pkg/controllers/nodeclass/status/validation.go Outdated
Comment thread pkg/providers/imagefamily/compatibility_unit_test.go Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 7, 2026 05:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The behavior change is narrowly scoped, integrated at the status-validation layer, and is backed by unit and integration tests covering provisioning and drift expectations.

Review details
  • Files reviewed: 9/10 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment on lines +38 to +40
// ImageFamilyKubernetesVersionIncompatible is the stable reason used when
// spec.imageFamily explicitly pins an OS version that the ready discovered
// Kubernetes version does not support.
Comment on lines +29 to +30
// kubernetesVersionPolicy is the Kubernetes version window in which one explicitly
// version-pinned spec.imageFamily value is usable.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 7, 2026 05:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It changes provisioning-gating validation behavior and upgrades multiple dependencies, so it warrants final human review to confirm the AKS support-window bounds and broader dependency impact.

Review details
  • Files reviewed: 9/10 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

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.

3 participants