Skip to content

Commit ca3d347

Browse files
jhjaggarsclaude
andauthored
CNTRLPLANE-2262: Add Azure scale-from-zero support (#8337)
* feat: CNTRLPLANE-2262: Add Azure scale-from-zero support Extend the existing scale-from-zero autoscaling framework to support Azure by implementing an Azure instance type provider that queries the Azure Resource SKUs API for VM size specifications and writing capacity annotations on MachineDeployments. Changes: - Add Azure instancetype.Provider using armcompute.ResourceSKUsClient - Add AzureMachineTemplate case to scale_from_zero.go type switch - Extend supportedScaleFromZeroPlatform() for Azure - Extend reconcileScaleFromZeroAnnotations() for Azure - Update autoscalerEnabledCondition() to accept Azure with min=0 - Update effectiveMin guard in capi.go to allow min=0 for Azure - Add "azure" to supportedProviders in main.go and install.go - Add Azure provider initialization with credential file parsing - Update CRD CEL validation to allow min=0 for Azure platform - Add unit tests for Azure provider and extended type switches Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address review feedback for Azure scale-from-zero - Update NodePoolAutoScaling.Min field comment and CRD validation rule to reflect Azure support alongside AWS - Regenerate CRD manifests with updated docs and validation - Fix partial SKU cache on Azure pager failure: build into local map and assign to cache only after full walk succeeds - Tighten platform gate: add ScaleFromZeroPlatform field so annotations are only set when nodepool platform matches the configured provider - Validate all required Azure credential fields (subscriptionId, clientId, clientSecret, tenantId, location) upfront with a clear error listing missing fields Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update envtest suite for Azure scale-from-zero Update CRD test suite to match the updated validation rule that allows autoScaling.min=0 on Azure platform: - Change Azure min=0 test from expecting failure to expecting success - Update Agent and KubeVirt error messages to include Azure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address lint and verify CI failures - Lowercase error string for Azure scale-from-zero credentials - Fix gci import ordering in main.go, provider_test.go, scale_from_zero_test.go, and nodepool_test.go Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address CodeRabbit review for Azure scale-from-zero - Gate effectiveMin=0 on runtime-configured scaleFromZeroPlatform instead of static platform type check, preventing stalled pools when the scale-from-zero provider isn't wired up - Resolve AZURE_CLOUD_NAME for credential and SKU client construction in scale-from-zero init, matching sovereign cloud support used elsewhere - Return errors on invalid/negative GPU values in transformSKU instead of silently skipping, with VM size in error messages for debuggability Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update CLI help text and regenerate vendor files Update the --scale-from-zero-provider help text to list both aws and azure as supported platforms. Regenerate vendor and docs to sync with the rebased branch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(e2e): enable scale-from-zero e2e test for Azure platform The TestNodePoolAutoscalingScaleFromZero test was hardcoded to skip on non-AWS platforms. The test logic is already platform-agnostic (it copies the existing NodePool spec), so the only change needed is widening the platform gate to include Azure. A follow-up PR in openshift/release will configure the Azure CI jobs to install the operator with --scale-from-zero-provider=azure and the appropriate credentials. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: make scale-from-zero effectiveMin data-driven Replace hardcoded platform checks with a data-driven approach: - Add hasStatusCapacity() to check native provider support - Change setMachine{Deployment,Set}Replicas to accept bool - Add statusCapacity extraction for Azure machine templates - effectiveMin=0 allowed when Status.Capacity is populated OR when the runtime scale-from-zero provider matches the platform Addresses review comments from enxebre on PR #8337. * fix: add cache TTL, VMSizeNotFoundError, and remove unrelated gitignore entries Address csrwng review feedback: - Add 1-hour TTL to Azure SKU cache so new VM sizes are picked up - Introduce VMSizeNotFoundError to distinguish permanent errors (VM size doesn't exist in region) from transient errors (API failure) - Stop retrying indefinitely for non-existent VM sizes - Document why Azure uses caching unlike the AWS provider - Remove unrelated .claude/skills/dev/azure-sandbox-* from .gitignore --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d6ec188 commit ca3d347

26 files changed

