From 9e8bcfcb1c55597dfe464678c2a50cf54c925352 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Tue, 5 May 2026 14:18:13 +0300 Subject: [PATCH] fix(api): OCPBUGS-84303: add IPv6 OVN join subnet config to prevent dual-stack routing collision When a KubeVirt hosted cluster and its management cluster both use OVN-Kubernetes with dual-stack networking, they each default to fd98::/64 for the IPv6 join switch subnet. External IPv6 LoadBalancer traffic targeting VM pods is SNAT'd to the management cluster's join IP (e.g. fd98::2). Inside the VM, the guest cluster's OVN intercepts the response because it also owns fd98::/64, black-holing the packet. This commit fixes the issue in two ways: 1. Automatic KubeVirt default: for KubeVirt hosted clusters with OVNKubernetes, the reconciler now sets IPv6.InternalJoinSubnet to fd99::/64 by default, avoiding the collision with the management cluster's fd98::/64. This mirrors the existing V4InternalSubnet override (100.66.0.0/16) already in place for IPv4. 2. User-facing API: adds OVNIPv6Config type to OVNKubernetesConfig, allowing explicit configuration of IPv6 internalJoinSubnet and internalTransitSwitchSubnet for any platform. This maps to the upstream operatorv1.IPv6OVNKubernetesConfig and includes IPv6 CIDR format validation via CEL rules. Also extends CIDR overlap validation in the HostedCluster webhook to cover IPv6 OVN subnets, and adds envtest CRD validation cases. Fixes: https://redhat.atlassian.net/browse/OCPBUGS-84303 Signed-off-by: Oren Cohen Assisted-by: Claude --- api/hypershift/v1beta1/operator.go | 74 +++ .../v1beta1/zz_generated.deepcopy.go | 16 + .../AAA_ungated.yaml | 88 ++++ .../ClusterUpdateAcceptRisks.yaml | 88 ++++ .../ClusterVersionOperatorConfiguration.yaml | 88 ++++ .../ExternalOIDC.yaml | 88 ++++ ...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 88 ++++ .../ExternalOIDCWithUpstreamParity.yaml | 88 ++++ .../GCPPlatform.yaml | 88 ++++ .../HCPEtcdBackup.yaml | 88 ++++ ...perShiftOnlyDynamicResourceAllocation.yaml | 88 ++++ .../ImageStreamImportMode.yaml | 88 ++++ .../KMSEncryptionProvider.yaml | 88 ++++ .../OpenStack.yaml | 88 ++++ .../TLSAdherence.yaml | 88 ++++ .../AAA_ungated.yaml | 88 ++++ .../ClusterUpdateAcceptRisks.yaml | 88 ++++ .../ClusterVersionOperatorConfiguration.yaml | 88 ++++ .../ExternalOIDC.yaml | 88 ++++ ...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 88 ++++ .../ExternalOIDCWithUpstreamParity.yaml | 88 ++++ .../GCPPlatform.yaml | 88 ++++ .../HCPEtcdBackup.yaml | 88 ++++ ...perShiftOnlyDynamicResourceAllocation.yaml | 88 ++++ .../ImageStreamImportMode.yaml | 88 ++++ .../KMSEncryptionProvider.yaml | 88 ++++ .../OpenStack.yaml | 88 ++++ .../TLSAdherence.yaml | 88 ++++ .../hypershift/v1beta1/ovnipv6config.go | 47 ++ .../hypershift/v1beta1/ovnkubernetesconfig.go | 9 + client/applyconfiguration/utils.go | 2 + ...e.hostedclusters.networking.testsuite.yaml | 436 ++++++++++++++++++ ...usters-Hypershift-CustomNoUpgrade.crd.yaml | 88 ++++ ...hostedclusters-Hypershift-Default.crd.yaml | 88 ++++ ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 88 ++++ ...planes-Hypershift-CustomNoUpgrade.crd.yaml | 88 ++++ ...dcontrolplanes-Hypershift-Default.crd.yaml | 88 ++++ ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 88 ++++ .../resources/network/reconcile.go | 28 +- .../resources/network/reconcile_test.go | 172 ++++++- .../controllers/resources/resources.go | 21 +- docs/content/reference/aggregated-docs.md | 86 ++++ docs/content/reference/api.md | 86 ++++ .../hostedcluster/hostedcluster_controller.go | 44 ++ .../hostedcluster_controller_test.go | 157 ++++++- .../api/hypershift/v1beta1/operator.go | 74 +++ .../v1beta1/zz_generated.deepcopy.go | 16 + 47 files changed, 4068 insertions(+), 16 deletions(-) create mode 100644 client/applyconfiguration/hypershift/v1beta1/ovnipv6config.go diff --git a/api/hypershift/v1beta1/operator.go b/api/hypershift/v1beta1/operator.go index ee74790f5ba..c14858d3fa1 100644 --- a/api/hypershift/v1beta1/operator.go +++ b/api/hypershift/v1beta1/operator.go @@ -4,6 +4,20 @@ import ( operatorv1 "github.com/openshift/api/operator/v1" ) +const ( + // KubevirtDefaultV6InternalJoinSubnet is the default IPv6 OVN join subnet + // for KubeVirt hosted clusters. The upstream OVN-Kubernetes default is fd98::/64, + // but KubeVirt guests use fd99::/64 to avoid collisions with the management + // cluster's join subnet when both run OVN-Kubernetes. + KubevirtDefaultV6InternalJoinSubnet = "fd99::/64" + + // KubevirtDefaultV4InternalSubnet is the default IPv4 OVN internal subnet + // for KubeVirt hosted clusters. The upstream OVN-Kubernetes default gateway + // router LRP CIDR is 100.64.0.0/16 and the default UDNs is 100.65.0.0/16. + // KubeVirt guests use 100.66.0.0/16 to avoid collisions with the management cluster. + KubevirtDefaultV4InternalSubnet = "100.66.0.0/16" +) + // +kubebuilder:validation:Enum="";Normal;Debug;Trace;TraceAll type LogLevel string @@ -38,6 +52,7 @@ type ClusterVersionOperatorSpec struct { OperatorLogLevel LogLevel `json:"operatorLogLevel,omitempty"` } +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)", message="ovnKubernetesConfig is immutable once set and cannot be removed" type ClusterNetworkOperatorSpec struct { // disableMultiNetwork when set to true disables the Multus CNI plugin and related components // in the hosted cluster. This prevents the installation of multus daemon sets in the @@ -62,7 +77,11 @@ type ClusterNetworkOperatorSpec struct { // OVNKubernetesConfig contains OVN-Kubernetes specific configuration options. // https://github.com/openshift/api/blob/6d3c4e25a8d3aeb57ad61649d80c38cbd27d1cc8/operator/v1/types_network.go#L400-L471 // +kubebuilder:validation:XValidation:rule="!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet", message="internalJoinSubnet and internalTransitSwitchSubnet must not be the same" +// +kubebuilder:validation:XValidation:rule="!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet != self.ipv6.internalTransitSwitchSubnet", message="ipv6 internalJoinSubnet and internalTransitSwitchSubnet must not be the same" // +kubebuilder:validation:XValidation:rule="!has(oldSelf.mtu) || has(self.mtu)",message="mtu is immutable once set and cannot be removed" +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.ipv6) || has(self.ipv6)", message="ipv6 is immutable once set and cannot be removed" +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))", message="ipv6.internalJoinSubnet cannot be removed once set" +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))", message="ipv6.internalTransitSwitchSubnet cannot be removed once set" // +kubebuilder:validation:MinProperties=1 type OVNKubernetesConfig struct { // ipv4 allows users to configure IP settings for IPv4 connections. When omitted, @@ -71,6 +90,15 @@ type OVNKubernetesConfig struct { // +optional IPv4 *OVNIPv4Config `json:"ipv4,omitempty"` + // ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + // this means no opinions and the default configuration is used. Check individual + // fields within ipv6 for details of default values. + // For KubeVirt hosted clusters using dual-stack networking, it is recommended to + // set ipv6.internalJoinSubnet to a value different from the management cluster's + // join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + // +optional + IPv6 OVNIPv6Config `json:"ipv6,omitzero,omitempty"` + // mtu is the MTU to use for the tunnel interface on hosted cluster nodes. // This must be 100 bytes smaller than the uplink MTU. // When unset, the cluster-network-operator will determine the MTU automatically @@ -126,6 +154,52 @@ type OVNIPv4Config struct { InternalJoinSubnet string `json:"internalJoinSubnet,omitempty"` } +// OVNIPv6Config contains IPv6-specific configuration options for OVN-Kubernetes. +// https://github.com/openshift/api/blob/6d3c4e25a8d3aeb57ad61649d80c38cbd27d1cc8/operator/v1/types_network.go#L541-L570 +// +kubebuilder:validation:MinProperties=1 +type OVNIPv6Config struct { + // internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + // by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + // architecture that connects the cluster routers on each node together to enable + // east west traffic. The subnet chosen should not overlap with other networks + // specified for OVN-Kubernetes as well as other networks used on the host. + // When omitted, this means no opinion and the platform is left to choose a reasonable + // default which is subject to change over time. + // The current default subnet is fd97::/64. + // The subnet must be large enough to accommodate one IP per node in your cluster. + // The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + // IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + // The prefix length must be in the range /0 to /125 inclusive. + // This field is immutable once set. + // +kubebuilder:validation:MaxLength=48 + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:XValidation:rule="isCIDR(self) && cidr(self).ip().family() == 6", message="Subnet must be in valid IPv6 CIDR format (e.g., fd97::/64)" + // +kubebuilder:validation:XValidation:rule="isCIDR(self) && cidr(self).prefixLength() <= 125", message="subnet must be in the range /0 to /125 inclusive" + // +kubebuilder:validation:XValidation:rule="self == oldSelf", message="internalTransitSwitchSubnet is immutable" + // +optional + InternalTransitSwitchSubnet string `json:"internalTransitSwitchSubnet,omitempty"` + // internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + // default one is being already used by something else. It must not overlap with + // any other subnet being used by OpenShift or by the node network. The size of the + // subnet must be larger than the number of nodes. + // The current default value is fd98::/64. + // For KubeVirt hosted clusters, if this field is not set, HyperShift will + // automatically use fd99::/64 to avoid collisions with the management cluster's + // default join subnet (fd98::/64). + // The subnet must be large enough to accommodate one IP per node in your cluster. + // The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + // IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + // The prefix length must be in the range /0 to /125 inclusive. + // This field is immutable once set. + // +kubebuilder:validation:MaxLength=48 + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:XValidation:rule="isCIDR(self) && cidr(self).ip().family() == 6", message="Subnet must be in valid IPv6 CIDR format (e.g., fd98::/64)" + // +kubebuilder:validation:XValidation:rule="isCIDR(self) && cidr(self).prefixLength() <= 125", message="subnet must be in the range /0 to /125 inclusive" + // +kubebuilder:validation:XValidation:rule="self == oldSelf", message="internalJoinSubnet is immutable" + // +optional + InternalJoinSubnet string `json:"internalJoinSubnet,omitempty"` +} + // IngressOperatorSpec is the specification of the desired behavior of the Ingress Operator. type IngressOperatorSpec struct { // endpointPublishingStrategy is used to publish the default ingress controller endpoints. diff --git a/api/hypershift/v1beta1/zz_generated.deepcopy.go b/api/hypershift/v1beta1/zz_generated.deepcopy.go index 5954bdd73ad..a3d882374d2 100644 --- a/api/hypershift/v1beta1/zz_generated.deepcopy.go +++ b/api/hypershift/v1beta1/zz_generated.deepcopy.go @@ -3818,6 +3818,21 @@ func (in *OVNIPv4Config) DeepCopy() *OVNIPv4Config { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OVNIPv6Config) DeepCopyInto(out *OVNIPv6Config) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OVNIPv6Config. +func (in *OVNIPv6Config) DeepCopy() *OVNIPv6Config { + if in == nil { + return nil + } + out := new(OVNIPv6Config) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = *in @@ -3826,6 +3841,7 @@ func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = new(OVNIPv4Config) **out = **in } + out.IPv6 = in.IPv6 } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OVNKubernetesConfig. 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 d4f89dc7f67..4234b1a13db 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 @@ -3193,6 +3193,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3220,9 +3289,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 182195cebaf..7833c1f1f42 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 @@ -3184,6 +3184,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3211,9 +3280,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 dee9aaf22e9..d191a0438f0 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 @@ -3184,6 +3184,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3211,9 +3280,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' clusterVersionOperator: description: clusterVersionOperator specifies the configuration for the Cluster Version Operator in the hosted cluster. 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 712a324f90c..b3c02852d11 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 @@ -3516,6 +3516,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3543,9 +3612,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 708eef6074f..e900b328630 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 @@ -3656,6 +3656,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3683,9 +3752,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 9e677999707..664a407b1a0 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 @@ -3647,6 +3647,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3674,9 +3743,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 664ded88d91..37c0f3143ce 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 @@ -3184,6 +3184,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3211,9 +3280,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 96efc699101..74268b4fe21 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 @@ -3249,6 +3249,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3276,9 +3345,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 3d80cd00968..e562c5cdad1 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 @@ -3206,6 +3206,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3233,9 +3302,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 541f071eec4..8ce3d4fad19 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 @@ -3202,6 +3202,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3229,9 +3298,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 da86225a28b..a1db7dd2b09 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 @@ -3260,6 +3260,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3287,9 +3356,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 3da4a9e3002..becec024ca6 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 @@ -3184,6 +3184,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3211,9 +3280,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 3b6458eb9e3..589202c8289 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 @@ -3224,6 +3224,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3251,9 +3320,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 d1af5de7c6f..8915bf2fb64 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 @@ -3081,6 +3081,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3108,9 +3177,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 849aee00c07..1540ec8d3d4 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 @@ -3072,6 +3072,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3099,9 +3168,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 4f6507aeb1e..4b5cea37472 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 @@ -3072,6 +3072,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3099,9 +3168,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' clusterVersionOperator: description: clusterVersionOperator specifies the configuration for the Cluster Version Operator in the hosted cluster. 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 1de483a48ec..8a5926d9a09 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 @@ -3404,6 +3404,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3431,9 +3500,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 40bad65502c..e0eb8d100ec 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 @@ -3544,6 +3544,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3571,9 +3640,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 945cd0cc009..040e4977c09 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 @@ -3535,6 +3535,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3562,9 +3631,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 d11902b2fac..bcc6e44ccc1 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 @@ -3072,6 +3072,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3099,9 +3168,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 9d7f764d263..db74c118d76 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 @@ -3137,6 +3137,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3164,9 +3233,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 b8c3890b21b..1a0efedcce2 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 @@ -3094,6 +3094,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3121,9 +3190,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 f6b4ae7f3a2..1f8d79dfc0a 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 @@ -3090,6 +3090,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3117,9 +3186,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 426e52a7dca..a73adb34234 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 @@ -3148,6 +3148,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3175,9 +3244,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 675c1d6f721..e2cff3fb651 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 @@ -3072,6 +3072,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3099,9 +3168,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 bcb4a21223b..6595c34e17c 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 @@ -3112,6 +3112,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3139,9 +3208,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. diff --git a/client/applyconfiguration/hypershift/v1beta1/ovnipv6config.go b/client/applyconfiguration/hypershift/v1beta1/ovnipv6config.go new file mode 100644 index 00000000000..2205ac30a97 --- /dev/null +++ b/client/applyconfiguration/hypershift/v1beta1/ovnipv6config.go @@ -0,0 +1,47 @@ +/* + + +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 + +// OVNIPv6ConfigApplyConfiguration represents a declarative configuration of the OVNIPv6Config type for use +// with apply. +type OVNIPv6ConfigApplyConfiguration struct { + InternalTransitSwitchSubnet *string `json:"internalTransitSwitchSubnet,omitempty"` + InternalJoinSubnet *string `json:"internalJoinSubnet,omitempty"` +} + +// OVNIPv6ConfigApplyConfiguration constructs a declarative configuration of the OVNIPv6Config type for use with +// apply. +func OVNIPv6Config() *OVNIPv6ConfigApplyConfiguration { + return &OVNIPv6ConfigApplyConfiguration{} +} + +// WithInternalTransitSwitchSubnet sets the InternalTransitSwitchSubnet 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 InternalTransitSwitchSubnet field is set to the value of the last call. +func (b *OVNIPv6ConfigApplyConfiguration) WithInternalTransitSwitchSubnet(value string) *OVNIPv6ConfigApplyConfiguration { + b.InternalTransitSwitchSubnet = &value + return b +} + +// WithInternalJoinSubnet sets the InternalJoinSubnet 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 InternalJoinSubnet field is set to the value of the last call. +func (b *OVNIPv6ConfigApplyConfiguration) WithInternalJoinSubnet(value string) *OVNIPv6ConfigApplyConfiguration { + b.InternalJoinSubnet = &value + return b +} diff --git a/client/applyconfiguration/hypershift/v1beta1/ovnkubernetesconfig.go b/client/applyconfiguration/hypershift/v1beta1/ovnkubernetesconfig.go index 6d3627c5420..ec04a89fa38 100644 --- a/client/applyconfiguration/hypershift/v1beta1/ovnkubernetesconfig.go +++ b/client/applyconfiguration/hypershift/v1beta1/ovnkubernetesconfig.go @@ -21,6 +21,7 @@ package v1beta1 // with apply. type OVNKubernetesConfigApplyConfiguration struct { IPv4 *OVNIPv4ConfigApplyConfiguration `json:"ipv4,omitempty"` + IPv6 *OVNIPv6ConfigApplyConfiguration `json:"ipv6,omitempty"` MTU *int32 `json:"mtu,omitempty"` } @@ -38,6 +39,14 @@ func (b *OVNKubernetesConfigApplyConfiguration) WithIPv4(value *OVNIPv4ConfigApp return b } +// WithIPv6 sets the IPv6 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 IPv6 field is set to the value of the last call. +func (b *OVNKubernetesConfigApplyConfiguration) WithIPv6(value *OVNIPv6ConfigApplyConfiguration) *OVNKubernetesConfigApplyConfiguration { + b.IPv6 = value + return b +} + // WithMTU sets the MTU 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 MTU field is set to the value of the last call. diff --git a/client/applyconfiguration/utils.go b/client/applyconfiguration/utils.go index 77e8b9c056b..6c7a8f85bb0 100644 --- a/client/applyconfiguration/utils.go +++ b/client/applyconfiguration/utils.go @@ -347,6 +347,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &hypershiftv1beta1.OperatorConfigurationApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("OVNIPv4Config"): return &hypershiftv1beta1.OVNIPv4ConfigApplyConfiguration{} + case v1beta1.SchemeGroupVersion.WithKind("OVNIPv6Config"): + return &hypershiftv1beta1.OVNIPv6ConfigApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("OVNKubernetesConfig"): return &hypershiftv1beta1.OVNKubernetesConfigApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("PersistentVolumeEtcdStorageSpec"): diff --git a/cmd/install/assets/crds/hypershift-operator/tests/hostedclusters.hypershift.openshift.io/stable.hostedclusters.networking.testsuite.yaml b/cmd/install/assets/crds/hypershift-operator/tests/hostedclusters.hypershift.openshift.io/stable.hostedclusters.networking.testsuite.yaml index 66b1e94a813..8c0073612e1 100644 --- a/cmd/install/assets/crds/hypershift-operator/tests/hostedclusters.hypershift.openshift.io/stable.hostedclusters.networking.testsuite.yaml +++ b/cmd/install/assets/crds/hypershift-operator/tests/hostedclusters.hypershift.openshift.io/stable.hostedclusters.networking.testsuite.yaml @@ -619,3 +619,439 @@ tests: servicePublishingStrategy: type: Route route: {} + + - name: When ovnKubernetesConfig ipv6 is set and networkType is OVNKubernetes it should pass + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: + ovnKubernetesConfig: + ipv6: + internalJoinSubnet: "fd99::/64" + internalTransitSwitchSubnet: "fd97:1::/64" + dns: + baseDomain: example.com + platform: + type: AWS + 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 ovnKubernetesConfig has both ipv4 and ipv6 it should pass + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: + ovnKubernetesConfig: + ipv4: + internalJoinSubnet: "10.10.0.0/16" + ipv6: + internalJoinSubnet: "fd99::/64" + dns: + baseDomain: example.com + platform: + type: AWS + 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 ovnKubernetesConfig ipv6 has same internalJoinSubnet and internalTransitSwitchSubnet it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: + ovnKubernetesConfig: + ipv6: + internalJoinSubnet: "fd99::/64" + internalTransitSwitchSubnet: "fd99::/64" + dns: + baseDomain: example.com + platform: + type: AWS + 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: "ipv6 internalJoinSubnet and internalTransitSwitchSubnet must not be the same" + + - name: When ovnKubernetesConfig ipv6 internalJoinSubnet has invalid CIDR it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: + ovnKubernetesConfig: + ipv6: + internalJoinSubnet: "not-a-cidr" + dns: + baseDomain: example.com + platform: + type: AWS + 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: "Subnet must be in valid IPv6 CIDR format" + + - name: When ovnKubernetesConfig ipv6 internalTransitSwitchSubnet has invalid CIDR it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: + ovnKubernetesConfig: + ipv6: + internalTransitSwitchSubnet: "not-a-cidr" + dns: + baseDomain: example.com + platform: + type: AWS + 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: "Subnet must be in valid IPv6 CIDR format" + + - name: When ovnKubernetesConfig ipv6 internalJoinSubnet has prefix length greater than 125 it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: + ovnKubernetesConfig: + ipv6: + internalJoinSubnet: "fd99::/126" + dns: + baseDomain: example.com + platform: + type: AWS + 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: "subnet must be in the range /0 to /125 inclusive" + + - name: When ovnKubernetesConfig ipv6 internalTransitSwitchSubnet has prefix length greater than 125 it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: + ovnKubernetesConfig: + ipv6: + internalTransitSwitchSubnet: "fd97::/126" + dns: + baseDomain: example.com + platform: + type: AWS + 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: "subnet must be in the range /0 to /125 inclusive" + + - name: When ovnKubernetesConfig ipv6 is empty object it should fail MinProperties validation + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: + ovnKubernetesConfig: + ipv6: {} + dns: + baseDomain: example.com + platform: + type: AWS + 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: "should have at least 1 properties" + + onUpdate: + - name: When ovnKubernetesConfig is removed after being set it should fail + initial: | + apiVersion: hypershift.openshift.io/v1beta1 + kind: HostedCluster + spec: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: + ovnKubernetesConfig: + ipv4: + internalJoinSubnet: "10.10.0.0/16" + dns: + baseDomain: example.com + platform: + type: AWS + 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: + networking: + networkType: OVNKubernetes + operatorConfiguration: + clusterNetworkOperator: {} + dns: + baseDomain: example.com + platform: + type: AWS + 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: "ovnKubernetesConfig is immutable once set and cannot be removed" 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 d9d85e84b65..845889ca935 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 @@ -4015,6 +4015,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -4042,9 +4111,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' clusterVersionOperator: description: clusterVersionOperator specifies the configuration for the Cluster Version Operator in the hosted cluster. 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 617e99b9a77..13e9216276d 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 @@ -3685,6 +3685,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3712,9 +3781,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 59441394383..5de98208ef4 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 @@ -3886,6 +3886,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3913,9 +3982,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' clusterVersionOperator: description: clusterVersionOperator specifies the configuration for the Cluster Version Operator in the hosted cluster. 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 861af7174b2..e267097b2bc 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 @@ -3903,6 +3903,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3930,9 +3999,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' clusterVersionOperator: description: clusterVersionOperator specifies the configuration for the Cluster Version Operator in the hosted cluster. 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 14b2906319b..3dbb3485271 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 @@ -3573,6 +3573,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3600,9 +3669,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' ingressOperator: description: |- ingressOperator specifies the configuration for the Ingress Operator in the hosted cluster. 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 435b260f05f..8b61ee5d386 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 @@ -3774,6 +3774,75 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalJoinSubnet is immutable + rule: self == oldSelf + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + The prefix length must be in the range /0 to /125 inclusive. + This field is immutable once set. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: isCIDR(self) && cidr(self).ip().family() == + 6 + - message: subnet must be in the range /0 to /125 + inclusive + rule: isCIDR(self) && cidr(self).prefixLength() + <= 125 + - message: internalTransitSwitchSubnet is immutable + rule: self == oldSelf + type: object mtu: description: |- mtu is the MTU to use for the tunnel interface on hosted cluster nodes. @@ -3801,9 +3870,28 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: ipv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' - message: mtu is immutable once set and cannot be removed rule: '!has(oldSelf.mtu) || has(self.mtu)' + - message: ipv6 is immutable once set and cannot be removed + rule: '!has(oldSelf.ipv6) || has(self.ipv6)' + - message: ipv6.internalJoinSubnet cannot be removed once + set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) + || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))' + - message: ipv6.internalTransitSwitchSubnet cannot be removed + once set + rule: '!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) + || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))' type: object + x-kubernetes-validations: + - message: ovnKubernetesConfig is immutable once set and cannot + be removed + rule: '!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)' clusterVersionOperator: description: clusterVersionOperator specifies the configuration for the Cluster Version Operator in the hosted cluster. diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile.go index 22ddaa1ee60..1d22a3e2d4a 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile.go @@ -33,11 +33,10 @@ const kubevirtDefaultVXLANPort = uint32(9879) // 9880 is a currently unassigned IANA port in the user port range. const kubevirtDefaultGenevePort = uint32(9880) -// The default OVN gateway router LRP CIDR is 100.64.0.0/16 and the default UDNs -// is 100.65.0.0/16. We need to avoid that for kubernetes which runs nested. -const kubevirtDefaultV4InternalSubnet = "100.66.0.0/16" +const kubevirtDefaultV4InternalSubnet = hyperv1.KubevirtDefaultV4InternalSubnet +const kubevirtDefaultV6InternalJoinSubnet = hyperv1.KubevirtDefaultV6InternalJoinSubnet -func ReconcileNetworkOperator(network *operatorv1.Network, networkType hyperv1.NetworkType, platformType hyperv1.PlatformType, disableMultiNetwork bool, ovnConfig *hyperv1.OVNKubernetesConfig) { +func ReconcileNetworkOperator(network *operatorv1.Network, networkType hyperv1.NetworkType, platformType hyperv1.PlatformType, disableMultiNetwork bool, ovnConfig *hyperv1.OVNKubernetesConfig, hasIPv6Network bool) { switch platformType { case hyperv1.KubevirtPlatform: // Modify vxlan port to avoid collisions with management cluster's default vxlan port. @@ -61,6 +60,14 @@ func ReconcileNetworkOperator(network *operatorv1.Network, networkType hyperv1.N if network.Spec.DefaultNetwork.OVNKubernetesConfig.GenevePort == nil { network.Spec.DefaultNetwork.OVNKubernetesConfig.GenevePort = &port } + if hasIPv6Network { + if network.Spec.DefaultNetwork.OVNKubernetesConfig.IPv6 == nil { + network.Spec.DefaultNetwork.OVNKubernetesConfig.IPv6 = &operatorv1.IPv6OVNKubernetesConfig{} + } + if network.Spec.DefaultNetwork.OVNKubernetesConfig.IPv6.InternalJoinSubnet == "" { + network.Spec.DefaultNetwork.OVNKubernetesConfig.IPv6.InternalJoinSubnet = kubevirtDefaultV6InternalJoinSubnet + } + } } case hyperv1.PowerVSPlatform: if networkType == hyperv1.OVNKubernetes { @@ -95,6 +102,19 @@ func ReconcileNetworkOperator(network *operatorv1.Network, networkType hyperv1.N ovnCfg.IPv4.InternalTransitSwitchSubnet = ovnConfig.IPv4.InternalTransitSwitchSubnet } } + // Apply IPv6 configuration + if ovnConfig.IPv6.InternalJoinSubnet != "" { + if ovnCfg.IPv6 == nil { + ovnCfg.IPv6 = &operatorv1.IPv6OVNKubernetesConfig{} + } + ovnCfg.IPv6.InternalJoinSubnet = ovnConfig.IPv6.InternalJoinSubnet + } + if ovnConfig.IPv6.InternalTransitSwitchSubnet != "" { + if ovnCfg.IPv6 == nil { + ovnCfg.IPv6 = &operatorv1.IPv6OVNKubernetesConfig{} + } + ovnCfg.IPv6.InternalTransitSwitchSubnet = ovnConfig.IPv6.InternalTransitSwitchSubnet + } // Apply MTU configuration if ovnConfig.MTU > 0 { ovnCfg.MTU = ptr.To(uint32(ovnConfig.MTU)) diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile_test.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile_test.go index 534dd6587f6..8222e38dabe 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile_test.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile_test.go @@ -16,6 +16,7 @@ func TestReconcileDefaultIngressController(t *testing.T) { vxlanPort := kubevirtDefaultVXLANPort genevePort := kubevirtDefaultGenevePort v4InternalSubnet := kubevirtDefaultV4InternalSubnet + v6InternalJoinSubnet := kubevirtDefaultV6InternalJoinSubnet fakePort := uint32(11111) testsCases := []struct { @@ -25,6 +26,7 @@ func TestReconcileDefaultIngressController(t *testing.T) { inputPlatformType hyperv1.PlatformType disableMultiNetwork bool ovnConfig *hyperv1.OVNKubernetesConfig + hasIPv6Network bool expectedNetwork *operatorv1.Network }{ { @@ -33,6 +35,7 @@ func TestReconcileDefaultIngressController(t *testing.T) { inputNetworkType: hyperv1.OVNKubernetes, inputPlatformType: hyperv1.KubevirtPlatform, disableMultiNetwork: false, + hasIPv6Network: true, expectedNetwork: &operatorv1.Network{ ObjectMeta: NetworkOperator().ObjectMeta, Spec: operatorv1.NetworkSpec{ @@ -43,6 +46,9 @@ func TestReconcileDefaultIngressController(t *testing.T) { OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ GenevePort: &genevePort, V4InternalSubnet: v4InternalSubnet, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: v6InternalJoinSubnet, + }, }, }, }, @@ -119,6 +125,7 @@ func TestReconcileDefaultIngressController(t *testing.T) { inputNetworkType: hyperv1.OVNKubernetes, inputPlatformType: hyperv1.KubevirtPlatform, disableMultiNetwork: false, + hasIPv6Network: true, expectedNetwork: &operatorv1.Network{ ObjectMeta: NetworkOperator().ObjectMeta, Spec: operatorv1.NetworkSpec{ @@ -129,6 +136,9 @@ func TestReconcileDefaultIngressController(t *testing.T) { OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ GenevePort: &fakePort, V4InternalSubnet: kubevirtDefaultV4InternalSubnet, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: v6InternalJoinSubnet, + }, }, }, }, @@ -153,6 +163,7 @@ func TestReconcileDefaultIngressController(t *testing.T) { inputNetworkType: hyperv1.OVNKubernetes, inputPlatformType: hyperv1.KubevirtPlatform, disableMultiNetwork: false, + hasIPv6Network: true, expectedNetwork: &operatorv1.Network{ ObjectMeta: NetworkOperator().ObjectMeta, Spec: operatorv1.NetworkSpec{ @@ -163,6 +174,9 @@ func TestReconcileDefaultIngressController(t *testing.T) { OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ V4InternalSubnet: "100.66.0.0/16", GenevePort: &genevePort, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: v6InternalJoinSubnet, + }, }, }, }, @@ -362,6 +376,7 @@ func TestReconcileDefaultIngressController(t *testing.T) { inputNetworkType: hyperv1.OVNKubernetes, inputPlatformType: hyperv1.KubevirtPlatform, disableMultiNetwork: false, + hasIPv6Network: true, ovnConfig: &hyperv1.OVNKubernetesConfig{ MTU: 1300, }, @@ -375,7 +390,10 @@ func TestReconcileDefaultIngressController(t *testing.T) { OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ GenevePort: &genevePort, V4InternalSubnet: v4InternalSubnet, - MTU: ptr.To(uint32(1300)), + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: v6InternalJoinSubnet, + }, + MTU: ptr.To(uint32(1300)), }, }, }, @@ -433,12 +451,162 @@ func TestReconcileDefaultIngressController(t *testing.T) { }, }, }, + { + name: "When IPv6 subnets configured for OVN Kubernetes it should propagate to network operator", + inputNetwork: NetworkOperator(), + inputNetworkType: hyperv1.OVNKubernetes, + inputPlatformType: hyperv1.AWSPlatform, + disableMultiNetwork: false, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + InternalTransitSwitchSubnet: "fd97:1::/64", + }, + }, + expectedNetwork: &operatorv1.Network{ + ObjectMeta: NetworkOperator().ObjectMeta, + Spec: operatorv1.NetworkSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: "Managed", + }, + DefaultNetwork: operatorv1.DefaultNetworkDefinition{ + OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: "fd99::/64", + InternalTransitSwitchSubnet: "fd97:1::/64", + }, + }, + }, + }, + }, + }, + { + name: "When OVN config has IPv4 and IPv6 subnets it should propagate both", + inputNetwork: NetworkOperator(), + inputNetworkType: hyperv1.OVNKubernetes, + inputPlatformType: hyperv1.AWSPlatform, + disableMultiNetwork: false, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv4: &hyperv1.OVNIPv4Config{ + InternalJoinSubnet: "192.168.1.0/24", + }, + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + }, + }, + expectedNetwork: &operatorv1.Network{ + ObjectMeta: NetworkOperator().ObjectMeta, + Spec: operatorv1.NetworkSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: "Managed", + }, + DefaultNetwork: operatorv1.DefaultNetworkDefinition{ + OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ + IPv4: &operatorv1.IPv4OVNKubernetesConfig{ + InternalJoinSubnet: "192.168.1.0/24", + }, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: "fd99::/64", + }, + }, + }, + }, + }, + }, + { + name: "When KubeVirt with OVNKubernetes and user-specified IPv6 join subnet it should not override", + inputNetwork: &operatorv1.Network{ + ObjectMeta: NetworkOperator().ObjectMeta, + Spec: operatorv1.NetworkSpec{ + DefaultNetwork: operatorv1.DefaultNetworkDefinition{ + OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: "fdaa::/64", + }, + }, + }, + }, + }, + inputNetworkType: hyperv1.OVNKubernetes, + inputPlatformType: hyperv1.KubevirtPlatform, + disableMultiNetwork: false, + hasIPv6Network: true, + expectedNetwork: &operatorv1.Network{ + ObjectMeta: NetworkOperator().ObjectMeta, + Spec: operatorv1.NetworkSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: "Managed", + }, + DefaultNetwork: operatorv1.DefaultNetworkDefinition{ + OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ + GenevePort: &genevePort, + V4InternalSubnet: v4InternalSubnet, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: "fdaa::/64", + }, + }, + }, + }, + }, + }, + { + name: "When KubeVirt with OVNKubernetes and user-specified IPv6 via ovnConfig it should override the KubeVirt default", + inputNetwork: NetworkOperator(), + inputNetworkType: hyperv1.OVNKubernetes, + inputPlatformType: hyperv1.KubevirtPlatform, + disableMultiNetwork: false, + hasIPv6Network: true, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fdbb::/64", + }, + }, + expectedNetwork: &operatorv1.Network{ + ObjectMeta: NetworkOperator().ObjectMeta, + Spec: operatorv1.NetworkSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: "Managed", + }, + DefaultNetwork: operatorv1.DefaultNetworkDefinition{ + OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ + GenevePort: &genevePort, + V4InternalSubnet: v4InternalSubnet, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: "fdbb::/64", + }, + }, + }, + }, + }, + }, + { + name: "When KubeVirt with OVNKubernetes and no IPv6 networks it should not set IPv6 join subnet default", + inputNetwork: NetworkOperator(), + inputNetworkType: hyperv1.OVNKubernetes, + inputPlatformType: hyperv1.KubevirtPlatform, + disableMultiNetwork: false, + hasIPv6Network: false, + expectedNetwork: &operatorv1.Network{ + ObjectMeta: NetworkOperator().ObjectMeta, + Spec: operatorv1.NetworkSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: "Managed", + }, + DefaultNetwork: operatorv1.DefaultNetworkDefinition{ + OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ + GenevePort: &genevePort, + V4InternalSubnet: v4InternalSubnet, + }, + }, + }, + }, + }, } for _, tc := range testsCases { t.Run(tc.name, func(t *testing.T) { g := NewGomegaWithT(t) - ReconcileNetworkOperator(tc.inputNetwork, tc.inputNetworkType, tc.inputPlatformType, tc.disableMultiNetwork, tc.ovnConfig) + ReconcileNetworkOperator(tc.inputNetwork, tc.inputNetworkType, tc.inputPlatformType, tc.disableMultiNetwork, tc.ovnConfig, tc.hasIPv6Network) g.Expect(tc.inputNetwork).To(BeEquivalentTo(tc.expectedNetwork)) }) } diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go index 1ee6a3a7180..b512d321833 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go @@ -830,7 +830,7 @@ func (r *reconciler) reconcileNetworkingAndSecrets(ctx context.Context, hcp *hyp ovnConfig = hcp.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig } if _, err := r.CreateOrUpdate(ctx, r.client, networkOperator, func() error { - networkoperator.ReconcileNetworkOperator(networkOperator, hcp.Spec.Networking.NetworkType, hcp.Spec.Platform.Type, netutil.IsDisableMultiNetwork(hcp), ovnConfig) + networkoperator.ReconcileNetworkOperator(networkOperator, hcp.Spec.Networking.NetworkType, hcp.Spec.Platform.Type, netutil.IsDisableMultiNetwork(hcp), ovnConfig, hasIPv6Network(hcp)) return nil }); err != nil { errs = append(errs, fmt.Errorf("failed to reconcile network operator: %w", err)) @@ -3642,6 +3642,25 @@ func (r *reconciler) reconcileAzureCloudNodeManager(ctx context.Context, image s return errs } +func hasIPv6Network(hcp *hyperv1.HostedControlPlane) bool { + for _, entry := range hcp.Spec.Networking.ClusterNetwork { + if net.IP(entry.CIDR.IP).To4() == nil { + return true + } + } + for _, entry := range hcp.Spec.Networking.ServiceNetwork { + if net.IP(entry.CIDR.IP).To4() == nil { + return true + } + } + for _, entry := range hcp.Spec.Networking.MachineNetwork { + if net.IP(entry.CIDR.IP).To4() == nil { + return true + } + } + return false +} + // imageRegistryPlatformWithPVC returns true if the platform requires a PVC for the image registry. func imageRegistryPlatformWithPVC(platform hyperv1.PlatformType) bool { switch platform { diff --git a/docs/content/reference/aggregated-docs.md b/docs/content/reference/aggregated-docs.md index 8b06fcd99af..e12ba9811c6 100644 --- a/docs/content/reference/aggregated-docs.md +++ b/docs/content/reference/aggregated-docs.md @@ -47841,6 +47841,73 @@ The value must be in proper IPV4 CIDR format

