Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 41 additions & 5 deletions api/hypershift/v1beta1/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -653,31 +653,38 @@ const (
// AzurePrivateType specifies the type of private connectivity mechanism used for the Azure
// hosted cluster's API server. This acts as the discriminator for the AzurePrivateSpec union.
//
// +kubebuilder:validation:Enum=PrivateLink
// +kubebuilder:validation:Enum=PrivateLink;Swift
type AzurePrivateType string

const (
// AzurePrivateTypePrivateLink specifies private connectivity using Azure Private Link Service.
// In this mode, the operator creates a Private Link Service backed by the management cluster's
// internal load balancer, and a Private Endpoint in the guest VNet for private API server access.
AzurePrivateTypePrivateLink AzurePrivateType = "PrivateLink"

// AzurePrivateTypeSwift specifies private connectivity using Azure Swift pod networking.
// In this mode, Azure Swift assigns a private IP from the customer VNet directly
// to the hosted cluster's router pods, providing private API server access without a
// separate Private Link Service. This is used by ARO HCP managed clusters.
AzurePrivateTypeSwift AzurePrivateType = "Swift"
)

// AzurePrivateSpec configures private connectivity to an Azure hosted cluster's API server.
// It is a discriminated union keyed on the type field, which selects the private connectivity
// mechanism. Currently only PrivateLink is supported; additional mechanisms (e.g., Swift) may
// be added in the future.
// mechanism.
//
// +kubebuilder:validation:XValidation:rule="self.type != 'PrivateLink' ? !has(self.privateLink) : true",message="privateLink is forbidden when type is not PrivateLink"
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.type) || self.type == oldSelf.type",message="type is immutable"
// +kubebuilder:validation:XValidation:rule="self.type == 'PrivateLink' ? has(self.privateLink) : !has(self.privateLink)",message="privateLink is required when type is PrivateLink, and forbidden otherwise"
Comment thread
muraee marked this conversation as resolved.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This tightens validation. The old rule allowed type: PrivateLink without privateLink being set; the new rule requires it. Since PrivateLink AzurePrivateLinkSpec uses json:"privateLink,omitzero" and all its fields are optional, a zero-valued AzurePrivateLinkSpec{} will not serialize the key into the object. So any existing HostedCluster created with type: PrivateLink but no privateLink subfields populated will fail validation on any subsequent update.

The test rename at line 551 of the test suite ("should pass" -> "should fail") confirms this is intentional. Either add a ratcheting test proving existing objects survive updates, or confirm that no cluster exists in this state. Per API conventions, validation tightening requires ensuring writes to existing objects continue to work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

thanks @saschagrunert . This is just a backport so old code can reuse the new APIs. in Prod our CRDs are always deployed from main where the original PR was introduced and has all the tests.