Lines changed: 992 additions & 103 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,4 @@ __pycache__/
5959
.pytest_cache/
6060
.venv/
6161
venv/
62-
*.egg
62+
*.egg

api/hypershift/v1beta1/nodepool_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ type NodePool struct {
107107
// +kubebuilder:validation:XValidation:rule="!has(self.replicas) || !has(self.autoScaling)", message="Both replicas or autoScaling should not be set"
108108
// +kubebuilder:validation:XValidation:rule="self.arch != 's390x' || has(self.platform.kubevirt)", message="s390x is only supported on KubeVirt platform"
109109
// +kubebuilder:validation:XValidation:rule="!has(self.platform.aws) || !has(self.platform.aws.imageType) || self.platform.aws.imageType != 'Windows' || self.arch == 'amd64'", message="ImageType 'Windows' requires arch 'amd64' (AWS only)"
110-
// +kubebuilder:validation:XValidation:rule="!has(self.autoScaling) || self.autoScaling.min > 0 || self.platform.type == 'AWS'", message="Scale-from-zero (autoScaling.min=0) is currently only supported for AWS platform"
110+
// +kubebuilder:validation:XValidation:rule="!has(self.autoScaling) || self.autoScaling.min > 0 || self.platform.type == 'AWS' || self.platform.type == 'Azure'", message="Scale-from-zero (autoScaling.min=0) is currently only supported for AWS and Azure platforms"
111111
type NodePoolSpec struct {
112112
// clusterName is the name of the HostedCluster this NodePool belongs to.
113113
// If a HostedCluster with this name doesn't exist, the controller will no-op until it exists.
@@ -546,7 +546,7 @@ type NodePoolManagement struct {
546546
// +kubebuilder:validation:XValidation:rule="self.max >= self.min", message="max must be equal or greater than min"
547547
type NodePoolAutoScaling struct {
548548
// min is the minimum number of nodes to maintain in the pool.
549-
// Can be set to 0 for scale-from-zero for AWS platform.
549+
// Can be set to 0 for scale-from-zero for AWS and Azure platforms.
550550
// Must be >= 0 and <= .Max.
551551
//
552552
// +kubebuilder:validation:Minimum=0

api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/AAA_ungated.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ spec:
108108
min:
109109
description: |-
110110
min is the minimum number of nodes to maintain in the pool.
111-
Can be set to 0 for scale-from-zero for AWS platform.
111+
Can be set to 0 for scale-from-zero for AWS and Azure platforms.
112112
Must be >= 0 and <= .Max.
113113
format: int32
114114
minimum: 0
@@ -1518,9 +1518,9 @@ spec:
15181518
rule: '!has(self.platform.aws) || !has(self.platform.aws.imageType)
15191519
|| self.platform.aws.imageType != ''Windows'' || self.arch == ''amd64'''
15201520
- message: Scale-from-zero (autoScaling.min=0) is currently only supported
1521-
for AWS platform
1521+
for AWS and Azure platforms
15221522
rule: '!has(self.autoScaling) || self.autoScaling.min > 0 || self.platform.type
1523-
== ''AWS'''
1523+
== ''AWS'' || self.platform.type == ''Azure'''
15241524
status:
15251525
description: status is the latest observed status of the NodePool.
15261526
properties:

api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/GCPPlatform.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ spec:
108108
min:
109109
description: |-
110110
min is the minimum number of nodes to maintain in the pool.
111-
Can be set to 0 for scale-from-zero for AWS platform.
111+
Can be set to 0 for scale-from-zero for AWS and Azure platforms.
112112
Must be >= 0 and <= .Max.
113113
format: int32
114114
minimum: 0
@@ -1787,9 +1787,9 @@ spec:
17871787
rule: '!has(self.platform.aws) || !has(self.platform.aws.imageType)
17881788
|| self.platform.aws.imageType != ''Windows'' || self.arch == ''amd64'''
17891789
- message: Scale-from-zero (autoScaling.min=0) is currently only supported
1790-
for AWS platform
1790+
for AWS and Azure platforms
17911791
rule: '!has(self.autoScaling) || self.autoScaling.min > 0 || self.platform.type
1792-
== ''AWS'''
1792+
== ''AWS'' || self.platform.type == ''Azure'''
17931793
status:
17941794
description: status is the latest observed status of the NodePool.
17951795
properties:

api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/OSStreams.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ spec:
108108
min:
109109
description: |-
110110
min is the minimum number of nodes to maintain in the pool.
111-
Can be set to 0 for scale-from-zero for AWS platform.
111+
Can be set to 0 for scale-from-zero for AWS and Azure platforms.
112112
Must be >= 0 and <= .Max.
113113
format: int32
114114
minimum: 0
@@ -1546,9 +1546,9 @@ spec:
15461546
rule: '!has(self.platform.aws) || !has(self.platform.aws.imageType)
15471547
|| self.platform.aws.imageType != ''Windows'' || self.arch == ''amd64'''
15481548
- message: Scale-from-zero (autoScaling.min=0) is currently only supported
1549-
for AWS platform
1549+
for AWS and Azure platforms
15501550
rule: '!has(self.autoScaling) || self.autoScaling.min > 0 || self.platform.type
1551-
== ''AWS'''
1551+
== ''AWS'' || self.platform.type == ''Azure'''
15521552
status:
15531553
description: status is the latest observed status of the NodePool.
15541554
properties:

api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/OpenStack.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ spec:
108108
min:
109109
description: |-
110110
min is the minimum number of nodes to maintain in the pool.
111-
Can be set to 0 for scale-from-zero for AWS platform.
111+
Can be set to 0 for scale-from-zero for AWS and Azure platforms.
112112
Must be >= 0 and <= .Max.
113113
format: int32
114114
minimum: 0
@@ -1705,9 +1705,9 @@ spec:
17051705
rule: '!has(self.platform.aws) || !has(self.platform.aws.imageType)
17061706
|| self.platform.aws.imageType != ''Windows'' || self.arch == ''amd64'''
17071707
- message: Scale-from-zero (autoScaling.min=0) is currently only supported
1708-
for AWS platform
1708+
for AWS and Azure platforms
17091709
rule: '!has(self.autoScaling) || self.autoScaling.min > 0 || self.platform.type
1710-
== ''AWS'''
1710+
== ''AWS'' || self.platform.type == ''Azure'''
17111711
status:
17121712
description: status is the latest observed status of the NodePool.
17131713
properties:

cmd/install/assets/crds/hypershift-operator/tests/nodepools.hypershift.openshift.io/stable.nodepools.autoscaling.testsuite.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ tests:
3131
id: "subnet-01234567"
3232
type: AWS
3333
34-
- name: when autoScaling min=0 on Azure platform it should fail
34+
- name: when autoScaling min=0 on Azure platform it should pass
3535
initial: |
3636
apiVersion: hypershift.openshift.io/v1beta1
3737
kind: NodePool
@@ -56,7 +56,6 @@ tests:
5656
diskStorageAccountType: Premium_LRS
5757
subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet"
5858
type: Azure
59-
expectedError: "Scale-from-zero (autoScaling.min=0) is currently only supported for AWS platform"
6059
6160
- name: when autoScaling min=0 on Agent platform it should fail
6261
initial: |
@@ -77,7 +76,7 @@ tests:
7776
agent: {}
7877
type: Agent
7978
80-
expectedError: "Scale-from-zero (autoScaling.min=0) is currently only supported for AWS platform"
79+
expectedError: "Scale-from-zero (autoScaling.min=0) is currently only supported for AWS and Azure platforms"
8180

8281
- name: when autoScaling min=0 on KubeVirt platform it should fail
8382
initial: |
@@ -101,7 +100,7 @@ tests:
101100
persistent:
102101
size: 32Gi
103102
type: KubeVirt
104-
expectedError: "Scale-from-zero (autoScaling.min=0) is currently only supported for AWS platform"
103+
expectedError: "Scale-from-zero (autoScaling.min=0) is currently only supported for AWS and Azure platforms"
105104

106105
- name: when autoScaling min=1 on Azure platform it should pass
107106
initial: |

cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-CustomNoUpgrade.crd.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-Default.crd.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-TechPreviewNoUpgrade.crd.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)