+###OVNIPv6Config { #hypershift.openshift.io/v1beta1.OVNIPv6Config } +

+(Appears on: +OVNKubernetesConfig) +

+

+

OVNIPv6Config contains IPv6-specific configuration options for OVN-Kubernetes. +https://github.com/openshift/api/blob/6d3c4e25a8d3aeb57ad61649d80c38cbd27d1cc8/operator/v1/types_network.go#L541-L570

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+internalTransitSwitchSubnet
+ +string + +
+(Optional) +

internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally +by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect +architecture that connects the cluster routers on each node together to enable +east west traffic. The subnet chosen should not overlap with other networks +specified for OVN-Kubernetes as well as other networks used on the host. +When omitted, this means no opinion and the platform is left to choose a reasonable +default which is subject to change over time. +The current default subnet is fd97::/64. +The subnet must be large enough to accommodate one IP per node in your cluster. +The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, +IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. +The prefix length must be in the range /0 to /125 inclusive. +This field is immutable once set.

+
+internalJoinSubnet
+ +string + +
+(Optional) +

internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the +default one is being already used by something else. It must not overlap with +any other subnet being used by OpenShift or by the node network. The size of the +subnet must be larger than the number of nodes. +The current default value is fd98::/64. +For KubeVirt hosted clusters, if this field is not set, HyperShift will +automatically use fd99::/64 to avoid collisions with the management cluster’s +default join subnet (fd98::/64). +The subnet must be large enough to accommodate one IP per node in your cluster. +The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, +IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. +The prefix length must be in the range /0 to /125 inclusive. +This field is immutable once set.

