diff --git a/api/hypershift/v1beta1/azure.go b/api/hypershift/v1beta1/azure.go index 76c9a3efbab..c95773e13bd 100644 --- a/api/hypershift/v1beta1/azure.go +++ b/api/hypershift/v1beta1/azure.go @@ -653,7 +653,7 @@ 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 ( @@ -661,23 +661,30 @@ const ( // 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="!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" +// +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. @@ -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. @@ -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 { diff --git a/api/hypershift/v1beta1/hostedcluster_conditions.go b/api/hypershift/v1beta1/hostedcluster_conditions.go index 665eeb4ef66..9fda11a60a2 100644 --- a/api/hypershift/v1beta1/hostedcluster_conditions.go +++ b/api/hypershift/v1beta1/hostedcluster_conditions.go @@ -252,6 +252,19 @@ const ( // **False / AutoNodeProgressing** means AutoNode is being enabled or disabled — the operation is in progress. // **False / AutoNodeNotConfigured** means AutoNode is not configured in the spec and all Karpenter components have been removed. AutoNodeEnabled ConditionType = "AutoNodeEnabled" + + // PublicEndpointExposed indicates whether public API server endpoints are + // currently configured and exposed for this cluster via the management + // cluster's shared ingress. Status reflects observed state: True means + // public endpoints are reachable, False means they are not. + PublicEndpointExposed ConditionType = "PublicEndpointExposed" +) + +// Reasons for PublicEndpointExposed condition. +const ( + PublicEndpointSharedIngressConfiguredReason = "SharedIngressConfigured" + PublicEndpointTopologyPrivateReason = "TopologyPrivate" + PublicEndpointConvergenceInProgressReason = "ConvergenceInProgress" ) // Reasons. diff --git a/api/hypershift/v1beta1/zz_generated.deepcopy.go b/api/hypershift/v1beta1/zz_generated.deepcopy.go index a3d882374d2..c022c3e918d 100644 --- a/api/hypershift/v1beta1/zz_generated.deepcopy.go +++ b/api/hypershift/v1beta1/zz_generated.deepcopy.go @@ -863,6 +863,7 @@ func (in *AzurePrivateLinkSpec) DeepCopy() *AzurePrivateLinkSpec { func (in *AzurePrivateSpec) DeepCopyInto(out *AzurePrivateSpec) { *out = *in in.PrivateLink.DeepCopyInto(&out.PrivateLink) + out.Swift = in.Swift } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzurePrivateSpec. @@ -892,6 +893,21 @@ func (in *AzureResourceManagedIdentities) DeepCopy() *AzureResourceManagedIdenti return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AzureSwiftSpec) DeepCopyInto(out *AzureSwiftSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureSwiftSpec. +func (in *AzureSwiftSpec) DeepCopy() *AzureSwiftSpec { + if in == nil { + return nil + } + out := new(AzureSwiftSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AzureVMImage) DeepCopyInto(out *AzureVMImage) { *out = *in diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml index e5e928dc898..4ed2391e13e 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml @@ -5276,25 +5276,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterUpdateAcceptRisks.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterUpdateAcceptRisks.yaml index 40083476fa4..9185fb00d93 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterUpdateAcceptRisks.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterUpdateAcceptRisks.yaml @@ -5267,25 +5267,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml index 955788dbad9..2269797a21d 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml @@ -5287,25 +5287,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml index fe08c90b5c2..0a1a136fa30 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml @@ -5599,25 +5599,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml index 6afcef0d203..cebc53316ac 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml @@ -5739,25 +5739,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUpstreamParity.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUpstreamParity.yaml index 9faf2cdb0f5..1270fd8cb1f 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUpstreamParity.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUpstreamParity.yaml @@ -5730,25 +5730,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml index 990cee3aae3..f7170ecada7 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml @@ -5267,25 +5267,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HCPEtcdBackup.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HCPEtcdBackup.yaml index abe0886f01f..fd458cb1f13 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HCPEtcdBackup.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HCPEtcdBackup.yaml @@ -5332,25 +5332,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml index 76cee1f00bd..461ae7dc798 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml @@ -5289,25 +5289,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml index bf1e2c27397..f741a117e78 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml @@ -5285,25 +5285,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml index a1263ec4683..33c70e1bc31 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml @@ -5343,25 +5343,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml index 93eee39d119..bdb6610a924 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml @@ -5267,25 +5267,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/TLSAdherence.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/TLSAdherence.yaml index 377f44044e1..517516cd2f4 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/TLSAdherence.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/TLSAdherence.yaml @@ -5307,25 +5307,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml index 1d833e21ca6..7faf853bd17 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml @@ -5156,25 +5156,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterUpdateAcceptRisks.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterUpdateAcceptRisks.yaml index 8194e7799d5..927f2b9ffc2 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterUpdateAcceptRisks.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterUpdateAcceptRisks.yaml @@ -5147,25 +5147,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml index ee97b0bf9ea..ad6e7742c0e 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml @@ -5167,25 +5167,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml index 03882677840..1b9da7de525 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml @@ -5479,25 +5479,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml index 31cb9e39a95..3cd3503473b 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml @@ -5619,25 +5619,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUpstreamParity.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUpstreamParity.yaml index dac1ead4844..9d7a73cb3bf 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUpstreamParity.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUpstreamParity.yaml @@ -5610,25 +5610,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml index a862e1dc02f..1527b355549 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml @@ -5147,25 +5147,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HCPEtcdBackup.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HCPEtcdBackup.yaml index f8dc77d0c2e..36a11500968 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HCPEtcdBackup.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HCPEtcdBackup.yaml @@ -5212,25 +5212,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml index 667923bb2e9..5ea38844b58 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml @@ -5169,25 +5169,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml index 55a2555f888..9de4ad90ead 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml @@ -5165,25 +5165,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml index 4dcb4e6c362..db3f3840a8c 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml @@ -5223,25 +5223,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml index da6e7167b43..c3c0b64fcf2 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml @@ -5147,25 +5147,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: 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: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/TLSAdherence.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/TLSAdherence.yaml index 75d60b7d459..e52cbe485e1 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/TLSAdherence.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/TLSAdherence.yaml @@ -5187,25 +5187,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: 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: |- diff --git a/client/applyconfiguration/hypershift/v1beta1/azureprivatespec.go b/client/applyconfiguration/hypershift/v1beta1/azureprivatespec.go index 3fe2eae5bc0..5d65112e28d 100644 --- a/client/applyconfiguration/hypershift/v1beta1/azureprivatespec.go +++ b/client/applyconfiguration/hypershift/v1beta1/azureprivatespec.go @@ -26,6 +26,7 @@ import ( type AzurePrivateSpecApplyConfiguration struct { Type *hypershiftv1beta1.AzurePrivateType `json:"type,omitempty"` PrivateLink *AzurePrivateLinkSpecApplyConfiguration `json:"privateLink,omitempty"` + Swift *AzureSwiftSpecApplyConfiguration `json:"swift,omitempty"` } // AzurePrivateSpecApplyConfiguration constructs a declarative configuration of the AzurePrivateSpec type for use with @@ -49,3 +50,11 @@ func (b *AzurePrivateSpecApplyConfiguration) WithPrivateLink(value *AzurePrivate b.PrivateLink = value return b } + +// WithSwift sets the Swift field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Swift field is set to the value of the last call. +func (b *AzurePrivateSpecApplyConfiguration) WithSwift(value *AzureSwiftSpecApplyConfiguration) *AzurePrivateSpecApplyConfiguration { + b.Swift = value + return b +} diff --git a/client/applyconfiguration/hypershift/v1beta1/azureswiftspec.go b/client/applyconfiguration/hypershift/v1beta1/azureswiftspec.go new file mode 100644 index 00000000000..d328964e02b --- /dev/null +++ b/client/applyconfiguration/hypershift/v1beta1/azureswiftspec.go @@ -0,0 +1,38 @@ +/* + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1beta1 + +// AzureSwiftSpecApplyConfiguration represents a declarative configuration of the AzureSwiftSpec type for use +// with apply. +type AzureSwiftSpecApplyConfiguration struct { + PodNetworkInstance *string `json:"podNetworkInstance,omitempty"` +} + +// AzureSwiftSpecApplyConfiguration constructs a declarative configuration of the AzureSwiftSpec type for use with +// apply. +func AzureSwiftSpec() *AzureSwiftSpecApplyConfiguration { + return &AzureSwiftSpecApplyConfiguration{} +} + +// WithPodNetworkInstance sets the PodNetworkInstance field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the PodNetworkInstance field is set to the value of the last call. +func (b *AzureSwiftSpecApplyConfiguration) WithPodNetworkInstance(value string) *AzureSwiftSpecApplyConfiguration { + b.PodNetworkInstance = &value + return b +} diff --git a/client/applyconfiguration/utils.go b/client/applyconfiguration/utils.go index 6c7a8f85bb0..cee82f9177f 100644 --- a/client/applyconfiguration/utils.go +++ b/client/applyconfiguration/utils.go @@ -133,6 +133,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &hypershiftv1beta1.AzurePrivateSpecApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("AzureResourceManagedIdentities"): return &hypershiftv1beta1.AzureResourceManagedIdentitiesApplyConfiguration{} + case v1beta1.SchemeGroupVersion.WithKind("AzureSwiftSpec"): + return &hypershiftv1beta1.AzureSwiftSpecApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("AzureVMImage"): return &hypershiftv1beta1.AzureVMImageApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("AzureWorkloadIdentities"): diff --git a/cmd/install/assets/crds/hypershift-operator/tests/hostedclusters.hypershift.openshift.io/stable.hostedclusters.azure.testsuite.yaml b/cmd/install/assets/crds/hypershift-operator/tests/hostedclusters.hypershift.openshift.io/stable.hostedclusters.azure.testsuite.yaml index 84fbbe40b96..d8833e0ac52 100644 --- a/cmd/install/assets/crds/hypershift-operator/tests/hostedclusters.hypershift.openshift.io/stable.hostedclusters.azure.testsuite.yaml +++ b/cmd/install/assets/crds/hypershift-operator/tests/hostedclusters.hypershift.openshift.io/stable.hostedclusters.azure.testsuite.yaml @@ -955,3 +955,1019 @@ tests: type: Route route: {} expectedError: "private is required when topology is Private or PublicAndPrivate, and forbidden otherwise" + # --- Azure Swift private networking validation --- + - name: When Private.Type is Swift with valid Swift spec it should pass + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: PublicAndPrivate + private: + type: Swift + swift: + podNetworkInstance: "test-pni" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + + - name: When Private.Type is Swift but privateLink is also set it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: PublicAndPrivate + private: + type: Swift + swift: + podNetworkInstance: "test-pni" + privateLink: + natSubnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/nat-subnet" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + expectedError: "privateLink is required when type is PrivateLink, and forbidden otherwise" + + - name: When Private.Type is Swift but swift spec is missing it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: PublicAndPrivate + private: + type: Swift + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + expectedError: "swift is required when type is Swift, and forbidden otherwise" + + - name: When Private.Type is PrivateLink but swift is also set it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: Private + private: + type: PrivateLink + privateLink: + natSubnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/nat-subnet" + swift: + podNetworkInstance: "test-pni" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + expectedError: "swift is required when type is Swift, and forbidden otherwise" + + - name: When Topology is Private with Private.Type Swift it should pass + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: Private + private: + type: Swift + swift: + podNetworkInstance: "test-pni" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + + onUpdate: + # --- Azure Swift private networking immutability --- + - name: When Private.Type changes from PrivateLink to Swift it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: Private + private: + type: PrivateLink + privateLink: + natSubnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/nat-subnet" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + updated: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: Private + private: + type: Swift + swift: + podNetworkInstance: "test-pni" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + expectedError: "type is immutable" + + - name: When Swift.PodNetworkInstance changes it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: PublicAndPrivate + private: + type: Swift + swift: + podNetworkInstance: "pni-old" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + updated: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: PublicAndPrivate + private: + type: Swift + swift: + podNetworkInstance: "pni-new" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + expectedError: "podNetworkInstance is immutable" + + - name: When Topology changes from PublicAndPrivate to Private it should pass + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: PublicAndPrivate + private: + type: Swift + swift: + podNetworkInstance: "test-pni" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + updated: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: Private + private: + type: Swift + swift: + podNetworkInstance: "test-pni" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + + - name: When Topology changes from Private to PublicAndPrivate it should pass + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: Private + private: + type: Swift + swift: + podNetworkInstance: "test-pni" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + updated: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: PublicAndPrivate + private: + type: Swift + swift: + podNetworkInstance: "test-pni" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + + - name: When Topology changes from Private to Public it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: Private + private: + type: Swift + swift: + podNetworkInstance: "test-pni" + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + updated: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + dns: + baseDomain: example.com + platform: + type: Azure + azure: + location: eastus + resourceGroupName: test-rg + vnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet" + subnetID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-subnet" + subscriptionID: "12345678-1234-5678-9012-123456789012" + securityGroupID: "/subscriptions/12345678-1234-5678-9012-123456789012/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg" + tenantID: "87654321-4321-8765-2109-876543210987" + topology: Public + azureAuthenticationConfig: + azureAuthenticationConfigType: WorkloadIdentities + workloadIdentities: + imageRegistry: + clientID: "12345678-1234-5678-9012-123456789012" + ingress: + clientID: "12345678-1234-5678-9012-123456789012" + file: + clientID: "12345678-1234-5678-9012-123456789012" + disk: + clientID: "12345678-1234-5678-9012-123456789012" + nodePoolManagement: + clientID: "12345678-1234-5678-9012-123456789012" + cloudProvider: + clientID: "12345678-1234-5678-9012-123456789012" + network: + clientID: "12345678-1234-5678-9012-123456789012" + controlPlaneOperator: + clientID: "12345678-1234-5678-9012-123456789012" + pullSecret: + name: secret + release: + image: quay.io/openshift-release-dev/ocp-release:4.15.11-x86_64 + secretEncryption: + aescbc: + activeKey: + name: key + type: aescbc + services: + - service: APIServer + servicePublishingStrategy: + type: Route + route: {} + - service: OAuthServer + servicePublishingStrategy: + type: Route + route: {} + - service: Konnectivity + servicePublishingStrategy: + type: Route + route: {} + - service: Ignition + servicePublishingStrategy: + type: Route + route: {} + expectedError: "transitions between Public and non-Public topology are not supported" diff --git a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml index 742c4609575..d406b89a759 100644 --- a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml +++ b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml @@ -6118,25 +6118,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: 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: |- diff --git a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml index b70562b4dbf..bbafc3f882a 100644 --- a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml +++ b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml @@ -5768,25 +5768,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: 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: |- diff --git a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml index c56f7d18bce..30d17382b0f 100644 --- a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml +++ b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml @@ -5989,25 +5989,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: 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: |- diff --git a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml index 8fed73ad00d..798d4f0664f 100644 --- a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml +++ b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml @@ -5998,25 +5998,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: 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: |- diff --git a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml index ac2928451c8..5fd583a45ff 100644 --- a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml +++ b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml @@ -5648,25 +5648,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: 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: |- diff --git a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml index a2f47dbfdca..25068f5cf7f 100644 --- a/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml +++ b/cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml @@ -5869,25 +5869,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: 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: |- diff --git a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go index 9337ae39d11..23f391db605 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go +++ b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go @@ -3029,7 +3029,7 @@ func (r *HostedControlPlaneReconciler) validateAzureKMSConfig(ctx context.Contex } azureKmsSpec := hcp.Spec.SecretEncryption.KMS.Azure - if hyperazureutil.IsAroHCP() { + if hyperazureutil.IsAroHCPByHCP(hcp) { key := hcp.Namespace + kmsAzureCredentials // We need to only store the Azure credentials once and reuse them after that. diff --git a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go index 7fbcdb4032c..d09a4c7dba7 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go +++ b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go @@ -1079,6 +1079,14 @@ func TestControlPlaneComponents(t *testing.T) { hyperv1.SwiftPodNetworkInstanceAnnotation: "swift-network-instance", }, mutateHCP: func(hcp *hyperv1.HostedControlPlane) { + // Configure Swift API fields for ARO-HCP + hcp.Spec.Platform.Azure.Private = hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "swift-network-instance", + }, + } + hcp.Spec.Platform.Azure.Topology = hyperv1.AzureTopologyPublicAndPrivate // Configure Azure KMS for ARO-HCP hcp.Spec.Platform.Azure.Cloud = "AzurePublicCloud" hcp.Spec.SecretEncryption = &hyperv1.SecretEncryptionSpec{ diff --git a/control-plane-operator/controllers/hostedcontrolplane/infra/infra.go b/control-plane-operator/controllers/hostedcontrolplane/infra/infra.go index 6f5f85a5190..e299d9e5680 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/infra/infra.go +++ b/control-plane-operator/controllers/hostedcontrolplane/infra/infra.go @@ -15,7 +15,6 @@ import ( "github.com/openshift/hypershift/control-plane-operator/controllers/hostedcontrolplane/oauth" routerutil "github.com/openshift/hypershift/control-plane-operator/controllers/hostedcontrolplane/v2/router/util" sharedingress "github.com/openshift/hypershift/hypershift-operator/controllers/sharedingress" - hyperazureutil "github.com/openshift/hypershift/support/azureutil" "github.com/openshift/hypershift/support/config" "github.com/openshift/hypershift/support/events" "github.com/openshift/hypershift/support/k8sutil" @@ -454,9 +453,9 @@ func (r *Reconciler) reconcileHCPRouterServices(ctx context.Context, hcp *hyperv return nil } - // ARO HCP doesn't need LB services; Swift handles connectivity. - // Only reconcile a ClusterIP private router service. - if hyperazureutil.IsAroHCP() { + // ARO HCP doesn't need LB services; shared ingress or Swift handles + // connectivity. Only reconcile a ClusterIP private router service. + if netutil.UseSwiftNetworkingHCP(hcp) || netutil.UseSharedIngressHCP(hcp) { if _, err := k8sutil.DeleteIfNeeded(ctx, r.Client, pubSvc); err != nil { return fmt.Errorf("failed to delete public router service: %w", err) } @@ -527,7 +526,7 @@ func (r *Reconciler) reconcileAPIServerServiceStatus(ctx context.Context, hcp *h return "", 0, "", errors.New("APIServer service strategy not specified") } - if sharedingress.UseSharedIngress() || (hcp.Spec.Platform.Type == hyperv1.IBMCloudPlatform && serviceStrategy.Type == hyperv1.Route) { + if netutil.UseSharedIngressHCP(hcp) || netutil.UseSwiftNetworkingHCP(hcp) || (hcp.Spec.Platform.Type == hyperv1.IBMCloudPlatform && serviceStrategy.Type == hyperv1.Route) { return sharedingress.KasRouteHostname(hcp), sharedingress.ExternalDNSLBPort, "", nil } @@ -684,15 +683,15 @@ func (r *Reconciler) reconcileClusterIPServiceStatus(ctx context.Context, svc *c } func (r *Reconciler) reconcileInternalRouterServiceStatus(ctx context.Context, hcp *hyperv1.HostedControlPlane) (host string, needed bool, message string, err error) { - // ARO is always private but there's no router service. Connection goes through swift. - if !netutil.IsPrivateHCP(hcp) || hyperazureutil.IsAroHCP() || hcp.Spec.Platform.Type == hyperv1.IBMCloudPlatform { + // Skip when not private, or when shared ingress / Swift handles connectivity, or IBM Cloud. + if !netutil.IsPrivateHCP(hcp) || netutil.UseSwiftNetworkingHCP(hcp) || netutil.UseSharedIngressHCP(hcp) || hcp.Spec.Platform.Type == hyperv1.IBMCloudPlatform { return } return r.reconcileRouterServiceStatus(ctx, manifests.PrivateRouterService(hcp.Namespace), events.NewMessageCollector(ctx, r.Client)) } func (r *Reconciler) reconcileExternalRouterServiceStatus(ctx context.Context, hcp *hyperv1.HostedControlPlane) (host string, needed bool, message string, err error) { - if !netutil.IsPublicHCP(hcp) || !netutil.LabelHCPRoutes(hcp) || sharedingress.UseSharedIngress() || hcp.Spec.Platform.Type == hyperv1.IBMCloudPlatform { + if !netutil.IsPublicHCP(hcp) || !netutil.LabelHCPRoutes(hcp) || netutil.UseSharedIngressHCP(hcp) || hcp.Spec.Platform.Type == hyperv1.IBMCloudPlatform { return } return r.reconcileRouterServiceStatus(ctx, manifests.RouterPublicService(hcp.Namespace), events.NewMessageCollector(ctx, r.Client)) diff --git a/control-plane-operator/controllers/hostedcontrolplane/infra/infra_test.go b/control-plane-operator/controllers/hostedcontrolplane/infra/infra_test.go index 1636e722d9b..76b6e254119 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/infra/infra_test.go +++ b/control-plane-operator/controllers/hostedcontrolplane/infra/infra_test.go @@ -536,11 +536,17 @@ func TestReconcileInfrastructure(t *testing.T) { }, // ARO HCP test cases - use shared ingress { - name: "ARO_Route_SharedIngress", - hcp: withServices( - baseAzureHCP(), - allServicesRouteWithHostnames(), - ), + name: "ARO_Route_SharedIngress_AnnotationFallback", + hcp: func() *hyperv1.HostedControlPlane { + hcp := withServices(baseAzureHCP(), allServicesRouteWithHostnames()) + hcp.Annotations = map[string]string{ + hyperv1.SwiftPodNetworkInstanceAnnotation: "swift-network-instance", + } + hcp.Spec.Platform.Azure.AzureAuthenticationConfig = hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + } + return hcp + }(), setupEnv: func(t *testing.T) { t.Setenv("MANAGED_SERVICE", hyperv1.AroHCP) }, @@ -562,23 +568,58 @@ func TestReconcileInfrastructure(t *testing.T) { }, }, { - name: "ARO_Route_SharedIngress_And_Swift", + name: "ARO_Route_Swift_PublicAndPrivate", + hcp: func() *hyperv1.HostedControlPlane { + hcp := withServices(baseAzureHCP(), allServicesRouteWithHostnames()) + hcp.Spec.Platform.Azure.Topology = hyperv1.AzureTopologyPublicAndPrivate + hcp.Spec.Platform.Azure.Private = hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + } + hcp.Spec.Platform.Azure.AzureAuthenticationConfig = hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + } + return hcp + }(), + expectError: false, + // New path: Swift detected via Private.Type=Swift API field with PublicAndPrivate topology. + // shared ingress for public access, internal router for private access. + expectedStatus: &InfrastructureStatus{ + APIHost: testKASHostname, + APIPort: 443, + OAuthEnabled: true, + OAuthHost: testOAuthHostname, + OAuthPort: 443, + KonnectivityHost: testKonnectivityHost, + KonnectivityPort: 443, + NeedInternalRouter: false, + NeedExternalRouter: false, + }, + }, + { + name: "ARO_Route_Swift_Private", hcp: func() *hyperv1.HostedControlPlane { hcp := withServices(baseAzureHCP(), allServicesRouteWithHostnames()) hcp.Annotations = map[string]string{ hyperv1.SwiftPodNetworkInstanceAnnotation: "swift-network-instance", } + hcp.Spec.Platform.Azure.Topology = hyperv1.AzureTopologyPrivate + hcp.Spec.Platform.Azure.Private = hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "swift-network-instance", + }, + } + hcp.Spec.Platform.Azure.AzureAuthenticationConfig = hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + } return hcp }(), - setupEnv: func(t *testing.T) { - t.Setenv("MANAGED_SERVICE", hyperv1.AroHCP) - }, expectError: false, - // For ARO with Swift: - // - Swift handles pod networking, so no router services are needed - // - APIHost comes from shared ingress (KasRouteHostname) - // - Port is 443 (ExternalDNSLBPort) - // - Konnectivity (and ignition see v2/ignitionserver) Routes use hypershift.local, kas and auth use both hypershift.local and external routes + // Swift detected via Private.Type=Swift API field with Private topology. + // No shared ingress needed, internal router needed. expectedStatus: &InfrastructureStatus{ APIHost: testKASHostname, APIPort: 443, @@ -596,7 +637,7 @@ func TestReconcileInfrastructure(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { g := NewGomegaWithT(t) - ctx := context.Background() + ctx := t.Context() // Run optional environment setup if tc.setupEnv != nil { @@ -676,18 +717,26 @@ func TestReconcileInfrastructure(t *testing.T) { // It unconditionally tries to provision all possible services/routes, ignoring "not found" errors. func simulateInfraProvisioning(ctx context.Context, c client.Client, hcp *hyperv1.HostedControlPlane, externalRouterLBHost, internalRouterLBHost, kasLBHost string) error { // List of all LoadBalancer services that might need provisioning - lbServices := []struct { + type lbService struct { svc *corev1.Service hostname string - }{ - {manifests.RouterPublicService(hcp.Namespace), externalRouterLBHost}, - {manifests.PrivateRouterService(hcp.Namespace), internalRouterLBHost}, + } + lbServices := []lbService{ {manifests.KubeAPIServerService(hcp.Namespace), kasLBHost}, {manifests.KubeAPIServerPrivateService(hcp.Namespace), kasLBHost}, {manifests.KubeAPIServerServiceAzureLB(hcp.Namespace), kasLBHost}, {manifests.OauthServerService(hcp.Namespace), testOAuthLBHostname}, } + // If not using Swift or shared ingress, provision the public and private router services as LB services + // Otherwise, only private-router service is created as ClusterIP service. + if !netutil.UseSwiftNetworkingHCP(hcp) && !netutil.UseSharedIngressHCP(hcp) { + lbServices = append(lbServices, []lbService{ + {manifests.RouterPublicService(hcp.Namespace), externalRouterLBHost}, + {manifests.PrivateRouterService(hcp.Namespace), internalRouterLBHost}, + }...) + } + for _, lb := range lbServices { if err := simulateLBServiceProvisioned(ctx, c, lb.svc, lb.hostname); err != nil { if !apierrors.IsNotFound(err) { @@ -1573,20 +1622,84 @@ func TestReconcileHCPRouterServices(t *testing.T) { expectedServices: nil, }, { - name: "When ARO is enabled it should not create any services", + name: "When ARO with Swift annotation fallback it should create only a ClusterIP private router service", endpointAccess: hyperv1.Public, exposeAPIServerThroughRouter: true, - expectedServices: nil, + expectedServices: []corev1.Service{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "private-router", + Namespace: namespace, + Labels: map[string]string{"app": "private-router"}, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeClusterIP, + Selector: map[string]string{"app": "private-router"}, + Ports: []corev1.ServicePort{ + { + Name: "https", + Port: 443, + TargetPort: intstr.FromString("https"), + Protocol: corev1.ProtocolTCP, + }, + }, + }, + }, + }, setupEnv: func(t *testing.T) { t.Setenv("MANAGED_SERVICE", hyperv1.AroHCP) }, hcpModifier: func(hcp *hyperv1.HostedControlPlane) { hcp.Spec.Platform.Type = hyperv1.AzurePlatform hcp.Spec.Platform.AWS = nil + hcp.Annotations = map[string]string{ + hyperv1.SwiftPodNetworkInstanceAnnotation: "swift-network-instance", + } }, }, { - name: "When ARO with Swift is enabled it should create only a ClusterIP private router service", + name: "When ARO with Swift API fields it should create only a ClusterIP private router service", + endpointAccess: hyperv1.Public, + exposeAPIServerThroughRouter: true, + expectedServices: []corev1.Service{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "private-router", + Namespace: namespace, + Labels: map[string]string{"app": "private-router"}, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeClusterIP, + Selector: map[string]string{"app": "private-router"}, + Ports: []corev1.ServicePort{ + { + Name: "https", + Port: 443, + TargetPort: intstr.FromString("https"), + Protocol: corev1.ProtocolTCP, + }, + }, + }, + }, + }, + setupEnv: func(t *testing.T) { + t.Setenv("MANAGED_SERVICE", hyperv1.AroHCP) + }, + hcpModifier: func(hcp *hyperv1.HostedControlPlane) { + hcp.Spec.Platform.Type = hyperv1.AzurePlatform + hcp.Spec.Platform.AWS = nil + hcp.Spec.Platform.Azure = &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + } + }, + }, + { + name: "When ARO with both Swift annotation and API fields it should create only a ClusterIP private router service", endpointAccess: hyperv1.Public, exposeAPIServerThroughRouter: true, expectedServices: []corev1.Service{ @@ -1619,6 +1732,14 @@ func TestReconcileHCPRouterServices(t *testing.T) { hcp.Annotations = map[string]string{ hyperv1.SwiftPodNetworkInstanceAnnotation: "swift-network-instance", } + hcp.Spec.Platform.Azure = &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "swift-network-instance", + }, + }, + } }, }, } @@ -1788,7 +1909,58 @@ func TestReconcileInternalRouterServiceStatus(t *testing.T) { wantMsg string }{ { - name: "When ARO swift is enabled it should not need internal router", + name: "When ARO swift is enabled via annotation fallback it should not need internal router", + setup: func(t *testing.T) { + t.Setenv("MANAGED_SERVICE", hyperv1.AroHCP) + }, + hcp: &hyperv1.HostedControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-hcp", + Namespace: "test-namespace", + Annotations: map[string]string{ + hyperv1.SwiftPodNetworkInstanceAnnotation: "swift-network-instance", + }, + }, + Spec: hyperv1.HostedControlPlaneSpec{ + Platform: hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Location: "eastus", + }, + }, + }, + }, + wantNeeded: false, + }, + { + name: "When ARO swift is enabled via API field it should not need internal router", + setup: func(t *testing.T) { + t.Setenv("MANAGED_SERVICE", hyperv1.AroHCP) + }, + hcp: &hyperv1.HostedControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-hcp", + Namespace: "test-namespace", + }, + Spec: hyperv1.HostedControlPlaneSpec{ + Platform: hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Location: "eastus", + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "swift-network-instance", + }, + }, + }, + }, + }, + }, + wantNeeded: false, + }, + { + name: "When ARO swift is enabled via both annotation and API field it should not need internal router", setup: func(t *testing.T) { t.Setenv("MANAGED_SERVICE", hyperv1.AroHCP) }, @@ -1805,6 +1977,12 @@ func TestReconcileInternalRouterServiceStatus(t *testing.T) { Type: hyperv1.AzurePlatform, Azure: &hyperv1.AzurePlatformSpec{ Location: "eastus", + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "swift-network-instance", + }, + }, }, }, }, diff --git a/control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_SharedIngress_And_Swift.yaml b/control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_SharedIngress_AnnotationFallback.yaml similarity index 100% rename from control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_SharedIngress_And_Swift.yaml rename to control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_SharedIngress_AnnotationFallback.yaml diff --git a/control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_Swift_Private.yaml b/control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_Swift_Private.yaml new file mode 100644 index 00000000000..77f150075ce --- /dev/null +++ b/control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_Swift_Private.yaml @@ -0,0 +1,284 @@ +routes: + items: + - metadata: + annotations: + haproxy.router.openshift.io/balance: roundrobin + labels: + hypershift.openshift.io/hosted-control-plane: test-namespace + hypershift.openshift.io/internal-route: "true" + name: konnectivity-server + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + host: konnectivity-server.apps.test-cluster.hypershift.local + tls: + insecureEdgeTerminationPolicy: None + termination: passthrough + to: + kind: Service + name: konnectivity-server + weight: null + status: {} + - metadata: + labels: + hypershift.openshift.io/hosted-control-plane: test-namespace + hypershift.openshift.io/internal-route: "true" + name: kube-apiserver-internal + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + host: api.test-cluster.hypershift.local + tls: + insecureEdgeTerminationPolicy: None + termination: passthrough + to: + kind: Service + name: kube-apiserver + weight: null + status: {} + - metadata: + labels: + hypershift.openshift.io/hosted-control-plane: test-namespace + hypershift.openshift.io/internal-route: "true" + hypershift.openshift.io/route-visibility: private + name: kube-apiserver-private + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + host: api.test.example.com + tls: + insecureEdgeTerminationPolicy: None + termination: passthrough + to: + kind: Service + name: kube-apiserver + weight: null + status: {} + - metadata: + labels: + hypershift.openshift.io/hosted-control-plane: test-namespace + hypershift.openshift.io/internal-route: "true" + name: oauth-internal + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + host: oauth.apps.test-cluster.hypershift.local + tls: + insecureEdgeTerminationPolicy: None + termination: passthrough + to: + kind: Service + name: oauth-openshift + weight: null + status: {} + - metadata: + labels: + hypershift.openshift.io/hosted-control-plane: test-namespace + hypershift.openshift.io/internal-route: "true" + hypershift.openshift.io/route-visibility: private + name: oauth-private + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + host: oauth.test.example.com + tls: + insecureEdgeTerminationPolicy: None + termination: passthrough + to: + kind: Service + name: oauth-openshift + weight: null + status: {} + metadata: {} +services: + items: + - metadata: + name: konnectivity-server + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + ports: + - port: 8091 + protocol: TCP + targetPort: 8091 + selector: + app: kube-apiserver + hypershift.openshift.io/control-plane-component: kube-apiserver + type: ClusterIP + status: + loadBalancer: {} + - metadata: + labels: + app: kube-apiserver + hypershift.openshift.io/control-plane-component: kube-apiserver + name: kube-apiserver + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + ipFamilyPolicy: PreferDualStack + ports: + - port: 6443 + protocol: TCP + targetPort: client + selector: + app: kube-apiserver + hypershift.openshift.io/control-plane-component: kube-apiserver + type: ClusterIP + status: + loadBalancer: {} + - metadata: + name: oauth-openshift + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + ipFamilyPolicy: PreferDualStack + ports: + - port: 6443 + protocol: TCP + targetPort: 6443 + selector: + app: oauth-openshift + hypershift.openshift.io/control-plane-component: oauth-openshift + type: ClusterIP + status: + loadBalancer: {} + - metadata: + labels: + app: openshift-apiserver + hypershift.openshift.io/control-plane-component: openshift-apiserver + name: openshift-apiserver + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: 8443 + selector: + app: openshift-apiserver + hypershift.openshift.io/control-plane-component: openshift-apiserver + type: ClusterIP + status: + loadBalancer: {} + - metadata: + labels: + app: openshift-apiserver + hypershift.openshift.io/control-plane-component: openshift-apiserver + name: openshift-oauth-apiserver + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: 8443 + selector: + app: openshift-oauth-apiserver + hypershift.openshift.io/control-plane-component: openshift-oauth-apiserver + type: ClusterIP + status: + loadBalancer: {} + - metadata: + labels: + app: openshift-apiserver + hypershift.openshift.io/control-plane-component: openshift-apiserver + name: packageserver + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: 5443 + selector: + app: packageserver + hypershift.openshift.io/control-plane-component: packageserver + type: ClusterIP + status: + loadBalancer: {} + - metadata: + labels: + app: private-router + name: private-router + namespace: test-namespace + spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: https + selector: + app: private-router + type: ClusterIP + status: + loadBalancer: {} + metadata: {} diff --git a/control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_SharedIngress.yaml b/control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_Swift_PublicAndPrivate.yaml similarity index 85% rename from control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_SharedIngress.yaml rename to control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_Swift_PublicAndPrivate.yaml index be61f321699..b343e2bfb91 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_SharedIngress.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/infra/testdata/zz_fixture_TestReconcileInfrastructure_ARO_Route_Swift_PublicAndPrivate.yaml @@ -5,6 +5,7 @@ routes: haproxy.router.openshift.io/balance: roundrobin labels: hypershift.openshift.io/hosted-control-plane: test-namespace + hypershift.openshift.io/internal-route: "true" name: konnectivity-server namespace: test-namespace ownerReferences: @@ -15,7 +16,7 @@ routes: name: test-cluster uid: "" spec: - host: konnectivity.test.example.com + host: konnectivity-server.apps.test-cluster.hypershift.local tls: insecureEdgeTerminationPolicy: None termination: passthrough @@ -91,6 +92,29 @@ routes: name: oauth-openshift weight: null status: {} + - metadata: + labels: + hypershift.openshift.io/hosted-control-plane: test-namespace + hypershift.openshift.io/internal-route: "true" + name: oauth-internal + namespace: test-namespace + ownerReferences: + - apiVersion: hypershift.openshift.io/v1beta1 + blockOwnerDeletion: true + controller: true + kind: HostedControlPlane + name: test-cluster + uid: "" + spec: + host: oauth.apps.test-cluster.hypershift.local + tls: + insecureEdgeTerminationPolicy: None + termination: passthrough + to: + kind: Service + name: oauth-openshift + weight: null + status: {} metadata: {} services: items: @@ -237,4 +261,20 @@ services: type: ClusterIP status: loadBalancer: {} + - metadata: + labels: + app: private-router + name: private-router + namespace: test-namespace + spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: https + selector: + app: private-router + type: ClusterIP + status: + loadBalancer: {} metadata: {} diff --git a/control-plane-operator/controllers/hostedcontrolplane/ingress/router.go b/control-plane-operator/controllers/hostedcontrolplane/ingress/router.go index 8421a068550..ae5c24b5cfa 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/ingress/router.go +++ b/control-plane-operator/controllers/hostedcontrolplane/ingress/router.go @@ -58,7 +58,7 @@ func ReconcileRouterService(svc *corev1.Service, internal, crossZoneLoadBalancin } } - if hcp.Spec.Platform.Type == hyperv1.AzurePlatform && !azureutil.IsAroHCP() { + if hcp.Spec.Platform.Type == hyperv1.AzurePlatform && !azureutil.IsAroHCPByHCP(hcp) { if svc.Annotations == nil { svc.Annotations = map[string]string{} } @@ -98,7 +98,7 @@ func ReconcileRouterService(svc *corev1.Service, internal, crossZoneLoadBalancin // Apply LoadBalancerSourceRanges for external router services to restrict CIDR access // Only apply for external (non-internal) services and when not running on ARO HCP allowedCIDRBlocks := netutil.AllowedCIDRBlocks(hcp) - if !internal && !azureutil.IsAroHCP() { + if !internal && !azureutil.IsAroHCPByHCP(hcp) { svc.Spec.LoadBalancerSourceRanges = allowedCIDRBlocks } diff --git a/control-plane-operator/controllers/hostedcontrolplane/kas/healthcheck.go b/control-plane-operator/controllers/hostedcontrolplane/kas/healthcheck.go index 082bc4c4888..20ff972d0cb 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/kas/healthcheck.go +++ b/control-plane-operator/controllers/hostedcontrolplane/kas/healthcheck.go @@ -7,6 +7,7 @@ import ( "github.com/openshift/hypershift/control-plane-operator/controllers/hostedcontrolplane/manifests" "github.com/openshift/hypershift/hypershift-operator/controllers/sharedingress" "github.com/openshift/hypershift/support/config" + "github.com/openshift/hypershift/support/netutil" routev1 "github.com/openshift/api/route/v1" ) @@ -20,12 +21,12 @@ func GetHealthcheckEndpointForRoute(externalRoute *routev1.Route, hcp *hyperv1.H endpoint = externalRoute.Status.Ingress[0].RouterCanonicalHostname port = 443 - if sharedingress.UseSharedIngress() { + if netutil.UseSharedIngressHCP(hcp) { endpoint = externalRoute.Spec.Host port = sharedingress.ExternalDNSLBPort } - if sharedingress.UseSharedIngress() && + if netutil.UseSharedIngressHCP(hcp) && hcp.Spec.Networking.APIServer != nil && len(hcp.Spec.Networking.APIServer.AllowedCIDRBlocks) > 0 { // When there's AllowedCIDRBlocks input, we have no guarantees the healthcheck can roundtrip through the haproxy load balancer. // Hence we use KubeAPIServerService as a best effort. diff --git a/control-plane-operator/controllers/hostedcontrolplane/kas/healthcheck_test.go b/control-plane-operator/controllers/hostedcontrolplane/kas/healthcheck_test.go index df1ddedcad7..04539407885 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/kas/healthcheck_test.go +++ b/control-plane-operator/controllers/hostedcontrolplane/kas/healthcheck_test.go @@ -64,7 +64,24 @@ func TestGetHealthcheckEndpoint(t *testing.T) { }, }, }, - hcp: &hyperv1.HostedControlPlane{}, + hcp: &hyperv1.HostedControlPlane{ + Spec: hyperv1.HostedControlPlaneSpec{ + Platform: hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + }, + }, + }, + }, + }, useSharedIngress: true, expectedEndpoint: "route.example.com", expectedPort: sharedingress.ExternalDNSLBPort, @@ -85,6 +102,20 @@ func TestGetHealthcheckEndpoint(t *testing.T) { }, hcp: &hyperv1.HostedControlPlane{ Spec: hyperv1.HostedControlPlaneSpec{ + Platform: hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + }, + }, + }, Networking: hyperv1.ClusterNetworking{ APIServer: &hyperv1.APIServerNetworking{ AllowedCIDRBlocks: []hyperv1.CIDRBlock{"10.0.0.0/16"}, diff --git a/control-plane-operator/controllers/hostedcontrolplane/kas/service.go b/control-plane-operator/controllers/hostedcontrolplane/kas/service.go index 1c69a7d4697..ffd30fb0c04 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/kas/service.go +++ b/control-plane-operator/controllers/hostedcontrolplane/kas/service.go @@ -79,7 +79,7 @@ func ReconcileService(svc *corev1.Service, strategy *hyperv1.ServicePublishingSt if strategy.LoadBalancer != nil && strategy.LoadBalancer.Hostname != "" { svc.Annotations[hyperv1.ExternalDNSHostnameAnnotation] = strategy.LoadBalancer.Hostname } - if !azureutil.IsAroHCP() { + if !azureutil.IsAroHCPByHCP(hcp) { svc.Spec.LoadBalancerSourceRanges = apiAllowedCIDRBlocks } diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml index 7e185cd1eb5..854f8ab8982 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml @@ -5,12 +5,12 @@ data: "cloud": "", "tenantId": "", "useManagedIdentityExtension": false, - "useFederatedWorkloadIdentityExtension": false, + "useFederatedWorkloadIdentityExtension": true, "subscriptionId": "", - "aadClientId": "", + "aadClientId": "myClientID", "aadClientSecret": "", "aadClientCertPath": "", - "aadFederatedTokenFile": "", + "aadFederatedTokenFile": "/var/run/secrets/openshift/serviceaccount/token", "aadMSIDataPlaneIdentityPath": "", "resourceGroup": "", "location": "", diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml index 6c4df55d61f..daa214bfed8 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml @@ -1,6 +1,6 @@ apiVersion: v1 data: - cloud.conf: ewogICJjbG91ZCI6ICIiLAogICJ0ZW5hbnRJZCI6ICIiLAogICJ1c2VNYW5hZ2VkSWRlbnRpdHlFeHRlbnNpb24iOiBmYWxzZSwKICAidXNlRmVkZXJhdGVkV29ya2xvYWRJZGVudGl0eUV4dGVuc2lvbiI6IGZhbHNlLAogICJzdWJzY3JpcHRpb25JZCI6ICIiLAogICJhYWRDbGllbnRJZCI6ICIiLAogICJhYWRDbGllbnRTZWNyZXQiOiAiIiwKICAiYWFkQ2xpZW50Q2VydFBhdGgiOiAiIiwKICAiYWFkRmVkZXJhdGVkVG9rZW5GaWxlIjogIiIsCiAgImFhZE1TSURhdGFQbGFuZUlkZW50aXR5UGF0aCI6ICIiLAogICJyZXNvdXJjZUdyb3VwIjogIiIsCiAgImxvY2F0aW9uIjogIiIsCiAgInZuZXROYW1lIjogIm15Vm5ldE5hbWUiLAogICJ2bmV0UmVzb3VyY2VHcm91cCI6ICJteVJlc291cmNlR3JvdXBOYW1lIiwKICAic3VibmV0TmFtZSI6ICJteVN1Ym5ldE5hbWUiLAogICJzZWN1cml0eUdyb3VwTmFtZSI6ICJteU5TR05hbWUiLAogICJzZWN1cml0eUdyb3VwUmVzb3VyY2VHcm91cCI6ICJteVJlc291cmNlR3JvdXBOYW1lIiwKICAicm91dGVUYWJsZU5hbWUiOiAiIiwKICAiY2xvdWRQcm92aWRlckJhY2tvZmYiOiB0cnVlLAogICJjbG91ZFByb3ZpZGVyQmFja29mZkR1cmF0aW9uIjogNiwKICAidXNlSW5zdGFuY2VNZXRhZGF0YSI6IHRydWUsCiAgImxvYWRCYWxhbmNlclNrdSI6ICJzdGFuZGFyZCIsCiAgImRpc2FibGVPdXRib3VuZFNOQVQiOiB0cnVlLAogICJsb2FkQmFsYW5jZXJOYW1lIjogIiIsCiAgImNsdXN0ZXJTZXJ2aWNlTG9hZEJhbGFuY2VySGVhbHRoUHJvYmVNb2RlIjogInNoYXJlZCIKfQ== + cloud.conf: ewogICJjbG91ZCI6ICIiLAogICJ0ZW5hbnRJZCI6ICIiLAogICJ1c2VNYW5hZ2VkSWRlbnRpdHlFeHRlbnNpb24iOiBmYWxzZSwKICAidXNlRmVkZXJhdGVkV29ya2xvYWRJZGVudGl0eUV4dGVuc2lvbiI6IHRydWUsCiAgInN1YnNjcmlwdGlvbklkIjogIiIsCiAgImFhZENsaWVudElkIjogIm15Q2xpZW50SUQiLAogICJhYWRDbGllbnRTZWNyZXQiOiAiIiwKICAiYWFkQ2xpZW50Q2VydFBhdGgiOiAiIiwKICAiYWFkRmVkZXJhdGVkVG9rZW5GaWxlIjogIi92YXIvcnVuL3NlY3JldHMvb3BlbnNoaWZ0L3NlcnZpY2VhY2NvdW50L3Rva2VuIiwKICAiYWFkTVNJRGF0YVBsYW5lSWRlbnRpdHlQYXRoIjogIiIsCiAgInJlc291cmNlR3JvdXAiOiAiIiwKICAibG9jYXRpb24iOiAiIiwKICAidm5ldE5hbWUiOiAibXlWbmV0TmFtZSIsCiAgInZuZXRSZXNvdXJjZUdyb3VwIjogIm15UmVzb3VyY2VHcm91cE5hbWUiLAogICJzdWJuZXROYW1lIjogIm15U3VibmV0TmFtZSIsCiAgInNlY3VyaXR5R3JvdXBOYW1lIjogIm15TlNHTmFtZSIsCiAgInNlY3VyaXR5R3JvdXBSZXNvdXJjZUdyb3VwIjogIm15UmVzb3VyY2VHcm91cE5hbWUiLAogICJyb3V0ZVRhYmxlTmFtZSI6ICIiLAogICJjbG91ZFByb3ZpZGVyQmFja29mZiI6IHRydWUsCiAgImNsb3VkUHJvdmlkZXJCYWNrb2ZmRHVyYXRpb24iOiA2LAogICJ1c2VJbnN0YW5jZU1ldGFkYXRhIjogdHJ1ZSwKICAibG9hZEJhbGFuY2VyU2t1IjogInN0YW5kYXJkIiwKICAiZGlzYWJsZU91dGJvdW5kU05BVCI6IHRydWUsCiAgImxvYWRCYWxhbmNlck5hbWUiOiAiIiwKICAiY2x1c3RlclNlcnZpY2VMb2FkQmFsYW5jZXJIZWFsdGhQcm9iZU1vZGUiOiAic2hhcmVkIgp9 kind: Secret metadata: name: azure-cloud-config diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml index 82e9a468ede..f04b83971e7 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/GCP/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml @@ -25,7 +25,7 @@ spec: metadata: annotations: cluster-autoscaler.kubernetes.io/safe-to-evict-local-volumes: cloud-token,tmp-dir - component.hypershift.openshift.io/config-hash: 6390db5f + component.hypershift.openshift.io/config-hash: 5e25069a hypershift.openshift.io/release-image: quay.io/openshift-release-dev/ocp-release:4.16.10-x86_64 labels: app: cloud-controller-manager @@ -139,6 +139,7 @@ spec: - mountPath: /etc/kubernetes name: kubeconfig priorityClassName: hypershift-control-plane + serviceAccountName: azure-cloud-controller-manager tolerations: - effect: NoSchedule key: hypershift.openshift.io/control-plane diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml index 7e185cd1eb5..854f8ab8982 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml @@ -5,12 +5,12 @@ data: "cloud": "", "tenantId": "", "useManagedIdentityExtension": false, - "useFederatedWorkloadIdentityExtension": false, + "useFederatedWorkloadIdentityExtension": true, "subscriptionId": "", - "aadClientId": "", + "aadClientId": "myClientID", "aadClientSecret": "", "aadClientCertPath": "", - "aadFederatedTokenFile": "", + "aadFederatedTokenFile": "/var/run/secrets/openshift/serviceaccount/token", "aadMSIDataPlaneIdentityPath": "", "resourceGroup": "", "location": "", diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml index 6c4df55d61f..daa214bfed8 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml @@ -1,6 +1,6 @@ apiVersion: v1 data: - cloud.conf: ewogICJjbG91ZCI6ICIiLAogICJ0ZW5hbnRJZCI6ICIiLAogICJ1c2VNYW5hZ2VkSWRlbnRpdHlFeHRlbnNpb24iOiBmYWxzZSwKICAidXNlRmVkZXJhdGVkV29ya2xvYWRJZGVudGl0eUV4dGVuc2lvbiI6IGZhbHNlLAogICJzdWJzY3JpcHRpb25JZCI6ICIiLAogICJhYWRDbGllbnRJZCI6ICIiLAogICJhYWRDbGllbnRTZWNyZXQiOiAiIiwKICAiYWFkQ2xpZW50Q2VydFBhdGgiOiAiIiwKICAiYWFkRmVkZXJhdGVkVG9rZW5GaWxlIjogIiIsCiAgImFhZE1TSURhdGFQbGFuZUlkZW50aXR5UGF0aCI6ICIiLAogICJyZXNvdXJjZUdyb3VwIjogIiIsCiAgImxvY2F0aW9uIjogIiIsCiAgInZuZXROYW1lIjogIm15Vm5ldE5hbWUiLAogICJ2bmV0UmVzb3VyY2VHcm91cCI6ICJteVJlc291cmNlR3JvdXBOYW1lIiwKICAic3VibmV0TmFtZSI6ICJteVN1Ym5ldE5hbWUiLAogICJzZWN1cml0eUdyb3VwTmFtZSI6ICJteU5TR05hbWUiLAogICJzZWN1cml0eUdyb3VwUmVzb3VyY2VHcm91cCI6ICJteVJlc291cmNlR3JvdXBOYW1lIiwKICAicm91dGVUYWJsZU5hbWUiOiAiIiwKICAiY2xvdWRQcm92aWRlckJhY2tvZmYiOiB0cnVlLAogICJjbG91ZFByb3ZpZGVyQmFja29mZkR1cmF0aW9uIjogNiwKICAidXNlSW5zdGFuY2VNZXRhZGF0YSI6IHRydWUsCiAgImxvYWRCYWxhbmNlclNrdSI6ICJzdGFuZGFyZCIsCiAgImRpc2FibGVPdXRib3VuZFNOQVQiOiB0cnVlLAogICJsb2FkQmFsYW5jZXJOYW1lIjogIiIsCiAgImNsdXN0ZXJTZXJ2aWNlTG9hZEJhbGFuY2VySGVhbHRoUHJvYmVNb2RlIjogInNoYXJlZCIKfQ== + cloud.conf: ewogICJjbG91ZCI6ICIiLAogICJ0ZW5hbnRJZCI6ICIiLAogICJ1c2VNYW5hZ2VkSWRlbnRpdHlFeHRlbnNpb24iOiBmYWxzZSwKICAidXNlRmVkZXJhdGVkV29ya2xvYWRJZGVudGl0eUV4dGVuc2lvbiI6IHRydWUsCiAgInN1YnNjcmlwdGlvbklkIjogIiIsCiAgImFhZENsaWVudElkIjogIm15Q2xpZW50SUQiLAogICJhYWRDbGllbnRTZWNyZXQiOiAiIiwKICAiYWFkQ2xpZW50Q2VydFBhdGgiOiAiIiwKICAiYWFkRmVkZXJhdGVkVG9rZW5GaWxlIjogIi92YXIvcnVuL3NlY3JldHMvb3BlbnNoaWZ0L3NlcnZpY2VhY2NvdW50L3Rva2VuIiwKICAiYWFkTVNJRGF0YVBsYW5lSWRlbnRpdHlQYXRoIjogIiIsCiAgInJlc291cmNlR3JvdXAiOiAiIiwKICAibG9jYXRpb24iOiAiIiwKICAidm5ldE5hbWUiOiAibXlWbmV0TmFtZSIsCiAgInZuZXRSZXNvdXJjZUdyb3VwIjogIm15UmVzb3VyY2VHcm91cE5hbWUiLAogICJzdWJuZXROYW1lIjogIm15U3VibmV0TmFtZSIsCiAgInNlY3VyaXR5R3JvdXBOYW1lIjogIm15TlNHTmFtZSIsCiAgInNlY3VyaXR5R3JvdXBSZXNvdXJjZUdyb3VwIjogIm15UmVzb3VyY2VHcm91cE5hbWUiLAogICJyb3V0ZVRhYmxlTmFtZSI6ICIiLAogICJjbG91ZFByb3ZpZGVyQmFja29mZiI6IHRydWUsCiAgImNsb3VkUHJvdmlkZXJCYWNrb2ZmRHVyYXRpb24iOiA2LAogICJ1c2VJbnN0YW5jZU1ldGFkYXRhIjogdHJ1ZSwKICAibG9hZEJhbGFuY2VyU2t1IjogInN0YW5kYXJkIiwKICAiZGlzYWJsZU91dGJvdW5kU05BVCI6IHRydWUsCiAgImxvYWRCYWxhbmNlck5hbWUiOiAiIiwKICAiY2x1c3RlclNlcnZpY2VMb2FkQmFsYW5jZXJIZWFsdGhQcm9iZU1vZGUiOiAic2hhcmVkIgp9 kind: Secret metadata: name: azure-cloud-config diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml index 46764bcf7cb..c1fc8dcb56c 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/IBMCloud/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml @@ -25,7 +25,7 @@ spec: metadata: annotations: cluster-autoscaler.kubernetes.io/safe-to-evict-local-volumes: tmp-dir - component.hypershift.openshift.io/config-hash: 6390db5f + component.hypershift.openshift.io/config-hash: 5e25069a hypershift.openshift.io/release-image: quay.io/openshift-release-dev/ocp-release:4.16.10-x86_64 labels: app: cloud-controller-manager @@ -94,6 +94,7 @@ spec: - mountPath: /tmp name: tmp-dir priorityClassName: hypershift-control-plane + serviceAccountName: azure-cloud-controller-manager tolerations: - effect: NoSchedule key: hypershift.openshift.io/control-plane diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml index 7e185cd1eb5..854f8ab8982 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml @@ -5,12 +5,12 @@ data: "cloud": "", "tenantId": "", "useManagedIdentityExtension": false, - "useFederatedWorkloadIdentityExtension": false, + "useFederatedWorkloadIdentityExtension": true, "subscriptionId": "", - "aadClientId": "", + "aadClientId": "myClientID", "aadClientSecret": "", "aadClientCertPath": "", - "aadFederatedTokenFile": "", + "aadFederatedTokenFile": "/var/run/secrets/openshift/serviceaccount/token", "aadMSIDataPlaneIdentityPath": "", "resourceGroup": "", "location": "", diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml index 6c4df55d61f..daa214bfed8 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml @@ -1,6 +1,6 @@ apiVersion: v1 data: - cloud.conf: ewogICJjbG91ZCI6ICIiLAogICJ0ZW5hbnRJZCI6ICIiLAogICJ1c2VNYW5hZ2VkSWRlbnRpdHlFeHRlbnNpb24iOiBmYWxzZSwKICAidXNlRmVkZXJhdGVkV29ya2xvYWRJZGVudGl0eUV4dGVuc2lvbiI6IGZhbHNlLAogICJzdWJzY3JpcHRpb25JZCI6ICIiLAogICJhYWRDbGllbnRJZCI6ICIiLAogICJhYWRDbGllbnRTZWNyZXQiOiAiIiwKICAiYWFkQ2xpZW50Q2VydFBhdGgiOiAiIiwKICAiYWFkRmVkZXJhdGVkVG9rZW5GaWxlIjogIiIsCiAgImFhZE1TSURhdGFQbGFuZUlkZW50aXR5UGF0aCI6ICIiLAogICJyZXNvdXJjZUdyb3VwIjogIiIsCiAgImxvY2F0aW9uIjogIiIsCiAgInZuZXROYW1lIjogIm15Vm5ldE5hbWUiLAogICJ2bmV0UmVzb3VyY2VHcm91cCI6ICJteVJlc291cmNlR3JvdXBOYW1lIiwKICAic3VibmV0TmFtZSI6ICJteVN1Ym5ldE5hbWUiLAogICJzZWN1cml0eUdyb3VwTmFtZSI6ICJteU5TR05hbWUiLAogICJzZWN1cml0eUdyb3VwUmVzb3VyY2VHcm91cCI6ICJteVJlc291cmNlR3JvdXBOYW1lIiwKICAicm91dGVUYWJsZU5hbWUiOiAiIiwKICAiY2xvdWRQcm92aWRlckJhY2tvZmYiOiB0cnVlLAogICJjbG91ZFByb3ZpZGVyQmFja29mZkR1cmF0aW9uIjogNiwKICAidXNlSW5zdGFuY2VNZXRhZGF0YSI6IHRydWUsCiAgImxvYWRCYWxhbmNlclNrdSI6ICJzdGFuZGFyZCIsCiAgImRpc2FibGVPdXRib3VuZFNOQVQiOiB0cnVlLAogICJsb2FkQmFsYW5jZXJOYW1lIjogIiIsCiAgImNsdXN0ZXJTZXJ2aWNlTG9hZEJhbGFuY2VySGVhbHRoUHJvYmVNb2RlIjogInNoYXJlZCIKfQ== + cloud.conf: ewogICJjbG91ZCI6ICIiLAogICJ0ZW5hbnRJZCI6ICIiLAogICJ1c2VNYW5hZ2VkSWRlbnRpdHlFeHRlbnNpb24iOiBmYWxzZSwKICAidXNlRmVkZXJhdGVkV29ya2xvYWRJZGVudGl0eUV4dGVuc2lvbiI6IHRydWUsCiAgInN1YnNjcmlwdGlvbklkIjogIiIsCiAgImFhZENsaWVudElkIjogIm15Q2xpZW50SUQiLAogICJhYWRDbGllbnRTZWNyZXQiOiAiIiwKICAiYWFkQ2xpZW50Q2VydFBhdGgiOiAiIiwKICAiYWFkRmVkZXJhdGVkVG9rZW5GaWxlIjogIi92YXIvcnVuL3NlY3JldHMvb3BlbnNoaWZ0L3NlcnZpY2VhY2NvdW50L3Rva2VuIiwKICAiYWFkTVNJRGF0YVBsYW5lSWRlbnRpdHlQYXRoIjogIiIsCiAgInJlc291cmNlR3JvdXAiOiAiIiwKICAibG9jYXRpb24iOiAiIiwKICAidm5ldE5hbWUiOiAibXlWbmV0TmFtZSIsCiAgInZuZXRSZXNvdXJjZUdyb3VwIjogIm15UmVzb3VyY2VHcm91cE5hbWUiLAogICJzdWJuZXROYW1lIjogIm15U3VibmV0TmFtZSIsCiAgInNlY3VyaXR5R3JvdXBOYW1lIjogIm15TlNHTmFtZSIsCiAgInNlY3VyaXR5R3JvdXBSZXNvdXJjZUdyb3VwIjogIm15UmVzb3VyY2VHcm91cE5hbWUiLAogICJyb3V0ZVRhYmxlTmFtZSI6ICIiLAogICJjbG91ZFByb3ZpZGVyQmFja29mZiI6IHRydWUsCiAgImNsb3VkUHJvdmlkZXJCYWNrb2ZmRHVyYXRpb24iOiA2LAogICJ1c2VJbnN0YW5jZU1ldGFkYXRhIjogdHJ1ZSwKICAibG9hZEJhbGFuY2VyU2t1IjogInN0YW5kYXJkIiwKICAiZGlzYWJsZU91dGJvdW5kU05BVCI6IHRydWUsCiAgImxvYWRCYWxhbmNlck5hbWUiOiAiIiwKICAiY2x1c3RlclNlcnZpY2VMb2FkQmFsYW5jZXJIZWFsdGhQcm9iZU1vZGUiOiAic2hhcmVkIgp9 kind: Secret metadata: name: azure-cloud-config diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml index db98131c478..355ee94448a 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/TechPreviewNoUpgrade/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml @@ -25,7 +25,7 @@ spec: metadata: annotations: cluster-autoscaler.kubernetes.io/safe-to-evict-local-volumes: cloud-token,tmp-dir - component.hypershift.openshift.io/config-hash: 6390db5f + component.hypershift.openshift.io/config-hash: 5e25069a hypershift.openshift.io/release-image: quay.io/openshift-release-dev/ocp-release:4.16.10-x86_64 labels: app: cloud-controller-manager @@ -128,6 +128,7 @@ spec: - mountPath: /etc/kubernetes name: kubeconfig priorityClassName: hypershift-control-plane + serviceAccountName: azure-cloud-controller-manager tolerations: - effect: NoSchedule key: hypershift.openshift.io/control-plane diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml index 7e185cd1eb5..854f8ab8982 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_config_configmap.yaml @@ -5,12 +5,12 @@ data: "cloud": "", "tenantId": "", "useManagedIdentityExtension": false, - "useFederatedWorkloadIdentityExtension": false, + "useFederatedWorkloadIdentityExtension": true, "subscriptionId": "", - "aadClientId": "", + "aadClientId": "myClientID", "aadClientSecret": "", "aadClientCertPath": "", - "aadFederatedTokenFile": "", + "aadFederatedTokenFile": "/var/run/secrets/openshift/serviceaccount/token", "aadMSIDataPlaneIdentityPath": "", "resourceGroup": "", "location": "", diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml index 6c4df55d61f..daa214bfed8 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_config_secret.yaml @@ -1,6 +1,6 @@ apiVersion: v1 data: - cloud.conf: ewogICJjbG91ZCI6ICIiLAogICJ0ZW5hbnRJZCI6ICIiLAogICJ1c2VNYW5hZ2VkSWRlbnRpdHlFeHRlbnNpb24iOiBmYWxzZSwKICAidXNlRmVkZXJhdGVkV29ya2xvYWRJZGVudGl0eUV4dGVuc2lvbiI6IGZhbHNlLAogICJzdWJzY3JpcHRpb25JZCI6ICIiLAogICJhYWRDbGllbnRJZCI6ICIiLAogICJhYWRDbGllbnRTZWNyZXQiOiAiIiwKICAiYWFkQ2xpZW50Q2VydFBhdGgiOiAiIiwKICAiYWFkRmVkZXJhdGVkVG9rZW5GaWxlIjogIiIsCiAgImFhZE1TSURhdGFQbGFuZUlkZW50aXR5UGF0aCI6ICIiLAogICJyZXNvdXJjZUdyb3VwIjogIiIsCiAgImxvY2F0aW9uIjogIiIsCiAgInZuZXROYW1lIjogIm15Vm5ldE5hbWUiLAogICJ2bmV0UmVzb3VyY2VHcm91cCI6ICJteVJlc291cmNlR3JvdXBOYW1lIiwKICAic3VibmV0TmFtZSI6ICJteVN1Ym5ldE5hbWUiLAogICJzZWN1cml0eUdyb3VwTmFtZSI6ICJteU5TR05hbWUiLAogICJzZWN1cml0eUdyb3VwUmVzb3VyY2VHcm91cCI6ICJteVJlc291cmNlR3JvdXBOYW1lIiwKICAicm91dGVUYWJsZU5hbWUiOiAiIiwKICAiY2xvdWRQcm92aWRlckJhY2tvZmYiOiB0cnVlLAogICJjbG91ZFByb3ZpZGVyQmFja29mZkR1cmF0aW9uIjogNiwKICAidXNlSW5zdGFuY2VNZXRhZGF0YSI6IHRydWUsCiAgImxvYWRCYWxhbmNlclNrdSI6ICJzdGFuZGFyZCIsCiAgImRpc2FibGVPdXRib3VuZFNOQVQiOiB0cnVlLAogICJsb2FkQmFsYW5jZXJOYW1lIjogIiIsCiAgImNsdXN0ZXJTZXJ2aWNlTG9hZEJhbGFuY2VySGVhbHRoUHJvYmVNb2RlIjogInNoYXJlZCIKfQ== + cloud.conf: ewogICJjbG91ZCI6ICIiLAogICJ0ZW5hbnRJZCI6ICIiLAogICJ1c2VNYW5hZ2VkSWRlbnRpdHlFeHRlbnNpb24iOiBmYWxzZSwKICAidXNlRmVkZXJhdGVkV29ya2xvYWRJZGVudGl0eUV4dGVuc2lvbiI6IHRydWUsCiAgInN1YnNjcmlwdGlvbklkIjogIiIsCiAgImFhZENsaWVudElkIjogIm15Q2xpZW50SUQiLAogICJhYWRDbGllbnRTZWNyZXQiOiAiIiwKICAiYWFkQ2xpZW50Q2VydFBhdGgiOiAiIiwKICAiYWFkRmVkZXJhdGVkVG9rZW5GaWxlIjogIi92YXIvcnVuL3NlY3JldHMvb3BlbnNoaWZ0L3NlcnZpY2VhY2NvdW50L3Rva2VuIiwKICAiYWFkTVNJRGF0YVBsYW5lSWRlbnRpdHlQYXRoIjogIiIsCiAgInJlc291cmNlR3JvdXAiOiAiIiwKICAibG9jYXRpb24iOiAiIiwKICAidm5ldE5hbWUiOiAibXlWbmV0TmFtZSIsCiAgInZuZXRSZXNvdXJjZUdyb3VwIjogIm15UmVzb3VyY2VHcm91cE5hbWUiLAogICJzdWJuZXROYW1lIjogIm15U3VibmV0TmFtZSIsCiAgInNlY3VyaXR5R3JvdXBOYW1lIjogIm15TlNHTmFtZSIsCiAgInNlY3VyaXR5R3JvdXBSZXNvdXJjZUdyb3VwIjogIm15UmVzb3VyY2VHcm91cE5hbWUiLAogICJyb3V0ZVRhYmxlTmFtZSI6ICIiLAogICJjbG91ZFByb3ZpZGVyQmFja29mZiI6IHRydWUsCiAgImNsb3VkUHJvdmlkZXJCYWNrb2ZmRHVyYXRpb24iOiA2LAogICJ1c2VJbnN0YW5jZU1ldGFkYXRhIjogdHJ1ZSwKICAibG9hZEJhbGFuY2VyU2t1IjogInN0YW5kYXJkIiwKICAiZGlzYWJsZU91dGJvdW5kU05BVCI6IHRydWUsCiAgImxvYWRCYWxhbmNlck5hbWUiOiAiIiwKICAiY2x1c3RlclNlcnZpY2VMb2FkQmFsYW5jZXJIZWFsdGhQcm9iZU1vZGUiOiAic2hhcmVkIgp9 kind: Secret metadata: name: azure-cloud-config diff --git a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml index db98131c478..355ee94448a 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml +++ b/control-plane-operator/controllers/hostedcontrolplane/testdata/azure-cloud-controller-manager/zz_fixture_TestControlPlaneComponents_azure_cloud_controller_manager_deployment.yaml @@ -25,7 +25,7 @@ spec: metadata: annotations: cluster-autoscaler.kubernetes.io/safe-to-evict-local-volumes: cloud-token,tmp-dir - component.hypershift.openshift.io/config-hash: 6390db5f + component.hypershift.openshift.io/config-hash: 5e25069a hypershift.openshift.io/release-image: quay.io/openshift-release-dev/ocp-release:4.16.10-x86_64 labels: app: cloud-controller-manager @@ -128,6 +128,7 @@ spec: - mountPath: /etc/kubernetes name: kubeconfig priorityClassName: hypershift-control-plane + serviceAccountName: azure-cloud-controller-manager tolerations: - effect: NoSchedule key: hypershift.openshift.io/control-plane diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/component.go b/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/component.go index 9aa87ef2839..1c1e7acc341 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/component.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/component.go @@ -90,9 +90,9 @@ func adaptServiceAccount(cpContext component.WorkloadContext, sa *corev1.Service } func isAroHCP(cpContext component.WorkloadContext) bool { - return azureutil.IsAroHCP() + return azureutil.IsAroHCPByHCP(cpContext.HCP) } func isSelfManagedAzure(cpContext component.WorkloadContext) bool { - return !azureutil.IsAroHCP() + return !azureutil.IsAroHCPByHCP(cpContext.HCP) } diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/config.go b/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/config.go index 060fee3aeb2..623c0adac07 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/config.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/config.go @@ -43,7 +43,7 @@ func adaptConfigSecret(cpContext component.WorkloadContext, secret *corev1.Secre return err } - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { cfg.UseManagedIdentityExtension = false cfg.UseInstanceMetadata = false } @@ -58,7 +58,7 @@ func adaptConfigSecret(cpContext component.WorkloadContext, secret *corev1.Secre } func adaptSecretProvider(cpContext component.WorkloadContext, secretProvider *secretsstorev1.SecretProviderClass) error { - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { secretproviderclass.ReconcileManagedAzureSecretProviderClass(secretProvider, cpContext.HCP, cpContext.HCP.Spec.Platform.Azure.AzureAuthenticationConfig.ManagedIdentities.ControlPlane.CloudProvider) } return nil @@ -146,10 +146,10 @@ func azureConfig(cpContext component.WorkloadContext, withCredentials bool) (Azu } // Configure authentication method based on platform type - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(hcp) { // ARO HCP uses managed identity azureConfig.UseManagedIdentityExtension = true - } else if azureutil.IsSelfManagedAzure(hcp.Spec.Platform.Type) { + } else { // Self-managed Azure uses workload identity azureConfig.UseFederatedWorkloadIdentityExtension = true azureConfig.AADClientID = string(azureplatform.AzureAuthenticationConfig.WorkloadIdentities.CloudProvider.ClientID) @@ -157,7 +157,7 @@ func azureConfig(cpContext component.WorkloadContext, withCredentials bool) (Azu } if withCredentials { - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(hcp) { azureConfig.AADMSIDataPlaneIdentityPath = config.ManagedAzureCertificatePath + hcp.Spec.Platform.Azure.AzureAuthenticationConfig.ManagedIdentities.ControlPlane.CloudProvider.CredentialsSecretName } } diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/deployment.go b/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/deployment.go index cd79cf9a4d8..0841db52ed1 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/deployment.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/cloud_controller_manager/azure/deployment.go @@ -21,18 +21,18 @@ func adaptDeployment(cpContext component.WorkloadContext, deployment *appsv1.Dep c.Args = append(c.Args, fmt.Sprintf("--cluster-name=%s", cpContext.HCP.Spec.InfraID), ) - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { c.VolumeMounts = append(c.VolumeMounts, azureutil.CreateVolumeMountForAzureSecretStoreProviderClass(config.ManagedAzureCloudProviderSecretStoreVolumeName), ) } }) - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { deployment.Spec.Template.Spec.Volumes = append(deployment.Spec.Template.Spec.Volumes, azureutil.CreateVolumeForAzureSecretStoreProviderClass(config.ManagedAzureCloudProviderSecretStoreVolumeName, config.ManagedAzureCloudProviderSecretProviderClassName), ) - } else if azureutil.IsSelfManagedAzure(cpContext.HCP.Spec.Platform.Type) { + } else { deployment.Spec.Template.Spec.ServiceAccountName = "azure-cloud-controller-manager" } diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/cno/component.go b/control-plane-operator/controllers/hostedcontrolplane/v2/cno/component.go index f6f884301e0..139e1163995 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/cno/component.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/cno/component.go @@ -79,7 +79,7 @@ func NewComponent() component.ControlPlaneComponent { } func isAroHCP(cpContext component.WorkloadContext) bool { - return azureutil.IsAroHCP() + return azureutil.IsAroHCPByHCP(cpContext.HCP) } func SetRestartAnnotationAndPatch(ctx context.Context, crclient client.Client, dep *appsv1.Deployment, restartAnnotation string) error { diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/cno/deployment.go b/control-plane-operator/controllers/hostedcontrolplane/v2/cno/deployment.go index 986c930145e..b647e6c4cab 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/cno/deployment.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/cno/deployment.go @@ -148,7 +148,7 @@ func buildCNOEnvVars(cpContext component.WorkloadContext) []corev1.EnvVar { // For managed Azure deployments, we pass the env variables for: // - the SecretProviderClass for the Secrets Store CSI driver to use on the CNCC deployment // - the filepath of the credentials - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(hcp) { cnoEnv = append(cnoEnv, corev1.EnvVar{ Name: config.ManagedAzureSecretProviderClassEnvVarKey, diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/controlplaneoperator/deployment.go b/control-plane-operator/controllers/hostedcontrolplane/v2/controlplaneoperator/deployment.go index a3620f1c028..2e54e823c3d 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/controlplaneoperator/deployment.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/controlplaneoperator/deployment.go @@ -223,7 +223,7 @@ func (cpo *ControlPlaneOperatorOptions) applyPlatformSpecificConfig(hcp *hyperv1 MountPath: "/etc/provider", }) case hyperv1.AzurePlatform: - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(hcp) { // Add the client ID of the managed Azure key vault as an environment variable on the CPO. This is used in // configuring the SecretProviderClass CRs for OpenShift components on the HCP needing to authenticate with // Azure cloud API. @@ -254,7 +254,7 @@ func (cpo *ControlPlaneOperatorOptions) applyPlatformSpecificConfig(hcp *hyperv1 azureutil.CreateVolumeForAzureSecretStoreProviderClass(config.ManagedAzureKMSSecretStoreVolumeName, config.ManagedAzureKMSSecretProviderClassName), ) } - } else if azureutil.IsSelfManagedAzure(hcp.Spec.Platform.Type) { + } else { if hcp.Spec.Platform.Azure.AzureAuthenticationConfig.WorkloadIdentities != nil && hcp.Spec.Platform.Azure.AzureAuthenticationConfig.WorkloadIdentities.ControlPlaneOperator.ClientID != "" { deployment.Spec.Template.Spec.Containers[0].Env = append( diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/controlplaneoperator/role.go b/control-plane-operator/controllers/hostedcontrolplane/v2/controlplaneoperator/role.go index b9bdc48f189..e7ded7121b5 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/controlplaneoperator/role.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/controlplaneoperator/role.go @@ -39,7 +39,7 @@ func adaptRole(cpContext component.WorkloadContext, role *rbacv1.Role) error { }) } - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { role.Rules = append(role.Rules, rbacv1.PolicyRule{ APIGroups: []string{"secrets-store.csi.x-k8s.io"}, Resources: []string{"secretproviderclasses"}, diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/ingressoperator/component.go b/control-plane-operator/controllers/hostedcontrolplane/v2/ingressoperator/component.go index caae5a3205c..728dd1a70af 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/ingressoperator/component.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/ingressoperator/component.go @@ -87,5 +87,5 @@ func isIngressCapabilityEnabled(cpContext component.WorkloadContext) (bool, erro } func isAroHCP(cpContext component.WorkloadContext) bool { - return azureutil.IsAroHCP() + return azureutil.IsAroHCPByHCP(cpContext.HCP) } diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/ingressoperator/deployment.go b/control-plane-operator/controllers/hostedcontrolplane/v2/ingressoperator/deployment.go index a7283b9e79e..74c97a55ddb 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/ingressoperator/deployment.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/ingressoperator/deployment.go @@ -32,7 +32,7 @@ func adaptDeployment(cpContext component.WorkloadContext, deployment *appsv1.Dep // we authenticate with Azure API through UserAssignedCredential authentication. We also mount the // SecretProviderClass for the Secrets Store CSI driver to use; it will grab the JSON object stored in the // MANAGED_AZURE_HCP_CREDENTIALS_FILE_PATH and mount it as a volume in the ingress pod in the path. - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { c.Env = append(c.Env, azureutil.CreateEnvVarsForAzureManagedIdentity(cpContext.HCP.Spec.Platform.Azure.AzureAuthenticationConfig.ManagedIdentities.ControlPlane.Ingress.CredentialsSecretName)...) diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/kas/component.go b/control-plane-operator/controllers/hostedcontrolplane/v2/kas/component.go index d28a7c380f3..404cd9ff81f 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/kas/component.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/kas/component.go @@ -130,7 +130,7 @@ func NewComponent() component.ControlPlaneComponent { func enableAzureKMSSecretProvider(cpContext component.WorkloadContext) bool { if cpContext.HCP.Spec.SecretEncryption != nil && cpContext.HCP.Spec.SecretEncryption.KMS != nil && cpContext.HCP.Spec.SecretEncryption.Type == hyperv1.KMS { - return azureutil.IsAroHCP() + return azureutil.IsAroHCPByHCP(cpContext.HCP) } return false } diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/kas/deployment.go b/control-plane-operator/controllers/hostedcontrolplane/v2/kas/deployment.go index a8f0aa04000..d0ecc5523bc 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/kas/deployment.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/kas/deployment.go @@ -141,7 +141,7 @@ func adaptDeployment(cpContext component.WorkloadContext, deployment *appsv1.Dep // sidecar resolves the Key Vault FQDN to the private-router Service ClusterIP. // The private router has access to the customer VNet (via Swift) and can reach the // Key Vault's private endpoint, acting as a TCP passthrough relay. - if azureutil.IsAroHCP() && azureutil.IsPrivateKeyVault(hcp) { + if azureutil.IsAroHCPByHCP(hcp) && azureutil.IsPrivateKeyVault(hcp) { kvFQDN, err := azureutil.GetKeyVaultFQDN(hcp) if err != nil { return fmt.Errorf("failed to get Key Vault FQDN for hostAlias: %w", err) diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/registryoperator/component.go b/control-plane-operator/controllers/hostedcontrolplane/v2/registryoperator/component.go index 5d56595c0ca..144a54c8c3d 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/registryoperator/component.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/registryoperator/component.go @@ -64,5 +64,5 @@ func isImageRegistryCapabilityEnabled(cpContext component.WorkloadContext) (bool } func isAroHCP(cpContext component.WorkloadContext) bool { - return azureutil.IsAroHCP() + return azureutil.IsAroHCPByHCP(cpContext.HCP) } diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/registryoperator/deployment.go b/control-plane-operator/controllers/hostedcontrolplane/v2/registryoperator/deployment.go index d1f563dd685..8703b193a1c 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/registryoperator/deployment.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/registryoperator/deployment.go @@ -28,7 +28,7 @@ func adaptDeployment(cpContext component.WorkloadContext, deployment *appsv1.Dep // we authenticate with Azure API through UserAssignedCredential authentication. We also mount the // SecretProviderClass for the Secrets Store CSI driver to use; it will grab the JSON object stored in the // MANAGED_AZURE_HCP_CREDENTIALS_FILE_PATH and mount it as a volume in the image registry pod in the path. - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { c.Env = append(c.Env, azureutil.CreateEnvVarsForAzureManagedIdentity(cpContext.HCP.Spec.Platform.Azure.AzureAuthenticationConfig.ManagedIdentities.ControlPlane.ImageRegistry.CredentialsSecretName)...) diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/router/config.go b/control-plane-operator/controllers/hostedcontrolplane/v2/router/config.go index 674f9021e5b..b7ce7f9541c 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/router/config.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/router/config.go @@ -62,7 +62,7 @@ func adaptConfig(cpContext component.WorkloadContext, cm *corev1.ConfigMap) erro } var keyVaultFQDN string - if azureutil.IsAroHCP() && azureutil.IsPrivateKeyVault(cpContext.HCP) { + if azureutil.IsAroHCPByHCP(cpContext.HCP) && azureutil.IsPrivateKeyVault(cpContext.HCP) { kvFQDN, err := azureutil.GetKeyVaultFQDN(cpContext.HCP) if err != nil { return fmt.Errorf("failed to get Key Vault FQDN: %w", err) diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/router/deployment.go b/control-plane-operator/controllers/hostedcontrolplane/v2/router/deployment.go index 205e96ec02b..0b34e02f698 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/router/deployment.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/router/deployment.go @@ -1,18 +1,18 @@ package router import ( - hyperv1 "github.com/openshift/hypershift/api/hypershift/v1beta1" component "github.com/openshift/hypershift/support/controlplane-component" + "github.com/openshift/hypershift/support/netutil" appsv1 "k8s.io/api/apps/v1" ) func adaptDeployment(cpContext component.WorkloadContext, deployment *appsv1.Deployment) error { - if swiftPodNetworkInstance := cpContext.HCP.Annotations[hyperv1.SwiftPodNetworkInstanceAnnotation]; swiftPodNetworkInstance != "" { + if pni := netutil.SwiftPodNetworkInstanceHCP(cpContext.HCP); pni != "" { if deployment.Spec.Template.Labels == nil { deployment.Spec.Template.Labels = map[string]string{} } - deployment.Spec.Template.Labels["kubernetes.azure.com/pod-network-instance"] = swiftPodNetworkInstance + deployment.Spec.Template.Labels["kubernetes.azure.com/pod-network-instance"] = pni } return nil diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/router/util/util.go b/control-plane-operator/controllers/hostedcontrolplane/v2/router/util/util.go index 0caa883956b..f277685141f 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/router/util/util.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/router/util/util.go @@ -2,7 +2,6 @@ package util import ( hyperv1 "github.com/openshift/hypershift/api/hypershift/v1beta1" - "github.com/openshift/hypershift/support/azureutil" "github.com/openshift/hypershift/support/netutil" ) @@ -17,11 +16,10 @@ func UseHCPRouter(hcp *hyperv1.HostedControlPlane) bool { if hcp.Spec.Platform.Type == hyperv1.IBMCloudPlatform { return false } - // For ARO HCP, the dedicated HCP router is only needed when the cluster is private - // (Swift enabled). LabelHCPRoutes returns true for all ARO to support the - // SharedIngressReconciler, but that doesn't mean a dedicated router deployment is needed. - if azureutil.IsAroHCP() { - return netutil.IsPrivateHCP(hcp) + // SharedIngress handles public routing for ARO-HCP; a dedicated HCP + // router is only needed when the cluster also has private access. + if netutil.UseSharedIngressHCP(hcp) && !netutil.IsPrivateHCP(hcp) { + return false } // Router infrastructure is needed when: // 1. Cluster has private access (Private or PublicAndPrivate) - for internal routes, OR diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/storage/azure.go b/control-plane-operator/controllers/hostedcontrolplane/v2/storage/azure.go index 5b6ba52bd1b..4bf3381dadd 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/storage/azure.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/storage/azure.go @@ -28,9 +28,9 @@ func adaptAzureCSISecret(cpContext component.WorkloadContext, managedIdentity hy Location: azureSpec.Location, } - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { azureConfig.AADMSIDataPlaneIdentityPath = path.Join(hyperconfig.ManagedAzureCertificatePath, managedIdentity.CredentialsSecretName) - } else if azureutil.IsSelfManagedAzure(cpContext.HCP.Spec.Platform.Type) { + } else { azureConfig.UseFederatedWorkloadIdentityExtension = true azureConfig.AADClientID = string(workloadIdentity.ClientID) azureConfig.AADFederatedTokenFile = "/var/run/secrets/openshift/serviceaccount/token" @@ -55,9 +55,9 @@ func adaptAzureCSISecret(cpContext component.WorkloadContext, managedIdentity hy func adaptAzureCSIDiskSecret(cpContext component.WorkloadContext, secret *corev1.Secret) error { var managedIdentity hyperv1.ManagedIdentity var workloadIdentity hyperv1.WorkloadIdentity - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { managedIdentity = cpContext.HCP.Spec.Platform.Azure.AzureAuthenticationConfig.ManagedIdentities.ControlPlane.Disk - } else if azureutil.IsSelfManagedAzure(cpContext.HCP.Spec.Platform.Type) { + } else { workloadIdentity = cpContext.HCP.Spec.Platform.Azure.AzureAuthenticationConfig.WorkloadIdentities.Disk } return adaptAzureCSISecret(cpContext, managedIdentity, workloadIdentity, secret) @@ -72,9 +72,9 @@ func adaptAzureCSIDiskSecretProvider(cpContext component.WorkloadContext, secret func adaptAzureCSIFileSecret(cpContext component.WorkloadContext, secret *corev1.Secret) error { var managedIdentity hyperv1.ManagedIdentity var workloadIdentity hyperv1.WorkloadIdentity - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { managedIdentity = cpContext.HCP.Spec.Platform.Azure.AzureAuthenticationConfig.ManagedIdentities.ControlPlane.File - } else if azureutil.IsSelfManagedAzure(cpContext.HCP.Spec.Platform.Type) { + } else { workloadIdentity = cpContext.HCP.Spec.Platform.Azure.AzureAuthenticationConfig.WorkloadIdentities.File } return adaptAzureCSISecret(cpContext, managedIdentity, workloadIdentity, secret) diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/storage/component.go b/control-plane-operator/controllers/hostedcontrolplane/v2/storage/component.go index 4655da99660..6caf7e91625 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/storage/component.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/storage/component.go @@ -83,7 +83,7 @@ func isStorageAndCSIManaged(cpContext component.WorkloadContext) (bool, error) { } func isAroHCP(cpContext component.WorkloadContext) bool { - return azureutil.IsAroHCP() + return azureutil.IsAroHCPByHCP(cpContext.HCP) } type operand struct { diff --git a/control-plane-operator/controllers/hostedcontrolplane/v2/storage/deployment.go b/control-plane-operator/controllers/hostedcontrolplane/v2/storage/deployment.go index 98e152c5c07..92f030271e7 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/v2/storage/deployment.go +++ b/control-plane-operator/controllers/hostedcontrolplane/v2/storage/deployment.go @@ -20,7 +20,7 @@ func adaptDeployment(cpContext component.WorkloadContext, deployment *appsv1.Dep // For managed Azure, we need to supply a couple of environment variables for CSO to pass on to the CSI controllers for disk and file. // CSO passes those on to the CSI deployment here - https://github.com/openshift/cluster-storage-operator/pull/517/files. // CSI then mounts the Secrets Provider Class here - https://github.com/openshift/csi-operator/pull/309/files. - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(cpContext.HCP) { c.Env = append(c.Env, corev1.EnvVar{ Name: "ARO_HCP_SECRET_PROVIDER_CLASS_FOR_DISK", diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go index d9a9e1394da..122b46d8c1c 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go @@ -1362,7 +1362,7 @@ func (r *reconciler) reconcileRBAC(ctx context.Context, hcp *hyperv1.HostedContr manifestAndReconcile[*rbacv1.RoleBinding]{manifest: manifests.KASConnectionCheckerRoleBinding, reconcile: rbac.ReconcileKASConnectionCheckerRoleBinding}, } - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHCP(hcp) { rbacReconciler = append(rbacReconciler, manifestAndReconcile[*rbacv1.ClusterRole]{manifest: manifests.AzureDiskCSIDriverNodeServiceAccountRole, reconcile: rbac.ReconcileAzureDiskCSIDriverNodeServiceAccountClusterRole}, manifestAndReconcile[*rbacv1.ClusterRoleBinding]{manifest: manifests.AzureDiskCSIDriverNodeServiceAccountRoleBinding, reconcile: rbac.ReconcileAzureDiskCSIDriverNodeServiceAccountClusterRoleBinding}, @@ -1515,7 +1515,7 @@ func (r *reconciler) reconcileAuthOIDC(ctx context.Context, hcp *hyperv1.HostedC errs = append(errs, fmt.Errorf("failed to get OIDCClient secret %s: %w", oidcClient.ClientSecret.Name, err)) continue } - if azureutil.IsAroHCP() && k8sutil.HasAnnotationWithValue(&src, hyperv1.HostedClusterSourcedAnnotation, "true") { + if azureutil.IsAroHCPByHCP(hcp) && k8sutil.HasAnnotationWithValue(&src, hyperv1.HostedClusterSourcedAnnotation, "true") { // This is a day-2 secret. We shouldn't copy it, instead it'll be provided by the end-user on the hosted cluster. continue } @@ -2187,7 +2187,7 @@ func (r *reconciler) reconcileCloudCredentialSecrets(ctx context.Context, hcp *h } // Set up the operand credentials for either managed or self-managed Azure environments - errs = azureresources.SetupOperandCredentials(ctx, r.client, r.CreateOrUpdateProvider, hcp, secretData, azureutil.IsAroHCP()) + errs = azureresources.SetupOperandCredentials(ctx, r.client, r.CreateOrUpdateProvider, hcp, secretData, azureutil.IsAroHCPByHCP(hcp)) if len(errs) > 0 { return errs } @@ -3465,7 +3465,7 @@ func (r *reconciler) reconcileStorage(ctx context.Context, hcp *hyperv1.HostedCo operatorv1.ManilaCSIDriver, } case hyperv1.AzurePlatform: - if azureutil.IsSelfManagedAzure(hcp.Spec.Platform.Type) { + if !azureutil.IsAroHCPByHCP(hcp) { driverNames = []operatorv1.CSIDriverName{ operatorv1.AzureDiskCSIDriver, operatorv1.AzureFileCSIDriver, diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources_test.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources_test.go index 7017deac878..8e1c5de8e35 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources_test.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources_test.go @@ -2033,6 +2033,20 @@ func TestReconcileAuthOIDC(t *testing.T) { Namespace: testNamespace, }, Spec: hyperv1.HostedControlPlaneSpec{ + Platform: hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + }, + }, + }, Configuration: &hyperv1.ClusterConfiguration{ Authentication: &configv1.AuthenticationSpec{ Type: configv1.AuthenticationTypeOIDC, diff --git a/docs/content/reference/aggregated-docs.md b/docs/content/reference/aggregated-docs.md index e1e9658ac27..5d0ca2e0ee9 100644 --- a/docs/content/reference/aggregated-docs.md +++ b/docs/content/reference/aggregated-docs.md @@ -40066,8 +40066,7 @@ in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
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.|
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. |
@@ -40107,6 +40107,23 @@ AzurePrivateLinkSpec
This field is required when type is “PrivateLink” and must not be set otherwise.
+|
+swift,omitzero
+
+
+AzureSwiftSpec
+
+
+ |
+
+(Optional)
+ 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. + |
+
"Swift"
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.
++(Appears on: +AzurePrivateSpec) +
++
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.
+ +| Field | +Description | +
|---|---|
+podNetworkInstance
+
+string
+
+ |
+
+ 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. + |
+
(Appears on: @@ -41640,6 +41699,12 @@ hosted cluster can be live migrated without experiencing a node restart
desired platform are valid. A failure here is unlikely to resolve without the changing user input. +"PublicEndpointExposed"
PublicEndpointExposed indicates whether public API server endpoints are +currently configured and exposed for this cluster via the management +cluster’s shared ingress. Status reflects observed state: True means +public endpoints are reachable, False means they are not.
+"ReconciliationActive"
ReconciliationActive indicates if reconciliation of the HostedCluster is active or paused hostedCluster.spec.pausedUntil.
diff --git a/docs/content/reference/api.md b/docs/content/reference/api.md index 828e8531ff1..7992d2a1d54 100644 --- a/docs/content/reference/api.md +++ b/docs/content/reference/api.md @@ -4381,8 +4381,7 @@ in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
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.|
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. |
@@ -4422,6 +4422,23 @@ AzurePrivateLinkSpec
This field is required when type is “PrivateLink” and must not be set otherwise.
+|
+swift,omitzero
+
+
+AzureSwiftSpec
+
+
+ |
+
+(Optional)
+ 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. + |
+
"Swift"
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.
++(Appears on: +AzurePrivateSpec) +
++
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.
+ +| Field | +Description | +
|---|---|
+podNetworkInstance
+
+string
+
+ |
+
+ 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. + |
+
(Appears on: @@ -5955,6 +6014,12 @@ hosted cluster can be live migrated without experiencing a node restart
desired platform are valid. A failure here is unlikely to resolve without the changing user input. +"PublicEndpointExposed"
PublicEndpointExposed indicates whether public API server endpoints are +currently configured and exposed for this cluster via the management +cluster’s shared ingress. Status reflects observed state: True means +public endpoints are reachable, False means they are not.
+"ReconciliationActive"
ReconciliationActive indicates if reconciliation of the HostedCluster is active or paused hostedCluster.spec.pausedUntil.
diff --git a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go index 095522e7bd2..f7c2deac532 100644 --- a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go +++ b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go @@ -213,6 +213,11 @@ type HostedClusterReconciler struct { FeatureSet configv1.FeatureSet OpenShiftTrustedCAFilePath string + + // ProbeSharedIngressEndpoint tests whether a public endpoint is reachable + // via the shared ingress. Defaults to probeSharedIngressEndpoint. Override + // in tests to avoid real network calls. + ProbeSharedIngressEndpoint func(context context.Context, serviceIP string, servicePort int, kasHostname string) bool } // +kubebuilder:rbac:groups=hypershift.openshift.io,resources=hostedclusters,verbs=get;list;watch;create;update;patch;delete @@ -991,7 +996,7 @@ func (r *HostedClusterReconciler) reconcile(ctx context.Context, req ctrl.Reques // Copy Azure Private Link conditions from the AzurePrivateLinkService resources. // ARO HCP uses Swift networking, not Private Link Services. - if hcluster.Spec.Platform.Type == hyperv1.AzurePlatform && !azureutil.IsAroHCP() { + if hcluster.Spec.Platform.Type == hyperv1.AzurePlatform && !netutil.UseSwiftNetworkingHC(hcluster) { hcpNamespace := manifests.HostedControlPlaneNamespace(hcluster.Namespace, hcluster.Name) var azPLSList hyperv1.AzurePrivateLinkServiceList if err := r.List(ctx, &azPLSList, &client.ListOptions{Namespace: hcpNamespace}); err != nil { @@ -2069,7 +2074,7 @@ func (r *HostedClusterReconciler) reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, err } case hyperv1.AzurePlatform: - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHC(hcluster) { // Reconcile CPO SecretProviderClass CR cpoSecretProviderClass := cpomanifests.ManagedAzureSecretProviderClass(config.ManagedAzureCPOSecretProviderClassName, hcp.Namespace) if _, err = createOrUpdate(ctx, r, cpoSecretProviderClass, func() error { @@ -2090,7 +2095,7 @@ func (r *HostedClusterReconciler) reconcile(ctx context.Context, req ctrl.Reques } if hcluster.Spec.SecretEncryption != nil && hcluster.Spec.SecretEncryption.KMS != nil { - if azureutil.IsAroHCP() { + if azureutil.IsAroHCPByHC(hcluster) { // Reconcile KMS SecretProviderClass CR kmsSecretProviderClass := cpomanifests.ManagedAzureSecretProviderClass(config.ManagedAzureKMSSecretProviderClassName, hcp.Namespace) if _, err := createOrUpdate(ctx, r, kmsSecretProviderClass, func() error { @@ -2113,6 +2118,12 @@ func (r *HostedClusterReconciler) reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, fmt.Errorf("failed to reconcile karpenter operator: %w", err) } + if pubEndpointRequeue, err := r.reconcilePublicEndpointExposedCondition(ctx, hcluster); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to reconcile PublicEndpointExposed condition: %w", err) + } else if pubEndpointRequeue != nil && (requeueAfter == nil || *pubEndpointRequeue < *requeueAfter) { + requeueAfter = pubEndpointRequeue + } + log.Info("successfully reconciled") result := ctrl.Result{} if requeueAfter != nil { @@ -3996,7 +4007,7 @@ func (r *HostedClusterReconciler) validateAzureConfig(hc *hyperv1.HostedCluster) // When topology is Private or PublicAndPrivate, the private field must be configured // to provide Azure Private Link Service settings for private API server access. // ARO HCP uses Swift networking, not Private Link Services. - if !azureutil.IsAroHCP() && + if !netutil.UseSwiftNetworkingHC(hc) && hc.Spec.Platform.Azure.Topology != "" && hc.Spec.Platform.Azure.Topology != hyperv1.AzureTopologyPublic && hc.Spec.Platform.Azure.Private.Type == "" { @@ -5217,7 +5228,7 @@ func ensureReferencedResourceAnnotation(ctx context.Context, client client.Clien } func ensureHostedResourcesAreEmpty(ctx context.Context, crclient client.Client, hcluster *hyperv1.HostedCluster, obj client.Object) error { - if !azureutil.IsAroHCP() || !k8sutil.HasAnnotationWithValue(obj, hyperv1.HostedClusterSourcedAnnotation, "true") { + if !azureutil.IsAroHCPByHC(hcluster) || !k8sutil.HasAnnotationWithValue(obj, hyperv1.HostedClusterSourcedAnnotation, "true") { return nil } var cm corev1.Secret @@ -5408,3 +5419,110 @@ func computeAzurePLSCondition(azPLSList hyperv1.AzurePrivateLinkServiceList, con } return computeEndpointServiceCondition(resourceConditions, conditionType, hyperv1.AzurePLSErrorReason, hyperv1.AzurePLSSuccessReason, "AzurePrivateLinkService conditions not found") } + +const publicEndpointProbeTimeout = 3 * time.Second + +func (r *HostedClusterReconciler) reconcilePublicEndpointExposedCondition(ctx context.Context, hc *hyperv1.HostedCluster) (*time.Duration, error) { + if !netutil.UseSwiftNetworkingHC(hc) { + return nil, nil + } + + kasStrategy := netutil.ServicePublishingStrategyByTypeByHC(hc, hyperv1.APIServer) + if kasStrategy == nil || kasStrategy.Route == nil || kasStrategy.Route.Hostname == "" { + return nil, nil + } + kasHostname := kasStrategy.Route.Hostname + + svc := &corev1.Service{} + svcKey := client.ObjectKey{Namespace: "hypershift-sharedingress", Name: "router"} + if err := r.Client.Get(ctx, svcKey, svc); err != nil { + if apierrors.IsNotFound(err) { + return nil, nil + } + return nil, fmt.Errorf("failed to get shared ingress service: %w", err) + } + if svc.Spec.ClusterIP == "" || svc.Spec.ClusterIP == "None" { + return nil, nil + } + + lbReady := len(svc.Status.LoadBalancer.Ingress) > 0 && + (svc.Status.LoadBalancer.Ingress[0].Hostname != "" || svc.Status.LoadBalancer.Ingress[0].IP != "") + usesSharedIngress := netutil.UseSharedIngressHC(hc) + + if !lbReady && usesSharedIngress { + condition := metav1.Condition{ + Type: string(hyperv1.PublicEndpointExposed), + Status: metav1.ConditionFalse, + Reason: hyperv1.PublicEndpointConvergenceInProgressReason, + Message: "Shared ingress LoadBalancer is not ready", + ObservedGeneration: hc.Generation, + } + if meta.SetStatusCondition(&hc.Status.Conditions, condition) { + if err := r.Client.Status().Update(ctx, hc); err != nil { + return nil, fmt.Errorf("failed to update PublicEndpointExposed condition: %w", err) + } + } + d := 10 * time.Second + return &d, nil + } + + probeFn := r.ProbeSharedIngressEndpoint + if probeFn == nil { + probeFn = probeSharedIngressEndpoint + } + exposed := probeFn(ctx, svc.Spec.ClusterIP, 443, kasHostname) + + var condition metav1.Condition + condition.Type = string(hyperv1.PublicEndpointExposed) + condition.ObservedGeneration = hc.Generation + var requeue *time.Duration + + switch { + case exposed && usesSharedIngress: + condition.Status = metav1.ConditionTrue + condition.Reason = hyperv1.PublicEndpointSharedIngressConfiguredReason + condition.Message = "Public API server endpoint is reachable via shared ingress" + + case !exposed && usesSharedIngress: + condition.Status = metav1.ConditionFalse + condition.Reason = hyperv1.PublicEndpointConvergenceInProgressReason + condition.Message = "Public endpoint configuration in progress" + d := 10 * time.Second + requeue = &d + + case exposed && !usesSharedIngress: + condition.Status = metav1.ConditionTrue + condition.Reason = hyperv1.PublicEndpointConvergenceInProgressReason + condition.Message = "Public endpoint removal in progress" + d := 10 * time.Second + requeue = &d + + case !exposed && !usesSharedIngress: + condition.Status = metav1.ConditionFalse + condition.Reason = hyperv1.PublicEndpointTopologyPrivateReason + condition.Message = "Public API server endpoint is not exposed via shared ingress" + } + + if meta.SetStatusCondition(&hc.Status.Conditions, condition) { + if err := r.Client.Status().Update(ctx, hc); err != nil { + return nil, fmt.Errorf("failed to update PublicEndpointExposed condition: %w", err) + } + } + return requeue, nil +} + +func probeSharedIngressEndpoint(context context.Context, serviceIP string, servicePort int, kasHostname string) bool { + dialer := &tls.Dialer{ + NetDialer: &net.Dialer{Timeout: publicEndpointProbeTimeout}, + Config: &tls.Config{ + ServerName: kasHostname, + InsecureSkipVerify: true, //nolint:gosec + }, + } + conn, err := dialer.DialContext(context, "tcp", net.JoinHostPort(serviceIP, strconv.Itoa(servicePort))) + if err != nil { + return false + } + conn.Close() + return true +} diff --git a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go index 668ffd25206..a2bb4c59082 100644 --- a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go +++ b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go @@ -1804,7 +1804,7 @@ func TestHostedClusterWatchesEverythingItCreates(t *testing.T) { SubscriptionID: "12345678-1234-1234-1234-123456789abc", SecurityGroupID: "/subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/test-resource-group/providers/Microsoft.Network/networkSecurityGroups/test-nsg", AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ - AzureAuthenticationConfigType: "WorkloadIdentities", + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, WorkloadIdentities: &hyperv1.AzureWorkloadIdentities{ ImageRegistry: hyperv1.WorkloadIdentity{ClientID: "12345678-1234-1234-1234-123456789abc"}, Ingress: hyperv1.WorkloadIdentity{ClientID: "12345678-1234-1234-1234-123456789abc"}, @@ -1868,6 +1868,12 @@ func TestHostedClusterWatchesEverythingItCreates(t *testing.T) { }, }, TenantID: "12345678-1234-1234-1234-123456789abc", + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, }, }, Release: hyperv1.Release{ @@ -5395,6 +5401,22 @@ func TestEnsureHostedResourcesAreEmpty(t *testing.T) { Namespace: namespace, }, } + if tc.setAROHCP { + hcluster.Spec.Platform = hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + }, + }, + } + } // Create a Secret that would exist in the cluster secret := &corev1.Secret{ @@ -6939,6 +6961,12 @@ func TestValidateAzureConfig(t *testing.T) { Type: hyperv1.AzurePlatform, Azure: &hyperv1.AzurePlatformSpec{ Topology: hyperv1.AzureTopologyPrivate, + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, }, }, }, diff --git a/hypershift-operator/controllers/hostedcluster/network_policies.go b/hypershift-operator/controllers/hostedcluster/network_policies.go index 056d3ce3611..684fbbd710a 100644 --- a/hypershift-operator/controllers/hostedcluster/network_policies.go +++ b/hypershift-operator/controllers/hostedcluster/network_policies.go @@ -15,6 +15,7 @@ import ( "github.com/openshift/hypershift/support/awsutil" "github.com/openshift/hypershift/support/capabilities" "github.com/openshift/hypershift/support/config" + "github.com/openshift/hypershift/support/netutil" "github.com/openshift/hypershift/support/rhobsmonitoring" "github.com/openshift/hypershift/support/upsert" @@ -79,7 +80,7 @@ func (r *HostedClusterReconciler) reconcileNetworkPolicies(ctx context.Context, return err } - if sharedingress.UseSharedIngress() { + if netutil.UseSharedIngressHC(hcluster) { policy := networkpolicy.SharedIngressNetworkPolicy(controlPlaneNamespaceName) if _, err := createOrUpdate(ctx, r.Client, policy, func() error { return reconcileSharedIngressNetworkPolicy(policy, hcluster) diff --git a/hypershift-operator/controllers/hostedcluster/public_endpoint_condition_test.go b/hypershift-operator/controllers/hostedcluster/public_endpoint_condition_test.go new file mode 100644 index 00000000000..0e7f88805d1 --- /dev/null +++ b/hypershift-operator/controllers/hostedcluster/public_endpoint_condition_test.go @@ -0,0 +1,209 @@ +package hostedcluster + +import ( + "context" + "testing" + "time" + + . "github.com/onsi/gomega" + + hyperv1 "github.com/openshift/hypershift/api/hypershift/v1beta1" + api "github.com/openshift/hypershift/support/api" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + crclient "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func sharedIngressService(clusterIP string, lbHostname string) *corev1.Service { + svc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "router", + Namespace: "hypershift-sharedingress", + }, + Spec: corev1.ServiceSpec{ + ClusterIP: clusterIP, + }, + } + if lbHostname != "" { + svc.Status.LoadBalancer.Ingress = []corev1.LoadBalancerIngress{ + {Hostname: lbHostname}, + } + } + return svc +} + +func swiftHostedCluster(name string, topology hyperv1.AzureTopologyType, kasHostname string) *hyperv1.HostedCluster { + return &hyperv1.HostedCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "clusters", + Generation: 1, + }, + Spec: hyperv1.HostedClusterSpec{ + Platform: hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Topology: topology, + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + }, + }, + }, + Services: []hyperv1.ServicePublishingStrategyMapping{ + { + Service: hyperv1.APIServer, + ServicePublishingStrategy: hyperv1.ServicePublishingStrategy{ + Type: hyperv1.Route, + Route: &hyperv1.RoutePublishingStrategy{ + Hostname: kasHostname, + }, + }, + }, + }, + }, + } +} + +func TestReconcilePublicEndpointExposedCondition(t *testing.T) { + tests := []struct { + name string + hc *hyperv1.HostedCluster + svc *corev1.Service + probeResult bool + expectCondition bool + expectStatus metav1.ConditionStatus + expectReason string + expectRequeue bool + }{ + { + name: "When cluster is not Swift it should not set condition", + hc: &hyperv1.HostedCluster{ + ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "clusters", Generation: 1}, + Spec: hyperv1.HostedClusterSpec{ + Platform: hyperv1.PlatformSpec{ + Type: hyperv1.AWSPlatform, + }, + }, + }, + expectCondition: false, + }, + { + name: "When shared ingress service is not found it should not set condition", + hc: swiftHostedCluster("test", hyperv1.AzureTopologyPublicAndPrivate, "api.test.example.com"), + svc: nil, + expectCondition: false, + }, + { + name: "When KAS hostname is not configured it should not set condition", + hc: swiftHostedCluster("test", hyperv1.AzureTopologyPublicAndPrivate, ""), + svc: sharedIngressService("10.0.0.1", "lb.example.com"), + expectCondition: false, + }, + { + name: "When LB is not ready and cluster uses shared ingress it should set False with ConvergenceInProgress", + hc: swiftHostedCluster("test", hyperv1.AzureTopologyPublicAndPrivate, "api.test.example.com"), + svc: sharedIngressService("10.0.0.1", ""), + expectCondition: true, + expectStatus: metav1.ConditionFalse, + expectReason: hyperv1.PublicEndpointConvergenceInProgressReason, + expectRequeue: true, + }, + { + name: "When probe succeeds and cluster uses shared ingress it should set True with SharedIngressConfigured", + hc: swiftHostedCluster("test", hyperv1.AzureTopologyPublicAndPrivate, "api.test.example.com"), + svc: sharedIngressService("10.0.0.1", "lb.example.com"), + probeResult: true, + expectCondition: true, + expectStatus: metav1.ConditionTrue, + expectReason: hyperv1.PublicEndpointSharedIngressConfiguredReason, + expectRequeue: false, + }, + { + name: "When probe fails and cluster uses shared ingress it should set False with ConvergenceInProgress", + hc: swiftHostedCluster("test", hyperv1.AzureTopologyPublicAndPrivate, "api.test.example.com"), + svc: sharedIngressService("10.0.0.1", "lb.example.com"), + probeResult: false, + expectCondition: true, + expectStatus: metav1.ConditionFalse, + expectReason: hyperv1.PublicEndpointConvergenceInProgressReason, + expectRequeue: true, + }, + { + name: "When probe succeeds but cluster is Private it should set True with ConvergenceInProgress", + hc: swiftHostedCluster("test", hyperv1.AzureTopologyPrivate, "api.test.example.com"), + svc: sharedIngressService("10.0.0.1", "lb.example.com"), + probeResult: true, + expectCondition: true, + expectStatus: metav1.ConditionTrue, + expectReason: hyperv1.PublicEndpointConvergenceInProgressReason, + expectRequeue: true, + }, + { + name: "When probe fails and cluster is Private it should set False with TopologyPrivate", + hc: swiftHostedCluster("test", hyperv1.AzureTopologyPrivate, "api.test.example.com"), + svc: sharedIngressService("10.0.0.1", "lb.example.com"), + probeResult: false, + expectCondition: true, + expectStatus: metav1.ConditionFalse, + expectReason: hyperv1.PublicEndpointTopologyPrivateReason, + expectRequeue: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + + objects := []crclient.Object{tt.hc} + if tt.svc != nil { + objects = append(objects, tt.svc) + } + cl := fake.NewClientBuilder(). + WithScheme(api.Scheme). + WithObjects(objects...). + WithStatusSubresource(tt.hc). + Build() + + r := &HostedClusterReconciler{ + Client: cl, + ProbeSharedIngressEndpoint: func(context context.Context, serviceIP string, servicePort int, kasHostname string) bool { + return tt.probeResult + }, + } + + requeue, err := r.reconcilePublicEndpointExposedCondition(t.Context(), tt.hc) + g.Expect(err).ToNot(HaveOccurred()) + + if tt.expectRequeue { + g.Expect(requeue).ToNot(BeNil(), "expected requeue") + g.Expect(*requeue).To(Equal(10 * time.Second)) + } else { + g.Expect(requeue).To(BeNil(), "expected no requeue") + } + + updatedHC := &hyperv1.HostedCluster{} + g.Expect(cl.Get(t.Context(), crclient.ObjectKeyFromObject(tt.hc), updatedHC)).To(Succeed()) + + condition := meta.FindStatusCondition(updatedHC.Status.Conditions, string(hyperv1.PublicEndpointExposed)) + if !tt.expectCondition { + g.Expect(condition).To(BeNil(), "expected no PublicEndpointExposed condition") + return + } + + g.Expect(condition).ToNot(BeNil(), "expected PublicEndpointExposed condition to be set") + g.Expect(condition.Status).To(Equal(tt.expectStatus), "unexpected condition status") + g.Expect(condition.Reason).To(Equal(tt.expectReason), "unexpected condition reason") + g.Expect(condition.ObservedGeneration).To(Equal(tt.hc.Generation)) + }) + } +} diff --git a/hypershift-operator/controllers/nodepool/apiserver-haproxy/haproxy.go b/hypershift-operator/controllers/nodepool/apiserver-haproxy/haproxy.go index df8ba33615e..1118e8f1f2a 100644 --- a/hypershift-operator/controllers/nodepool/apiserver-haproxy/haproxy.go +++ b/hypershift-operator/controllers/nodepool/apiserver-haproxy/haproxy.go @@ -157,7 +157,7 @@ func (r *HAProxy) reconcileHAProxyIgnitionConfig(ctx context.Context, hcluster * } // This is true for ARO in CI while swift is not available. - if sharedingress.UseSharedIngress() && !netutil.IsPrivateHC(hcluster) { + if netutil.UseSharedIngressHC(hcluster) && !netutil.IsPrivateHC(hcluster) { sharedIngressRouteSVC := &corev1.Service{ TypeMeta: metav1.TypeMeta{}, ObjectMeta: metav1.ObjectMeta{ @@ -175,7 +175,7 @@ func (r *HAProxy) reconcileHAProxyIgnitionConfig(ctx context.Context, hcluster * apiServerExternalPort = sharedingress.KASSVCLBPort } - useProxyProtocol := sharedingress.UseSharedIngress() && !netutil.IsPrivateHC(hcluster) + useProxyProtocol := netutil.UseSharedIngressHC(hcluster) && !netutil.IsPrivateHC(hcluster) serializedConfig, err := apiServerProxyConfig(r.HAProxyImage, controlPlaneOperatorImage, hcluster.Spec.ClusterID, apiServerExternalAddress, apiServerInternalAddress, apiServerExternalPort, apiServerInternalPort, diff --git a/hypershift-operator/controllers/nodepool/apiserver-haproxy/haproxy_test.go b/hypershift-operator/controllers/nodepool/apiserver-haproxy/haproxy_test.go index 44b32b29ba3..c938f1a9962 100644 --- a/hypershift-operator/controllers/nodepool/apiserver-haproxy/haproxy_test.go +++ b/hypershift-operator/controllers/nodepool/apiserver-haproxy/haproxy_test.go @@ -396,6 +396,14 @@ kind: Config` hc: hc(func(hc *hyperv1.HostedCluster) { hc.Spec.Platform.Type = hyperv1.AzurePlatform hc.Spec.Platform.AWS = nil + hc.Spec.Platform.Azure = &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-swift-instance", + }, + }, + } hc.ObjectMeta.Annotations = map[string]string{ hyperv1.SwiftPodNetworkInstanceAnnotation: "test-swift-instance", } @@ -422,13 +430,25 @@ kind: Config` expectedHAProxyConfigContent: []string{"api.hc.hypershift.local:443"}, }, { - name: "When ARO and no Swift is used (CI) it should use the shared ingress LB service IP, port 6443 and proxy protocol", + name: "When ARO shared ingress is used it should use the shared ingress LB service IP, port 6443 and proxy protocol", setupEnv: func(t *testing.T) { azureutil.SetAsAroHCPTest(t) }, hc: hc(func(hc *hyperv1.HostedCluster) { hc.Spec.Platform.Type = hyperv1.AzurePlatform hc.Spec.Platform.AWS = nil + hc.Spec.Platform.Azure = &hyperv1.AzurePlatformSpec{ + Topology: hyperv1.AzureTopologyPublic, + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + }, + } hc.Status.KubeConfig = &corev1.LocalObjectReference{Name: "kk"} hc.Spec.Networking.ServiceNetwork = []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("192.168.1.0/24")}} hc.Spec.Services = []hyperv1.ServicePublishingStrategyMapping{ diff --git a/hypershift-operator/controllers/nodepool/apiserver-haproxy/testdata/zz_fixture_TestReconcileHAProxyIgnitionConfig_When_ARO__and_no_Swift_is_used_CI__it_should_use_the_shared_ingress_LB_service_IP__port_6443_and_proxy_protocol.yaml b/hypershift-operator/controllers/nodepool/apiserver-haproxy/testdata/zz_fixture_TestReconcileHAProxyIgnitionConfig_When_ARO_shared_ingress_is_used_it_should_use_the_shared_ingress_LB_service_IP__port_6443_and_proxy_protocol.yaml similarity index 100% rename from hypershift-operator/controllers/nodepool/apiserver-haproxy/testdata/zz_fixture_TestReconcileHAProxyIgnitionConfig_When_ARO__and_no_Swift_is_used_CI__it_should_use_the_shared_ingress_LB_service_IP__port_6443_and_proxy_protocol.yaml rename to hypershift-operator/controllers/nodepool/apiserver-haproxy/testdata/zz_fixture_TestReconcileHAProxyIgnitionConfig_When_ARO_shared_ingress_is_used_it_should_use_the_shared_ingress_LB_service_IP__port_6443_and_proxy_protocol.yaml diff --git a/hypershift-operator/controllers/nodepool/nodepool_controller.go b/hypershift-operator/controllers/nodepool/nodepool_controller.go index 8a550972e4a..b2b89f4f769 100644 --- a/hypershift-operator/controllers/nodepool/nodepool_controller.go +++ b/hypershift-operator/controllers/nodepool/nodepool_controller.go @@ -16,12 +16,12 @@ import ( haproxy "github.com/openshift/hypershift/hypershift-operator/controllers/nodepool/apiserver-haproxy" "github.com/openshift/hypershift/hypershift-operator/controllers/nodepool/instancetype" "github.com/openshift/hypershift/hypershift-operator/controllers/nodepool/kubevirt" - "github.com/openshift/hypershift/hypershift-operator/controllers/sharedingress" kvinfra "github.com/openshift/hypershift/kubevirtexternalinfra" "github.com/openshift/hypershift/support/awsapi" "github.com/openshift/hypershift/support/capabilities" "github.com/openshift/hypershift/support/images" "github.com/openshift/hypershift/support/k8sutil" + "github.com/openshift/hypershift/support/netutil" "github.com/openshift/hypershift/support/releaseinfo" "github.com/openshift/hypershift/support/supportedversion" "github.com/openshift/hypershift/support/upsert" @@ -1084,21 +1084,17 @@ func (r *NodePoolReconciler) getAdditionalTrustBundle(ctx context.Context, hoste // resolveHAProxyImage determines which HAProxy image to use based on priority: // 1. NodePool annotation (highest priority) -// 2. Environment variable override (when shared ingress enabled) -// 3. Hardcoded default (when shared ingress enabled) -// 4. Release payload (default) -func resolveHAProxyImage(nodePool *hyperv1.NodePool, releaseImage *releaseinfo.ReleaseImage) (string, error) { - // Check NodePool annotation first (highest priority) +// 2. Shared ingress image (when cluster uses shared ingress for public endpoints) +// 3. Release payload (default) +func resolveHAProxyImage(nodePool *hyperv1.NodePool, hcluster *hyperv1.HostedCluster, releaseImage *releaseinfo.ReleaseImage) (string, error) { if annotationImage := strings.TrimSpace(nodePool.Annotations[hyperv1.NodePoolHAProxyImageAnnotation]); annotationImage != "" { return annotationImage, nil } - // Check if shared ingress is enabled - if sharedingress.UseSharedIngress() { + if netutil.UseSharedIngressHC(hcluster) { return images.GetSharedIngressHAProxyImage(), nil } - // Fall back to release payload image haProxyImage, ok := releaseImage.ComponentImages()[haproxy.HAProxyRouterImageName] if !ok { return "", fmt.Errorf("release image doesn't have a %s image", haproxy.HAProxyRouterImageName) @@ -1107,7 +1103,7 @@ func resolveHAProxyImage(nodePool *hyperv1.NodePool, releaseImage *releaseinfo.R } func (r *NodePoolReconciler) generateHAProxyRawConfig(ctx context.Context, nodePool *hyperv1.NodePool, hcluster *hyperv1.HostedCluster, releaseImage *releaseinfo.ReleaseImage) (string, error) { - haProxyImage, err := resolveHAProxyImage(nodePool, releaseImage) + haProxyImage, err := resolveHAProxyImage(nodePool, hcluster, releaseImage) if err != nil { return "", err } diff --git a/hypershift-operator/controllers/nodepool/nodepool_controller_test.go b/hypershift-operator/controllers/nodepool/nodepool_controller_test.go index 210b69afcef..2783e89f120 100644 --- a/hypershift-operator/controllers/nodepool/nodepool_controller_test.go +++ b/hypershift-operator/controllers/nodepool/nodepool_controller_test.go @@ -2652,12 +2652,29 @@ kind: Config`), Namespace: "clusters", }, Spec: hyperv1.HostedClusterSpec{ - Platform: hyperv1.PlatformSpec{ - Type: hyperv1.AWSPlatform, - AWS: &hyperv1.AWSPlatformSpec{ - EndpointAccess: hyperv1.Public, - }, - }, + Platform: func() hyperv1.PlatformSpec { + if tc.useSharedIngress { + return hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Topology: hyperv1.AzureTopologyPublicAndPrivate, + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{PodNetworkInstance: "test-pni"}, + }, + AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + }, + }, + } + } + return hyperv1.PlatformSpec{ + Type: hyperv1.AWSPlatform, + AWS: &hyperv1.AWSPlatformSpec{ + EndpointAccess: hyperv1.Public, + }, + } + }(), Networking: hyperv1.ClusterNetworking{ ServiceNetwork: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("192.168.1.0/24")}}, }, diff --git a/sharedingress-config-generator/config.go b/sharedingress-config-generator/config.go index 6810c004e99..998bdd04e66 100644 --- a/sharedingress-config-generator/config.go +++ b/sharedingress-config-generator/config.go @@ -85,6 +85,10 @@ func generateRouterConfig(ctx context.Context, client crclient.Client, w io.Writ if !hc.DeletionTimestamp.IsZero() { continue } + // Skip clusters that don't use shared ingress (Private topology or non-Swift). + if !netutil.UseSharedIngressHC(&hc) { + continue + } backends, externalDNSBackends, err := getBackendsForHostedCluster(ctx, hc, client) if err != nil { diff --git a/sharedingress-config-generator/config_test.go b/sharedingress-config-generator/config_test.go index 53bd460f05c..962d6698e78 100644 --- a/sharedingress-config-generator/config_test.go +++ b/sharedingress-config-generator/config_test.go @@ -108,6 +108,21 @@ func TestGenerateConfig(t *testing.T) { Spec: hyperv1.HostedClusterSpec{ ClusterID: "hc1-UUID", KubeAPIServerDNSName: "kube-apiserver-public-custom.example.com", + Platform: hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + Topology: hyperv1.AzureTopologyPublicAndPrivate, + AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + }, + }, + }, }, }, routes: []client.Object{ @@ -139,6 +154,21 @@ func TestGenerateConfig(t *testing.T) { }, }, }, + Platform: hyperv1.PlatformSpec{ + Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + Topology: hyperv1.AzureTopologyPublicAndPrivate, + AzureAuthenticationConfig: hyperv1.AzureAuthenticationConfiguration{ + AzureAuthenticationConfigType: hyperv1.AzureAuthenticationTypeManagedIdentities, + }, + }, + }, }, }, routes: []client.Object{ @@ -174,14 +204,20 @@ func TestGenerateConfig(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "hc1", Namespace: "test", - Annotations: map[string]string{ - hyperv1.SwiftPodNetworkInstanceAnnotation: "test-swift-instance", - }, }, Spec: hyperv1.HostedClusterSpec{ ClusterID: "hc1-UUID", Platform: hyperv1.PlatformSpec{ Type: hyperv1.AzurePlatform, + Azure: &hyperv1.AzurePlatformSpec{ + Private: hyperv1.AzurePrivateSpec{ + Type: hyperv1.AzurePrivateTypeSwift, + Swift: hyperv1.AzureSwiftSpec{ + PodNetworkInstance: "test-pni", + }, + }, + Topology: hyperv1.AzureTopologyPrivate, + }, }, }, }, diff --git a/sharedingress-config-generator/testdata/zz_fixture_TestGenerateConfig_When_ARO_Swift_is_enabled_it_should_skip_the_dataplane_kas_svc.cfg b/sharedingress-config-generator/testdata/zz_fixture_TestGenerateConfig_When_ARO_Swift_is_enabled_it_should_skip_the_dataplane_kas_svc.cfg index f658e9893cf..0c125167bdc 100644 --- a/sharedingress-config-generator/testdata/zz_fixture_TestGenerateConfig_When_ARO_Swift_is_enabled_it_should_skip_the_dataplane_kas_svc.cfg +++ b/sharedingress-config-generator/testdata/zz_fixture_TestGenerateConfig_When_ARO_Swift_is_enabled_it_should_skip_the_dataplane_kas_svc.cfg @@ -39,10 +39,6 @@ frontend external-dns tcp-request content set-var(sess.src_ip) src log-format "%{+Q}o\ src_ip = %[var(sess.src_ip)], %ci:%cp / %si:%sp -> %fi:%fp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq" - acl is_test-hc1-ignition req_ssl_sni -i ignition-server.example.com - acl is_test-hc1-apiserver req_ssl_sni -i kube-apiserver-public.example.com - use_backend test-hc1-ignition if is_test-hc1-ignition - use_backend test-hc1-apiserver if is_test-hc1-apiserver default_backend no-match @@ -54,10 +50,6 @@ listen health_check_http_url # Backends for the KAS SVCs to support traffic coming form the data plane via kubernetes.svc. # Backends support any traffic coming from external DNS. -backend test-hc1-ignition - server test-hc1-ignition 1.1.1.1:443 -backend test-hc1-apiserver - server test-hc1-apiserver 4.4.4.4:6443 backend no-match tcp-request content reject diff --git a/sharedingress-config-generator/testdata/zz_fixture_TestGenerateConfig_When_there_s_two_HostedClusters_with_all_their_Routes_and_SVCs_it_should_generate_the_config_with_frontends_and_backends_for_both.cfg b/sharedingress-config-generator/testdata/zz_fixture_TestGenerateConfig_When_there_s_two_HostedClusters_with_all_their_Routes_and_SVCs_it_should_generate_the_config_with_frontends_and_backends_for_both.cfg index dac4686b904..d8ea59b32dc 100644 --- a/sharedingress-config-generator/testdata/zz_fixture_TestGenerateConfig_When_there_s_two_HostedClusters_with_all_their_Routes_and_SVCs_it_should_generate_the_config_with_frontends_and_backends_for_both.cfg +++ b/sharedingress-config-generator/testdata/zz_fixture_TestGenerateConfig_When_there_s_two_HostedClusters_with_all_their_Routes_and_SVCs_it_should_generate_the_config_with_frontends_and_backends_for_both.cfg @@ -27,12 +27,6 @@ frontend dataplane-kas-svc # example output: cluster_id = "4954e6da-fc87-4e74-9861-05895fe9549d", "169.254.169.1":38984 -> "172.20.0.1":6443 [10/Jul/2024:14:02:09.943] "dataplane-kas-svc" "