// +kubebuilder:validation:XValidation:rule="self.type == 'Swift' ? has(self.swift) : !has(self.swift)",message="swift is required when type is Swift, and forbidden otherwise"
// +union
type AzurePrivateSpec struct {
// type specifies the private connectivity mechanism used for the hosted cluster's API server.
// "PrivateLink" selects Azure Private Link Service for private API server access.
// "Swift" selects Azure Swift pod networking for private API server access, used by ARO HCP.
// This field is immutable once set.
//
// +unionDiscriminator
// +required
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="type is immutable"
Type AzurePrivateType `json:"type,omitempty"`

// privateLink configures Azure Private Link Service for private API server access.
Expand All @@ -686,6 +693,15 @@ type AzurePrivateSpec struct {
// +optional
// +unionMember
PrivateLink AzurePrivateLinkSpec `json:"privateLink,omitzero"`

// swift configures Azure Swift pod networking for private API server access.
// Swift networking requires the management cluster to be pre-configured with
// Azure Swift support; this is not provisioned by HyperShift automatically.
// This field is required when type is "Swift" and must not be set otherwise.
//
// +optional
// +unionMember
Swift AzureSwiftSpec `json:"swift,omitzero"`
}

// AzurePrivateLinkSpec configures Azure Private Link Service connectivity.
Expand Down Expand Up @@ -716,6 +732,26 @@ type AzurePrivateLinkSpec struct {
AdditionalAllowedSubscriptions []AzureSubscriptionID `json:"additionalAllowedSubscriptions,omitempty"`
}

// AzureSwiftSpec configures Azure Swift pod networking for private API server access.
// Swift assigns a private IP from the customer VNet directly to the hosted cluster's
// router pods, providing private connectivity without a separate Private Link Service.
//
// +kubebuilder:validation:XValidation:rule="self.podNetworkInstance == oldSelf.podNetworkInstance",message="podNetworkInstance is immutable"
type AzureSwiftSpec struct {
// podNetworkInstance is the name of a PodNetworkInstance custom resource in the
// hosted control plane namespace. This resource configures Azure Swift pod networking
// for private connectivity to the hosted cluster's router pods.
// The value must be a valid Kubernetes object name (RFC 1123 DNS label): lowercase
// alphanumeric characters or hyphens, must start and end with an alphanumeric character.
// This field is immutable once set.
//
// +required
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=63
// +kubebuilder:validation:XValidation:rule="self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?$')",message="podNetworkInstance must be a valid DNS label: lowercase alphanumeric characters or hyphens, must start and end with an alphanumeric character"
PodNetworkInstance string `json:"podNetworkInstance,omitempty"`
}

// ControlPlaneManagedIdentities contains the managed identities on the HCP control plane needing to authenticate with
// Azure's API.
type ControlPlaneManagedIdentities struct {
Expand Down
16 changes: 16 additions & 0 deletions api/hypershift/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5047,24 +5047,58 @@ spec:
(e.g., /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnet}/subnets/{subnet})
rule: self.matches('^/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft\\.Network/virtualNetworks/[^/]+/subnets/[^/]+$')
type: object
swift:
description: |-
swift configures Azure Swift pod networking for private API server access.
Swift networking requires the management cluster to be pre-configured with
Azure Swift support; this is not provisioned by HyperShift automatically.
This field is required when type is "Swift" and must not be set otherwise.
properties:
podNetworkInstance:
description: |-
podNetworkInstance is the name of a PodNetworkInstance custom resource in the
hosted control plane namespace. This resource configures Azure Swift pod networking
for private connectivity to the hosted cluster's router pods.
The value must be a valid Kubernetes object name (RFC 1123 DNS label): lowercase
alphanumeric characters or hyphens, must start and end with an alphanumeric character.
This field is immutable once set.
maxLength: 63
minLength: 1
type: string
x-kubernetes-validations:
- message: 'podNetworkInstance must be a valid DNS
label: lowercase alphanumeric characters or hyphens,
must start and end with an alphanumeric character'
rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?$')
required:
- podNetworkInstance
type: object
x-kubernetes-validations:
- message: podNetworkInstance is immutable
rule: self.podNetworkInstance == oldSelf.podNetworkInstance
type:
description: |-
type specifies the private connectivity mechanism used for the hosted cluster's API server.
"PrivateLink" selects Azure Private Link Service for private API server access.
"Swift" selects Azure Swift pod networking for private API server access, used by ARO HCP.
This field is immutable once set.
enum:
- PrivateLink
- Swift
type: string
x-kubernetes-validations:
- message: type is immutable
rule: self == oldSelf
required:
- type
type: object
x-kubernetes-validations:
- message: privateLink is forbidden when type is not PrivateLink
rule: 'self.type != ''PrivateLink'' ? !has(self.privateLink)
: true'
- message: type is immutable
rule: '!has(oldSelf.type) || self.type == oldSelf.type'
- message: privateLink is required when type is PrivateLink,
and forbidden otherwise
rule: 'self.type == ''PrivateLink'' ? has(self.privateLink)
: !has(self.privateLink)'
- message: swift is required when type is Swift, and forbidden
otherwise
rule: 'self.type == ''Swift'' ? has(self.swift) : !has(self.swift)'
resourceGroup:
default: default
description: |-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5174,24 +5174,58 @@ spec:
(e.g., /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnet}/subnets/{subnet})
rule: self.matches('^/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft\\.Network/virtualNetworks/[^/]+/subnets/[^/]+$')
type: object
swift:
description: |-
swift configures Azure Swift pod networking for private API server access.
Swift networking requires the management cluster to be pre-configured with
Azure Swift support; this is not provisioned by HyperShift automatically.
This field is required when type is "Swift" and must not be set otherwise.
properties:
podNetworkInstance:
description: |-
podNetworkInstance is the name of a PodNetworkInstance custom resource in the
hosted control plane namespace. This resource configures Azure Swift pod networking
for private connectivity to the hosted cluster's router pods.
The value must be a valid Kubernetes object name (RFC 1123 DNS label): lowercase
alphanumeric characters or hyphens, must start and end with an alphanumeric character.
This field is immutable once set.
maxLength: 63
minLength: 1
type: string
x-kubernetes-validations:
- message: 'podNetworkInstance must be a valid DNS
label: lowercase alphanumeric characters or hyphens,
must start and end with an alphanumeric character'
rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?$')
required:
- podNetworkInstance
type: object
x-kubernetes-validations:
- message: podNetworkInstance is immutable
rule: self.podNetworkInstance == oldSelf.podNetworkInstance
type:
description: |-
type specifies the private connectivity mechanism used for the hosted cluster's API server.
"PrivateLink" selects Azure Private Link Service for private API server access.
"Swift" selects Azure Swift pod networking for private API server access, used by ARO HCP.
This field is immutable once set.
enum:
- PrivateLink
- Swift
type: string
x-kubernetes-validations:
- message: type is immutable
rule: self == oldSelf
required:
- type
type: object
x-kubernetes-validations:
- message: privateLink is forbidden when type is not PrivateLink
rule: 'self.type != ''PrivateLink'' ? !has(self.privateLink)
: true'
- message: type is immutable
rule: '!has(oldSelf.type) || self.type == oldSelf.type'
- message: privateLink is required when type is PrivateLink,
and forbidden otherwise
rule: 'self.type == ''PrivateLink'' ? has(self.privateLink)
: !has(self.privateLink)'
- message: swift is required when type is Swift, and forbidden
otherwise
rule: 'self.type == ''Swift'' ? has(self.swift) : !has(self.swift)'
resourceGroup:
default: default
description: |-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5038,24 +5038,58 @@ spec:
(e.g., /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnet}/subnets/{subnet})
rule: self.matches('^/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft\\.Network/virtualNetworks/[^/]+/subnets/[^/]+$')
type: object
swift:
description: |-
swift configures Azure Swift pod networking for private API server access.
Swift networking requires the management cluster to be pre-configured with
Azure Swift support; this is not provisioned by HyperShift automatically.
This field is required when type is "Swift" and must not be set otherwise.
properties:
podNetworkInstance:
description: |-
podNetworkInstance is the name of a PodNetworkInstance custom resource in the
hosted control plane namespace. This resource configures Azure Swift pod networking
for private connectivity to the hosted cluster's router pods.
The value must be a valid Kubernetes object name (RFC 1123 DNS label): lowercase
alphanumeric characters or hyphens, must start and end with an alphanumeric character.
This field is immutable once set.
maxLength: 63
minLength: 1
type: string
x-kubernetes-validations:
- message: 'podNetworkInstance must be a valid DNS
label: lowercase alphanumeric characters or hyphens,
must start and end with an alphanumeric character'
rule: self.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?$')
required:
- podNetworkInstance
type: object
x-kubernetes-validations:
- message: podNetworkInstance is immutable
rule: self.podNetworkInstance == oldSelf.podNetworkInstance
type:
description: |-
type specifies the private connectivity mechanism used for the hosted cluster's API server.
"PrivateLink" selects Azure Private Link Service for private API server access.
"Swift" selects Azure Swift pod networking for private API server access, used by ARO HCP.
This field is immutable once set.
enum:
- PrivateLink
- Swift
type: string
x-kubernetes-validations:
- message: type is immutable
rule: self == oldSelf
required:
- type
type: object
x-kubernetes-validations:
- message: privateLink is forbidden when type is not PrivateLink
rule: 'self.type != ''PrivateLink'' ? !has(self.privateLink)
: true'
- message: type is immutable
rule: '!has(oldSelf.type) || self.type == oldSelf.type'
- message: privateLink is required when type is PrivateLink,
and forbidden otherwise
rule: 'self.type == ''PrivateLink'' ? has(self.privateLink)
: !has(self.privateLink)'
- message: swift is required when type is Swift, and forbidden
otherwise
rule: 'self.type == ''Swift'' ? has(self.swift) : !has(self.swift)'
resourceGroup:
default: default
description: |-
Expand Down
Loading
Loading