+
###OVNKubernetesConfig { #hypershift.openshift.io/v1beta1.OVNKubernetesConfig }

(Appears on: @@ -47876,6 +47943,25 @@ fields within ipv4 for details of default values.

+ipv6,omitzero
+ + +OVNIPv6Config + + + + +(Optional) +

ipv6 allows users to configure IP settings for IPv6 connections. When omitted, +this means no opinions and the default configuration is used. Check individual +fields within ipv6 for details of default values. +For KubeVirt hosted clusters using dual-stack networking, it is recommended to +set ipv6.internalJoinSubnet to a value different from the management cluster’s +join subnet (default fd98::/64) to avoid IPv6 routing conflicts.

+ + + + mtu
int32 diff --git a/docs/content/reference/api.md b/docs/content/reference/api.md index 81f244bc303..828e8531ff1 100644 --- a/docs/content/reference/api.md +++ b/docs/content/reference/api.md @@ -13630,6 +13630,73 @@ The value must be in proper IPV4 CIDR format

+###OVNIPv6Config { #hypershift.openshift.io/v1beta1.OVNIPv6Config } +

+(Appears on: +OVNKubernetesConfig) +

+

+

OVNIPv6Config contains IPv6-specific configuration options for OVN-Kubernetes. +https://github.com/openshift/api/blob/6d3c4e25a8d3aeb57ad61649d80c38cbd27d1cc8/operator/v1/types_network.go#L541-L570

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+internalTransitSwitchSubnet
+ +string + +
+(Optional) +

internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally +by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect +architecture that connects the cluster routers on each node together to enable +east west traffic. The subnet chosen should not overlap with other networks +specified for OVN-Kubernetes as well as other networks used on the host. +When omitted, this means no opinion and the platform is left to choose a reasonable +default which is subject to change over time. +The current default subnet is fd97::/64. +The subnet must be large enough to accommodate one IP per node in your cluster. +The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, +IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. +The prefix length must be in the range /0 to /125 inclusive. +This field is immutable once set.

+
+internalJoinSubnet
+ +string + +
+(Optional) +

internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the +default one is being already used by something else. It must not overlap with +any other subnet being used by OpenShift or by the node network. The size of the +subnet must be larger than the number of nodes. +The current default value is fd98::/64. +For KubeVirt hosted clusters, if this field is not set, HyperShift will +automatically use fd99::/64 to avoid collisions with the management cluster’s +default join subnet (fd98::/64). +The subnet must be large enough to accommodate one IP per node in your cluster. +The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, +IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. +The prefix length must be in the range /0 to /125 inclusive. +This field is immutable once set.

+
###OVNKubernetesConfig { #hypershift.openshift.io/v1beta1.OVNKubernetesConfig }

(Appears on: @@ -13665,6 +13732,25 @@ fields within ipv4 for details of default values.

+ipv6,omitzero
+ + +OVNIPv6Config + + + + +(Optional) +

ipv6 allows users to configure IP settings for IPv6 connections. When omitted, +this means no opinions and the default configuration is used. Check individual +fields within ipv6 for details of default values. +For KubeVirt hosted clusters using dual-stack networking, it is recommended to +set ipv6.internalJoinSubnet to a value different from the management cluster’s +join subnet (default fd98::/64) to avoid IPv6 routing conflicts.

+ + + + mtu
int32 diff --git a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go index bec35502b68..450507dd1ab 100644 --- a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go +++ b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go @@ -4336,6 +4336,50 @@ func validateSliceNetworkCIDRs(hc *hyperv1.HostedCluster) field.ErrorList { } } } + + if hc.Spec.Networking.NetworkType == hyperv1.OVNKubernetes { + var ipv4JoinSubnet string + if hc.Spec.OperatorConfiguration != nil && hc.Spec.OperatorConfiguration.ClusterNetworkOperator != nil && + hc.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig != nil && + hc.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig.IPv4 != nil { + ipv4JoinSubnet = hc.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig.IPv4.InternalJoinSubnet + } + // The reconciler defaults KubeVirt IPv4 internal subnet to avoid collision + // with the management cluster; include the effective value so overlaps are caught at admission time. + if ipv4JoinSubnet == "" && hc.Spec.Platform.Type == hyperv1.KubevirtPlatform { + _, cidr, err := net.ParseCIDR(hyperv1.KubevirtDefaultV4InternalSubnet) + if err == nil { + ce := cidrEntry{*cidr, *field.NewPath("spec", "operatorConfiguration", "clusterNetworkOperator", "ovnKubernetesConfig", "ipv4", "v4InternalSubnet (default)")} + cidrEntries = append(cidrEntries, ce) + } + } + + var ipv6JoinSubnet, ipv6TransitSubnet string + if hc.Spec.OperatorConfiguration != nil && hc.Spec.OperatorConfiguration.ClusterNetworkOperator != nil && + hc.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig != nil { + ipv6JoinSubnet = hc.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig.IPv6.InternalJoinSubnet + ipv6TransitSubnet = hc.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig.IPv6.InternalTransitSwitchSubnet + } + // The reconciler defaults KubeVirt IPv6 join subnet to avoid collision with the + // management cluster; include the effective value so overlaps are caught at admission time. + if ipv6JoinSubnet == "" && hc.Spec.Platform.Type == hyperv1.KubevirtPlatform { + ipv6JoinSubnet = hyperv1.KubevirtDefaultV6InternalJoinSubnet + } + if ipv6JoinSubnet != "" { + _, cidr, err := net.ParseCIDR(ipv6JoinSubnet) + if err == nil { + ce := cidrEntry{*cidr, *field.NewPath("spec", "operatorConfiguration", "clusterNetworkOperator", "ovnKubernetesConfig", "ipv6", "internalJoinSubnet")} + cidrEntries = append(cidrEntries, ce) + } + } + if ipv6TransitSubnet != "" { + _, cidr, err := net.ParseCIDR(ipv6TransitSubnet) + if err == nil { + ce := cidrEntry{*cidr, *field.NewPath("spec", "operatorConfiguration", "clusterNetworkOperator", "ovnKubernetesConfig", "ipv6", "internalTransitSwitchSubnet")} + cidrEntries = append(cidrEntries, ce) + } + } + } return compareCIDREntries(cidrEntries) } diff --git a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go index f289f3dd122..8c0a8b33f75 100644 --- a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go +++ b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go @@ -3918,13 +3918,14 @@ func TestComputeAWSEndpointServiceCondition(t *testing.T) { func TestValidateSliceNetworkCIDRs(t *testing.T) { t.Parallel() tests := []struct { - name string - mn []hyperv1.MachineNetworkEntry - cn []hyperv1.ClusterNetworkEntry - sn []hyperv1.ServiceNetworkEntry - networkType hyperv1.NetworkType - ovnConfig *hyperv1.OVNKubernetesConfig - wantErr bool + name string + mn []hyperv1.MachineNetworkEntry + cn []hyperv1.ClusterNetworkEntry + sn []hyperv1.ServiceNetworkEntry + networkType hyperv1.NetworkType + platformType hyperv1.PlatformType + ovnConfig *hyperv1.OVNKubernetesConfig + wantErr bool }{ { name: "given a conflicting IPv6 clusterNetwork overlapped with machineNetwork, it should fail", @@ -4069,6 +4070,143 @@ func TestValidateSliceNetworkCIDRs(t *testing.T) { }, wantErr: false, }, + { + name: "When OVN-Kubernetes with valid IPv6 InternalJoinSubnet it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd03::/112")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + }, + }, + wantErr: false, + }, + { + name: "When OVN-Kubernetes with valid IPv6 InternalTransitSwitchSubnet it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd03::/112")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalTransitSwitchSubnet: "fd97:1::/64", + }, + }, + wantErr: false, + }, + { + name: "When OVN-Kubernetes IPv6 InternalJoinSubnet overlaps with MachineNetwork it should fail", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd99::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd03::/112")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + }, + }, + wantErr: true, + }, + { + name: "When OVN-Kubernetes IPv6 subnets overlap with each other it should fail", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd03::/112")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + InternalTransitSwitchSubnet: "fd99::/48", + }, + }, + wantErr: true, + }, + { + name: "When OVN-Kubernetes with both valid IPv4 and IPv6 subnets it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("192.168.1.0/24")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("10.128.0.0/14")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("172.30.0.0/16")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv4: &hyperv1.OVNIPv4Config{ + InternalJoinSubnet: "100.64.0.0/16", + }, + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + }, + }, + wantErr: false, + }, + { + name: "When OVN-Kubernetes with empty IPv6 subnet strings it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("192.168.1.0/24")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("10.128.0.0/14")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("172.30.0.0/16")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "", + InternalTransitSwitchSubnet: "", + }, + }, + wantErr: false, + }, + { + name: "When KubeVirt OVN-Kubernetes with no IPv6 config and MachineNetwork overlaps default fd99::/64 it should fail", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd99::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/112")}}, + networkType: hyperv1.OVNKubernetes, + platformType: hyperv1.KubevirtPlatform, + ovnConfig: nil, + wantErr: true, + }, + { + name: "When KubeVirt OVN-Kubernetes with no IPv6 config and non-overlapping networks it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd03::/112")}}, + networkType: hyperv1.OVNKubernetes, + platformType: hyperv1.KubevirtPlatform, + ovnConfig: nil, + wantErr: false, + }, + { + name: "When KubeVirt OVN-Kubernetes with explicit IPv6 join subnet it should use explicit value not default", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd99::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/112")}}, + networkType: hyperv1.OVNKubernetes, + platformType: hyperv1.KubevirtPlatform, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fdaa::/64", + }, + }, + wantErr: false, + }, + { + name: "When KubeVirt OVN-Kubernetes with no IPv4 config and MachineNetwork overlaps default 100.66.0.0/16 it should fail", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("100.66.0.0/24")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("10.128.0.0/14")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("172.30.0.0/16")}}, + networkType: hyperv1.OVNKubernetes, + platformType: hyperv1.KubevirtPlatform, + ovnConfig: nil, + wantErr: true, + }, + { + name: "When KubeVirt OVN-Kubernetes with no IPv4 config and non-overlapping networks it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("192.168.1.0/24")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("10.128.0.0/14")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("172.30.0.0/16")}}, + networkType: hyperv1.OVNKubernetes, + platformType: hyperv1.KubevirtPlatform, + ovnConfig: nil, + wantErr: false, + }, } for _, tt := range tests { @@ -4079,6 +4217,9 @@ func TestValidateSliceNetworkCIDRs(t *testing.T) { Namespace: "any", }, Spec: hyperv1.HostedClusterSpec{ + Platform: hyperv1.PlatformSpec{ + Type: tt.platformType, + }, Networking: hyperv1.ClusterNetworking{ NetworkType: tt.networkType, MachineNetwork: tt.mn, @@ -4088,9 +4229,7 @@ func TestValidateSliceNetworkCIDRs(t *testing.T) { }, } - // Set OVN configuration if provided if tt.ovnConfig != nil { - //OperatorConfiguration hc.Spec.OperatorConfiguration = &hyperv1.OperatorConfiguration{ ClusterNetworkOperator: &hyperv1.ClusterNetworkOperatorSpec{ OVNKubernetesConfig: tt.ovnConfig, diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/operator.go b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/operator.go index ee74790f5ba..c14858d3fa1 100644 --- a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/operator.go +++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/operator.go @@ -4,6 +4,20 @@ import ( operatorv1 "github.com/openshift/api/operator/v1" ) +const ( + // KubevirtDefaultV6InternalJoinSubnet is the default IPv6 OVN join subnet + // for KubeVirt hosted clusters. The upstream OVN-Kubernetes default is fd98::/64, + // but KubeVirt guests use fd99::/64 to avoid collisions with the management + // cluster's join subnet when both run OVN-Kubernetes. + KubevirtDefaultV6InternalJoinSubnet = "fd99::/64" + + // KubevirtDefaultV4InternalSubnet is the default IPv4 OVN internal subnet + // for KubeVirt hosted clusters. The upstream OVN-Kubernetes default gateway + // router LRP CIDR is 100.64.0.0/16 and the default UDNs is 100.65.0.0/16. + // KubeVirt guests use 100.66.0.0/16 to avoid collisions with the management cluster. + KubevirtDefaultV4InternalSubnet = "100.66.0.0/16" +) + // +kubebuilder:validation:Enum="";Normal;Debug;Trace;TraceAll type LogLevel string @@ -38,6 +52,7 @@ type ClusterVersionOperatorSpec struct { OperatorLogLevel LogLevel `json:"operatorLogLevel,omitempty"` } +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.ovnKubernetesConfig) || has(self.ovnKubernetesConfig)", message="ovnKubernetesConfig is immutable once set and cannot be removed" type ClusterNetworkOperatorSpec struct { // disableMultiNetwork when set to true disables the Multus CNI plugin and related components // in the hosted cluster. This prevents the installation of multus daemon sets in the @@ -62,7 +77,11 @@ type ClusterNetworkOperatorSpec struct { // OVNKubernetesConfig contains OVN-Kubernetes specific configuration options. // https://github.com/openshift/api/blob/6d3c4e25a8d3aeb57ad61649d80c38cbd27d1cc8/operator/v1/types_network.go#L400-L471 // +kubebuilder:validation:XValidation:rule="!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet", message="internalJoinSubnet and internalTransitSwitchSubnet must not be the same" +// +kubebuilder:validation:XValidation:rule="!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet != self.ipv6.internalTransitSwitchSubnet", message="ipv6 internalJoinSubnet and internalTransitSwitchSubnet must not be the same" // +kubebuilder:validation:XValidation:rule="!has(oldSelf.mtu) || has(self.mtu)",message="mtu is immutable once set and cannot be removed" +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.ipv6) || has(self.ipv6)", message="ipv6 is immutable once set and cannot be removed" +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalJoinSubnet) || (has(self.ipv6) && has(self.ipv6.internalJoinSubnet))", message="ipv6.internalJoinSubnet cannot be removed once set" +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.ipv6) || !has(oldSelf.ipv6.internalTransitSwitchSubnet) || (has(self.ipv6) && has(self.ipv6.internalTransitSwitchSubnet))", message="ipv6.internalTransitSwitchSubnet cannot be removed once set" // +kubebuilder:validation:MinProperties=1 type OVNKubernetesConfig struct { // ipv4 allows users to configure IP settings for IPv4 connections. When omitted, @@ -71,6 +90,15 @@ type OVNKubernetesConfig struct { // +optional IPv4 *OVNIPv4Config `json:"ipv4,omitempty"` + // ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + // this means no opinions and the default configuration is used. Check individual + // fields within ipv6 for details of default values. + // For KubeVirt hosted clusters using dual-stack networking, it is recommended to + // set ipv6.internalJoinSubnet to a value different from the management cluster's + // join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + // +optional + IPv6 OVNIPv6Config `json:"ipv6,omitzero,omitempty"` + // mtu is the MTU to use for the tunnel interface on hosted cluster nodes. // This must be 100 bytes smaller than the uplink MTU. // When unset, the cluster-network-operator will determine the MTU automatically @@ -126,6 +154,52 @@ type OVNIPv4Config struct { InternalJoinSubnet string `json:"internalJoinSubnet,omitempty"` } +// OVNIPv6Config contains IPv6-specific configuration options for OVN-Kubernetes. +// https://github.com/openshift/api/blob/6d3c4e25a8d3aeb57ad61649d80c38cbd27d1cc8/operator/v1/types_network.go#L541-L570 +// +kubebuilder:validation:MinProperties=1 +type OVNIPv6Config struct { + // internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + // by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + // architecture that connects the cluster routers on each node together to enable + // east west traffic. The subnet chosen should not overlap with other networks + // specified for OVN-Kubernetes as well as other networks used on the host. + // When omitted, this means no opinion and the platform is left to choose a reasonable + // default which is subject to change over time. + // The current default subnet is fd97::/64. + // The subnet must be large enough to accommodate one IP per node in your cluster. + // The value must be a valid IPv6 CIDR (e.g. fd97::/64). IPv4 addresses, + // IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + // The prefix length must be in the range /0 to /125 inclusive. + // This field is immutable once set. + // +kubebuilder:validation:MaxLength=48 + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:XValidation:rule="isCIDR(self) && cidr(self).ip().family() == 6", message="Subnet must be in valid IPv6 CIDR format (e.g., fd97::/64)" + // +kubebuilder:validation:XValidation:rule="isCIDR(self) && cidr(self).prefixLength() <= 125", message="subnet must be in the range /0 to /125 inclusive" + // +kubebuilder:validation:XValidation:rule="self == oldSelf", message="internalTransitSwitchSubnet is immutable" + // +optional + InternalTransitSwitchSubnet string `json:"internalTransitSwitchSubnet,omitempty"` + // internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + // default one is being already used by something else. It must not overlap with + // any other subnet being used by OpenShift or by the node network. The size of the + // subnet must be larger than the number of nodes. + // The current default value is fd98::/64. + // For KubeVirt hosted clusters, if this field is not set, HyperShift will + // automatically use fd99::/64 to avoid collisions with the management cluster's + // default join subnet (fd98::/64). + // The subnet must be large enough to accommodate one IP per node in your cluster. + // The value must be a valid IPv6 CIDR (e.g. fd98::/64). IPv4 addresses, + // IPv4-mapped IPv6 addresses, and dual-stack addresses are not permitted. + // The prefix length must be in the range /0 to /125 inclusive. + // This field is immutable once set. + // +kubebuilder:validation:MaxLength=48 + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:XValidation:rule="isCIDR(self) && cidr(self).ip().family() == 6", message="Subnet must be in valid IPv6 CIDR format (e.g., fd98::/64)" + // +kubebuilder:validation:XValidation:rule="isCIDR(self) && cidr(self).prefixLength() <= 125", message="subnet must be in the range /0 to /125 inclusive" + // +kubebuilder:validation:XValidation:rule="self == oldSelf", message="internalJoinSubnet is immutable" + // +optional + InternalJoinSubnet string `json:"internalJoinSubnet,omitempty"` +} + // IngressOperatorSpec is the specification of the desired behavior of the Ingress Operator. type IngressOperatorSpec struct { // endpointPublishingStrategy is used to publish the default ingress controller endpoints. diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go index 5954bdd73ad..a3d882374d2 100644 --- a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go @@ -3818,6 +3818,21 @@ func (in *OVNIPv4Config) DeepCopy() *OVNIPv4Config { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OVNIPv6Config) DeepCopyInto(out *OVNIPv6Config) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OVNIPv6Config. +func (in *OVNIPv6Config) DeepCopy() *OVNIPv6Config { + if in == nil { + return nil + } + out := new(OVNIPv6Config) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = *in @@ -3826,6 +3841,7 @@ func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = new(OVNIPv4Config) **out = **in } + out.IPv6 = in.IPv6 } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OVNKubernetesConfig.