diff --git a/config/v1/tests/infrastructures.config.openshift.io/AAA_ungated.yaml b/config/v1/tests/infrastructures.config.openshift.io/AAA_ungated.yaml
index f5a31aab5f4..97dc8191f24 100644
--- a/config/v1/tests/infrastructures.config.openshift.io/AAA_ungated.yaml
+++ b/config/v1/tests/infrastructures.config.openshift.io/AAA_ungated.yaml
@@ -1735,6 +1735,7 @@ tests:
aws:
cloudLoadBalancerConfig:
dnsType: PlatformDefault
+ ipFamily: IPv4
region: us-east-1
resourceTags:
- key: key with space
@@ -1783,6 +1784,7 @@ tests:
aws:
cloudLoadBalancerConfig:
dnsType: PlatformDefault
+ ipFamily: IPv4
region: us-east-1
resourceTags:
- key: key:_./=+-@
diff --git a/config/v1/tests/infrastructures.config.openshift.io/AWSClusterHostedDNSInstall.yaml b/config/v1/tests/infrastructures.config.openshift.io/AWSClusterHostedDNSInstall.yaml
index 485c4c66eac..c89a82291eb 100644
--- a/config/v1/tests/infrastructures.config.openshift.io/AWSClusterHostedDNSInstall.yaml
+++ b/config/v1/tests/infrastructures.config.openshift.io/AWSClusterHostedDNSInstall.yaml
@@ -3,7 +3,6 @@ name: "Infrastructure"
crdName: infrastructures.config.openshift.io
featureGates:
- AWSClusterHostedDNSInstall
-- -AWSDualStackInstall
tests:
onCreate:
- name: Should be able to create a minimal Infrastructure
@@ -61,6 +60,7 @@ tests:
aws:
cloudLoadBalancerConfig:
dnsType: PlatformDefault
+ ipFamily: IPv4
type: AWS
- name: should be able to set dnsType to non-default value of `ClusterHosted`
initial: |
@@ -102,6 +102,7 @@ tests:
aws:
cloudLoadBalancerConfig:
dnsType: ClusterHosted
+ ipFamily: IPv4
type: AWS
- name: Should not allow changing the immutable dnsType field
initial: |
@@ -138,6 +139,7 @@ tests:
aws:
cloudLoadBalancerConfig:
dnsType: PlatformDefault
+ ipFamily: IPv4
type: AWS
expectedStatusError: "status.platformStatus.aws.cloudLoadBalancerConfig.dnsType: Invalid value: \"string\": dnsType is immutable"
- name: Should not accept non-IP address values for Load Balancer IPs
@@ -214,6 +216,7 @@ tests:
clusterHosted:
apiIntLoadBalancerIPs:
- 10.10.10.20
+ ipFamily: IPv4
type: AWS
expectedStatusError: "status.platformStatus.aws.cloudLoadBalancerConfig: Invalid value: \"object\": clusterHosted is permitted only when dnsType is ClusterHosted"
- name: Should not accept duplicate IP addresses for any of the Load Balancer IPs
diff --git a/config/v1/tests/infrastructures.config.openshift.io/AWSDualStackInstall.yaml b/config/v1/tests/infrastructures.config.openshift.io/AWSDualStackInstall.yaml
index 7752610223c..846d65892d7 100644
--- a/config/v1/tests/infrastructures.config.openshift.io/AWSDualStackInstall.yaml
+++ b/config/v1/tests/infrastructures.config.openshift.io/AWSDualStackInstall.yaml
@@ -87,6 +87,8 @@ tests:
platformStatus:
aws:
region: us-east-1
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
ipFamily: DualStackIPv6Primary
type: AWS
expected: |
@@ -130,6 +132,8 @@ tests:
platformStatus:
aws:
region: us-east-1
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
ipFamily: DualStackIPv4Primary
type: AWS
expected: |
@@ -191,6 +195,8 @@ tests:
platformStatus:
aws:
region: us-east-1
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
ipFamily: IPv4
type: AWS
updated: |
@@ -207,6 +213,8 @@ tests:
platformStatus:
aws:
region: us-east-1
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
ipFamily: DualStackIPv6Primary
type: AWS
expectedStatusError: "status.platformStatus.aws.ipFamily: Invalid value: \"string\": ipFamily is immutable once set"
@@ -224,6 +232,8 @@ tests:
platform: AWS
platformStatus:
aws:
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
region: us-east-1
ipFamily: DualStackIPv6Primary
type: AWS
@@ -240,6 +250,8 @@ tests:
platform: AWS
platformStatus:
aws:
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
region: us-east-1
ipFamily: DualStackIPv6Primary
type: AWS
@@ -277,6 +289,8 @@ tests:
platformStatus:
aws:
region: us-east-1
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
ipFamily: DualStackIPv4Primary
type: AWS
updated: |
diff --git a/config/v1/types_infrastructure.go b/config/v1/types_infrastructure.go
index 5d9f10374eb..68e3209d807 100644
--- a/config/v1/types_infrastructure.go
+++ b/config/v1/types_infrastructure.go
@@ -586,6 +586,15 @@ type AWSPlatformStatus struct {
// IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
// protocol family.
//
+ // Valid values are:
+ // * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ // * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ // * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+ //
+ // When omitted, this field defaults to "IPv4".
+ //
+ // This field is immutable and cannot be changed once set.
+ //
// +default="IPv4"
// +kubebuilder:default="IPv4"
// +kubebuilder:validation:XValidation:rule="oldSelf == '' || self == oldSelf",message="ipFamily is immutable once set"
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Default.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Default.crd.yaml
index 0305366dfd1..15b6bd7cc39 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Default.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Default.crd.yaml
@@ -1287,6 +1287,30 @@ spec:
ClusterHosted
rule: 'has(self.dnsType) && self.dnsType != ''ClusterHosted''
? !has(self.clusterHosted) : true'
+ ipFamily:
+ default: IPv4
+ description: |-
+ ipFamily specifies the IP protocol family that should be used for AWS
+ network resources. This controls whether AWS resources are created with
+ IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
+ protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
+ enum:
+ - IPv4
+ - DualStackIPv6Primary
+ - DualStackIPv4Primary
+ type: string
+ x-kubernetes-validations:
+ - message: ipFamily is immutable once set
+ rule: oldSelf == '' || self == oldSelf
region:
description: region holds the default AWS region for new AWS
resources created by the cluster.
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml
index 2829b41dce9..56840a9fcd9 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml
@@ -1380,6 +1380,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml
index a3064161f2e..33e654be218 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml
@@ -1365,6 +1365,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml
index cafc698a8ac..1b344019edb 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml
@@ -1365,6 +1365,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-OKD.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-OKD.crd.yaml
index 6cdb3f76af3..4eb30d34f55 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-OKD.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-OKD.crd.yaml
@@ -1287,6 +1287,30 @@ spec:
ClusterHosted
rule: 'has(self.dnsType) && self.dnsType != ''ClusterHosted''
? !has(self.clusterHosted) : true'
+ ipFamily:
+ default: IPv4
+ description: |-
+ ipFamily specifies the IP protocol family that should be used for AWS
+ network resources. This controls whether AWS resources are created with
+ IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
+ protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
+ enum:
+ - IPv4
+ - DualStackIPv6Primary
+ - DualStackIPv4Primary
+ type: string
+ x-kubernetes-validations:
+ - message: ipFamily is immutable once set
+ rule: oldSelf == '' || self == oldSelf
region:
description: region holds the default AWS region for new AWS
resources created by the cluster.
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml
index 310ba4ad386..dc47d947825 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml
@@ -1380,6 +1380,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
index f3b307973b9..e87adbbca96 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
@@ -1380,6 +1380,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
index 998b9be396a..8a1c908b845 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
@@ -1365,6 +1365,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/config/v1/zz_generated.featuregated-crd-manifests/infrastructures.config.openshift.io/AWSDualStackInstall.yaml b/config/v1/zz_generated.featuregated-crd-manifests/infrastructures.config.openshift.io/AWSDualStackInstall.yaml
index 1b1fe5d1d5a..72e9126ac49 100644
--- a/config/v1/zz_generated.featuregated-crd-manifests/infrastructures.config.openshift.io/AWSDualStackInstall.yaml
+++ b/config/v1/zz_generated.featuregated-crd-manifests/infrastructures.config.openshift.io/AWSDualStackInstall.yaml
@@ -1155,6 +1155,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/config/v1/zz_generated.swagger_doc_generated.go b/config/v1/zz_generated.swagger_doc_generated.go
index 631f11a1b29..b7b7ea80186 100644
--- a/config/v1/zz_generated.swagger_doc_generated.go
+++ b/config/v1/zz_generated.swagger_doc_generated.go
@@ -1581,7 +1581,7 @@ var map_AWSPlatformStatus = map[string]string{
"serviceEndpoints": "serviceEndpoints list contains custom endpoints which will override default service endpoint of AWS Services. There must be only one ServiceEndpoint for a service.",
"resourceTags": "resourceTags is a list of additional tags to apply to AWS resources created for the cluster. See https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for information on tagging AWS resources. AWS supports a maximum of 50 tags per resource. OpenShift reserves 25 tags for its use, leaving 25 tags available for the user.",
"cloudLoadBalancerConfig": "cloudLoadBalancerConfig holds configuration related to DNS and cloud load balancers. It allows configuration of in-cluster DNS as an alternative to the platform default DNS implementation. When using the ClusterHosted DNS type, Load Balancer IP addresses must be provided for the API and internal API load balancers as well as the ingress load balancer.",
- "ipFamily": "ipFamily specifies the IP protocol family that should be used for AWS network resources. This controls whether AWS resources are created with IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary protocol family.",
+ "ipFamily": "ipFamily specifies the IP protocol family that should be used for AWS network resources. This controls whether AWS resources are created with IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary protocol family.\n\nValid values are: * \"IPv4\" (default): Cloud platform resources use IPv4 addressing only. * \"DualStackIPv6Primary\": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family. * \"DualStackIPv4Primary\": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.\n\nWhen omitted, this field defaults to \"IPv4\".\n\nThis field is immutable and cannot be changed once set.",
}
func (AWSPlatformStatus) SwaggerDoc() map[string]string {
diff --git a/features.md b/features.md
index c78d402696a..f09bc5e8c17 100644
--- a/features.md
+++ b/features.md
@@ -30,7 +30,6 @@
| ProvisioningRequestAvailable| | | Enabled | Enabled | | | | |
| AWSClusterHostedDNS| | | Enabled | Enabled | | | Enabled | Enabled |
| AWSDedicatedHosts| | | Enabled | Enabled | | | Enabled | Enabled |
-| AWSDualStackInstall| | | Enabled | Enabled | | | Enabled | Enabled |
| AWSEuropeanSovereignCloudInstall| | | Enabled | Enabled | | | Enabled | Enabled |
| AdditionalStorageConfig| | | Enabled | Enabled | | | Enabled | Enabled |
| AutomatedEtcdBackup| | | Enabled | Enabled | | | Enabled | Enabled |
@@ -96,6 +95,7 @@
| VolumeGroupSnapshot| | | Enabled | Enabled | | | Enabled | Enabled |
| OSStreams| | Enabled | Enabled | Enabled | | Enabled | Enabled | Enabled |
| AWSClusterHostedDNSInstall| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
+| AWSDualStackInstall| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| AWSServiceLBNetworkSecurityGroup| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| AzureWorkloadIdentity| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| BootImageSkewEnforcement| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
diff --git a/features/features.go b/features/features.go
index b45bef77056..f70a1e5437b 100644
--- a/features/features.go
+++ b/features/features.go
@@ -869,7 +869,7 @@ var (
contactPerson("sadasu").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1806").
- enable(inTechPreviewNoUpgrade(), inDevPreviewNoUpgrade()).
+ enable(inDefault(), inOKD(), inTechPreviewNoUpgrade(), inDevPreviewNoUpgrade()).
mustRegister()
FeatureGateAzureDualStackInstall = newFeatureGate("AzureDualStackInstall").
diff --git a/machineconfiguration/v1/tests/controllerconfigs.machineconfiguration.openshift.io/AWSDualStackInstall.yaml b/machineconfiguration/v1/tests/controllerconfigs.machineconfiguration.openshift.io/AWSDualStackInstall.yaml
index 35edae5c3ae..57fa9d7c4dc 100644
--- a/machineconfiguration/v1/tests/controllerconfigs.machineconfiguration.openshift.io/AWSDualStackInstall.yaml
+++ b/machineconfiguration/v1/tests/controllerconfigs.machineconfiguration.openshift.io/AWSDualStackInstall.yaml
@@ -91,10 +91,10 @@ tests:
platformStatus:
type: AWS
aws:
- region: us-east-1
- ipFamily: IPv4
cloudLoadBalancerConfig:
dnsType: PlatformDefault
+ region: us-east-1
+ ipFamily: IPv4
ipFamilies: IPv4
kubeAPIServerServingCAData: Y2VydGlmaWNhdGUK
network: null
@@ -172,6 +172,8 @@ tests:
platformStatus:
type: AWS
aws:
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
region: us-east-1
ipFamily: DualStackIPv6Primary
ipFamilies: IPv4
@@ -217,10 +219,10 @@ tests:
platformStatus:
type: AWS
aws:
- region: us-east-1
- ipFamily: DualStackIPv6Primary
cloudLoadBalancerConfig:
dnsType: PlatformDefault
+ region: us-east-1
+ ipFamily: DualStackIPv6Primary
ipFamilies: IPv4
kubeAPIServerServingCAData: Y2VydGlmaWNhdGUK
network: null
@@ -262,6 +264,8 @@ tests:
platformStatus:
type: AWS
aws:
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
region: us-east-1
ipFamily: IPv4
ipFamilies: IPv4
@@ -304,6 +308,8 @@ tests:
platformStatus:
type: AWS
aws:
+ cloudLoadBalancerConfig:
+ dnsType: PlatformDefault
region: us-east-1
ipFamily: DualStackIPv6Primary
ipFamilies: IPv4
diff --git a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Default.crd.yaml b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Default.crd.yaml
index 7c0f73b0413..633ccb976db 100644
--- a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Default.crd.yaml
+++ b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Default.crd.yaml
@@ -1578,6 +1578,30 @@ spec:
is ClusterHosted
rule: 'has(self.dnsType) && self.dnsType != ''ClusterHosted''
? !has(self.clusterHosted) : true'
+ ipFamily:
+ default: IPv4
+ description: |-
+ ipFamily specifies the IP protocol family that should be used for AWS
+ network resources. This controls whether AWS resources are created with
+ IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
+ protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
+ enum:
+ - IPv4
+ - DualStackIPv6Primary
+ - DualStackIPv4Primary
+ type: string
+ x-kubernetes-validations:
+ - message: ipFamily is immutable once set
+ rule: oldSelf == '' || self == oldSelf
region:
description: region holds the default AWS region for
new AWS resources created by the cluster.
diff --git a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml
index 9fd305414c5..43ccde322c0 100644
--- a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml
+++ b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml
@@ -1674,6 +1674,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml
index 4717d10021a..d217d920b0b 100644
--- a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml
+++ b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml
@@ -1659,6 +1659,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml
index f176deea6ef..a426a59445d 100644
--- a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml
+++ b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml
@@ -1659,6 +1659,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-OKD.crd.yaml b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-OKD.crd.yaml
index baa96854daa..f86ca02f7b2 100644
--- a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-OKD.crd.yaml
+++ b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-OKD.crd.yaml
@@ -1578,6 +1578,30 @@ spec:
is ClusterHosted
rule: 'has(self.dnsType) && self.dnsType != ''ClusterHosted''
? !has(self.clusterHosted) : true'
+ ipFamily:
+ default: IPv4
+ description: |-
+ ipFamily specifies the IP protocol family that should be used for AWS
+ network resources. This controls whether AWS resources are created with
+ IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
+ protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
+ enum:
+ - IPv4
+ - DualStackIPv6Primary
+ - DualStackIPv4Primary
+ type: string
+ x-kubernetes-validations:
+ - message: ipFamily is immutable once set
+ rule: oldSelf == '' || self == oldSelf
region:
description: region holds the default AWS region for
new AWS resources created by the cluster.
diff --git a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml
index de2a65dfa33..23ce8df23b4 100644
--- a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml
+++ b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml
@@ -1674,6 +1674,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
index 7bf1e60dfa5..97aa78f4c4c 100644
--- a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
+++ b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
@@ -1674,6 +1674,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
index 51b3d3ceca1..3176362d6b4 100644
--- a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
+++ b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
@@ -1659,6 +1659,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/machineconfiguration/v1/zz_generated.featuregated-crd-manifests/controllerconfigs.machineconfiguration.openshift.io/AWSDualStackInstall.yaml b/machineconfiguration/v1/zz_generated.featuregated-crd-manifests/controllerconfigs.machineconfiguration.openshift.io/AWSDualStackInstall.yaml
index ee5edcb5edb..573c8281c50 100644
--- a/machineconfiguration/v1/zz_generated.featuregated-crd-manifests/controllerconfigs.machineconfiguration.openshift.io/AWSDualStackInstall.yaml
+++ b/machineconfiguration/v1/zz_generated.featuregated-crd-manifests/controllerconfigs.machineconfiguration.openshift.io/AWSDualStackInstall.yaml
@@ -1451,6 +1451,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go
index 9f78f6c321f..7b08008fc5b 100644
--- a/openapi/generated_openapi/zz_generated.openapi.go
+++ b/openapi/generated_openapi/zz_generated.openapi.go
@@ -9427,7 +9427,7 @@ func schema_openshift_api_config_v1_AWSPlatformStatus(ref common.ReferenceCallba
},
"ipFamily": {
SchemaProps: spec.SchemaProps{
- Description: "ipFamily specifies the IP protocol family that should be used for AWS network resources. This controls whether AWS resources are created with IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary protocol family.",
+ Description: "ipFamily specifies the IP protocol family that should be used for AWS network resources. This controls whether AWS resources are created with IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary protocol family.\n\nValid values are: * \"IPv4\" (default): Cloud platform resources use IPv4 addressing only. * \"DualStackIPv6Primary\": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family. * \"DualStackIPv4Primary\": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.\n\nWhen omitted, this field defaults to \"IPv4\".\n\nThis field is immutable and cannot be changed once set.",
Default: "IPv4",
Type: []string{"string"},
Format: "",
diff --git a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Default.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Default.crd.yaml
index 0305366dfd1..15b6bd7cc39 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Default.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Default.crd.yaml
@@ -1287,6 +1287,30 @@ spec:
ClusterHosted
rule: 'has(self.dnsType) && self.dnsType != ''ClusterHosted''
? !has(self.clusterHosted) : true'
+ ipFamily:
+ default: IPv4
+ description: |-
+ ipFamily specifies the IP protocol family that should be used for AWS
+ network resources. This controls whether AWS resources are created with
+ IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
+ protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
+ enum:
+ - IPv4
+ - DualStackIPv6Primary
+ - DualStackIPv4Primary
+ type: string
+ x-kubernetes-validations:
+ - message: ipFamily is immutable once set
+ rule: oldSelf == '' || self == oldSelf
region:
description: region holds the default AWS region for new AWS
resources created by the cluster.
diff --git a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml
index 2829b41dce9..56840a9fcd9 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-CustomNoUpgrade.crd.yaml
@@ -1380,6 +1380,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml
index a3064161f2e..33e654be218 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-DevPreviewNoUpgrade.crd.yaml
@@ -1365,6 +1365,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml
index cafc698a8ac..1b344019edb 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-Hypershift-TechPreviewNoUpgrade.crd.yaml
@@ -1365,6 +1365,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-OKD.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-OKD.crd.yaml
index 6cdb3f76af3..4eb30d34f55 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-OKD.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-OKD.crd.yaml
@@ -1287,6 +1287,30 @@ spec:
ClusterHosted
rule: 'has(self.dnsType) && self.dnsType != ''ClusterHosted''
? !has(self.clusterHosted) : true'
+ ipFamily:
+ default: IPv4
+ description: |-
+ ipFamily specifies the IP protocol family that should be used for AWS
+ network resources. This controls whether AWS resources are created with
+ IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
+ protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
+ enum:
+ - IPv4
+ - DualStackIPv6Primary
+ - DualStackIPv4Primary
+ type: string
+ x-kubernetes-validations:
+ - message: ipFamily is immutable once set
+ rule: oldSelf == '' || self == oldSelf
region:
description: region holds the default AWS region for new AWS
resources created by the cluster.
diff --git a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml
index 310ba4ad386..dc47d947825 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-CustomNoUpgrade.crd.yaml
@@ -1380,6 +1380,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
index f3b307973b9..e87adbbca96 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
@@ -1380,6 +1380,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
index 998b9be396a..8a1c908b845 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_infrastructures-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
@@ -1365,6 +1365,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Default.crd.yaml b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Default.crd.yaml
index 7c0f73b0413..633ccb976db 100644
--- a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Default.crd.yaml
+++ b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Default.crd.yaml
@@ -1578,6 +1578,30 @@ spec:
is ClusterHosted
rule: 'has(self.dnsType) && self.dnsType != ''ClusterHosted''
? !has(self.clusterHosted) : true'
+ ipFamily:
+ default: IPv4
+ description: |-
+ ipFamily specifies the IP protocol family that should be used for AWS
+ network resources. This controls whether AWS resources are created with
+ IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
+ protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
+ enum:
+ - IPv4
+ - DualStackIPv6Primary
+ - DualStackIPv4Primary
+ type: string
+ x-kubernetes-validations:
+ - message: ipFamily is immutable once set
+ rule: oldSelf == '' || self == oldSelf
region:
description: region holds the default AWS region for
new AWS resources created by the cluster.
diff --git a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml
index 9fd305414c5..43ccde322c0 100644
--- a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-CustomNoUpgrade.crd.yaml
@@ -1674,6 +1674,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml
index 4717d10021a..d217d920b0b 100644
--- a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-DevPreviewNoUpgrade.crd.yaml
@@ -1659,6 +1659,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml
index f176deea6ef..a426a59445d 100644
--- a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-Hypershift-TechPreviewNoUpgrade.crd.yaml
@@ -1659,6 +1659,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-OKD.crd.yaml b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-OKD.crd.yaml
index baa96854daa..f86ca02f7b2 100644
--- a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-OKD.crd.yaml
+++ b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-OKD.crd.yaml
@@ -1578,6 +1578,30 @@ spec:
is ClusterHosted
rule: 'has(self.dnsType) && self.dnsType != ''ClusterHosted''
? !has(self.clusterHosted) : true'
+ ipFamily:
+ default: IPv4
+ description: |-
+ ipFamily specifies the IP protocol family that should be used for AWS
+ network resources. This controls whether AWS resources are created with
+ IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
+ protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
+ enum:
+ - IPv4
+ - DualStackIPv6Primary
+ - DualStackIPv4Primary
+ type: string
+ x-kubernetes-validations:
+ - message: ipFamily is immutable once set
+ rule: oldSelf == '' || self == oldSelf
region:
description: region holds the default AWS region for
new AWS resources created by the cluster.
diff --git a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml
index de2a65dfa33..23ce8df23b4 100644
--- a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-CustomNoUpgrade.crd.yaml
@@ -1674,6 +1674,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
index 7bf1e60dfa5..97aa78f4c4c 100644
--- a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
@@ -1674,6 +1674,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
index 51b3d3ceca1..3176362d6b4 100644
--- a/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_80_machine-config_01_controllerconfigs-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
@@ -1659,6 +1659,15 @@ spec:
network resources. This controls whether AWS resources are created with
IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary
protocol family.
+
+ Valid values are:
+ * "IPv4" (default): Cloud platform resources use IPv4 addressing only.
+ * "DualStackIPv6Primary": Cloud platform resources use dual-stack networking with IPv6 as the primary protocol family.
+ * "DualStackIPv4Primary": Cloud platform resources use dual-stack networking with IPv4 as the primary protocol family.
+
+ When omitted, this field defaults to "IPv4".
+
+ This field is immutable and cannot be changed once set.
enum:
- IPv4
- DualStackIPv6Primary
diff --git a/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml b/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml
index 2873fff0258..0a8bca6af16 100644
--- a/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml
@@ -20,9 +20,6 @@
{
"name": "AWSDedicatedHosts"
},
- {
- "name": "AWSDualStackInstall"
- },
{
"name": "AWSEuropeanSovereignCloudInstall"
},
@@ -301,6 +298,9 @@
{
"name": "AWSClusterHostedDNSInstall"
},
+ {
+ "name": "AWSDualStackInstall"
+ },
{
"name": "AWSServiceLBNetworkSecurityGroup"
},
diff --git a/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml b/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml
index ee9d301c7c5..977b1e4a0ce 100644
--- a/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml
@@ -22,9 +22,6 @@
{
"name": "AWSDedicatedHosts"
},
- {
- "name": "AWSDualStackInstall"
- },
{
"name": "AWSEuropeanSovereignCloudInstall"
},
@@ -303,6 +300,9 @@
{
"name": "AWSClusterHostedDNSInstall"
},
+ {
+ "name": "AWSDualStackInstall"
+ },
{
"name": "AWSServiceLBNetworkSecurityGroup"
},
diff --git a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
index d3ec99985fc..d671992dae4 100644
--- a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
@@ -20,9 +20,6 @@
{
"name": "AWSDedicatedHosts"
},
- {
- "name": "AWSDualStackInstall"
- },
{
"name": "AWSEuropeanSovereignCloudInstall"
},
@@ -295,6 +292,9 @@
{
"name": "AWSClusterHostedDNSInstall"
},
+ {
+ "name": "AWSDualStackInstall"
+ },
{
"name": "AWSServiceLBNetworkSecurityGroup"
},
diff --git a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
index 326fe926316..e85a3f29dd9 100644
--- a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
@@ -22,9 +22,6 @@
{
"name": "AWSDedicatedHosts"
},
- {
- "name": "AWSDualStackInstall"
- },
{
"name": "AWSEuropeanSovereignCloudInstall"
},
@@ -297,6 +294,9 @@
{
"name": "AWSClusterHostedDNSInstall"
},
+ {
+ "name": "AWSDualStackInstall"
+ },
{
"name": "AWSServiceLBNetworkSecurityGroup"
},
diff --git a/tools/codegen/cmd/featuregate-test-analyzer.go b/tools/codegen/cmd/featuregate-test-analyzer.go
index 9eda83a226b..f2f9919043e 100644
--- a/tools/codegen/cmd/featuregate-test-analyzer.go
+++ b/tools/codegen/cmd/featuregate-test-analyzer.go
@@ -35,6 +35,9 @@ const (
// required pass rate.
// nearly all current tests pass 99% of the time, but in a two week window we lack enough data to say.
requiredPassRateOfTestsPerVariant = 0.95
+
+ // required pass rate for "install should succeed" test
+ requiredPassRateForInstallTest = 1.0
)
type FeatureGateTestAnalyzerOptions struct {
@@ -181,26 +184,67 @@ func (o *FeatureGateTestAnalyzerOptions) Run(ctx context.Context) error {
clusterProfiles := recentlyEnabledFeatureGatesToClusterProfiles[enabledFeatureGate]
md.Title(1, enabledFeatureGate)
- testingResults, err := listTestResultFor(enabledFeatureGate, clusterProfiles)
+ testingResults, installTestLevelData, err := listTestResultFor(enabledFeatureGate, clusterProfiles)
if err != nil {
return err
}
writeTestingMarkDown(testingResults, md)
- validationResults := checkIfTestingIsSufficient(enabledFeatureGate, testingResults)
+ validationResults := checkIfTestingIsSufficient(enabledFeatureGate, testingResults, installTestLevelData)
- // Separate warnings from blocking errors
+ // Separate warnings and blocking errors
blockingErrors := []error{}
warnings := []error{}
+ var blockingResults, warningResults []ValidationResult
for _, vr := range validationResults {
if vr.IsWarning {
warnings = append(warnings, vr.Error)
+ warningResults = append(warningResults, vr)
} else {
blockingErrors = append(blockingErrors, vr.Error)
+ blockingResults = append(blockingResults, vr)
}
}
+ // For Install feature gates, report "install should succeed: overall" test statistics first
+ if strings.Contains(enabledFeatureGate, "Install") {
+ md.Text("")
+ fmt.Fprintf(o.Out, "\n")
+ md.Textf("**Install test statistics for \"install should succeed: overall\":**\n")
+ fmt.Fprintf(o.Out, "Install test statistics for \"install should succeed: overall\":\n")
+ jobVariants := make([]JobVariant, 0, len(testingResults))
+ for jobVariant := range testingResults {
+ jobVariants = append(jobVariants, jobVariant)
+ }
+ sort.Slice(jobVariants, func(i, j int) bool {
+ return jobVariants[i].String() < jobVariants[j].String()
+ })
+ prevCloud := ""
+ for _, jobVariant := range jobVariants {
+ if prevCloud != "" && jobVariant.Cloud != prevCloud {
+ md.Text("")
+ fmt.Fprintf(o.Out, "\n")
+ }
+ prevCloud = jobVariant.Cloud
+ installTest := installTestLevelData[jobVariant]
+ if installTest == nil {
+ md.Textf(" - %v: test not found\n", jobVariant)
+ fmt.Fprintf(o.Out, " %v: test not found\n", jobVariant)
+ } else if installTest.TotalRuns > 0 {
+ passPercent := float32(installTest.SuccessfulRuns) / float32(installTest.TotalRuns)
+ displayActual := int(passPercent * 100)
+ md.Textf(" - %v: passed %d%% (%d/%d runs)\n", jobVariant, displayActual, installTest.SuccessfulRuns, installTest.TotalRuns)
+ fmt.Fprintf(o.Out, " %v: passed %d%% (%d/%d runs)\n", jobVariant, displayActual, installTest.SuccessfulRuns, installTest.TotalRuns)
+ } else {
+ md.Textf(" - %v: 0 runs\n", jobVariant)
+ fmt.Fprintf(o.Out, " %v: 0 runs\n", jobVariant)
+ }
+ }
+ md.Text("")
+ fmt.Fprintf(o.Out, "\n")
+ }
+
if len(validationResults) == 0 {
md.Textf("Sufficient CI testing for %q.\n", enabledFeatureGate)
fmt.Fprintf(o.Out, "Sufficient CI testing for %q.\n", enabledFeatureGate)
@@ -208,38 +252,41 @@ func (o *FeatureGateTestAnalyzerOptions) Run(ctx context.Context) error {
if len(blockingErrors) > 0 {
md.Textf("INSUFFICIENT CI testing for %q.\n", enabledFeatureGate)
fmt.Fprintf(o.Out, "INSUFFICIENT CI testing for %q.\n", enabledFeatureGate)
- } else {
+ } else if len(warnings) > 0 {
md.Textf("CI testing issues found for %q (non-blocking warnings).\n", enabledFeatureGate)
fmt.Fprintf(o.Out, "CI testing issues found for %q (non-blocking warnings).\n", enabledFeatureGate)
+ } else {
+ md.Textf("Sufficient CI testing for %q.\n", enabledFeatureGate)
+ fmt.Fprintf(o.Out, "Sufficient CI testing for %q.\n", enabledFeatureGate)
}
- md.Textf("* At least five tests are expected for a feature\n")
- md.Textf("* Tests must be be run on every TechPreview platform (ask for an exception if your feature doesn't support a variant)")
- md.Textf("* All tests must run at least 14 times on every platform")
- md.Textf("* All tests must pass at least 95%% of the time")
- md.Textf("* JobTier must be one of: standard, informing, blocking, candidate (candidate is allowed but produces a warning as it is not covered by Component Readiness)\n")
- md.Text("")
+ if len(blockingErrors) > 0 || len(warnings) > 0 {
+ md.Textf("* At least five tests are expected for a feature\n")
+ md.Textf("* Tests must be be run on every TechPreview platform (ask for an exception if your feature doesn't support a variant)")
+ md.Textf("* All tests must run at least 14 times on every platform")
+ md.Textf("* All tests must pass at least 95%% of the time")
+ md.Textf("* For Install feature gates, the \"install should succeed: overall\" test must pass at least 100%% of the time")
+ md.Textf("* JobTier must be one of: standard, informing, blocking, candidate (candidate is allowed but produces a warning as it is not covered by Component Readiness)\n")
+ md.Text("")
+ }
if len(warnings) > 0 {
md.Textf("**Non-blocking warnings (optional variants):**\n")
- for _, warn := range warnings {
- md.Textf(" - %s\n", warn.Error())
- }
+ writeGroupedValidationResults(warningResults, md)
md.Text("")
}
if len(blockingErrors) > 0 {
md.Textf("**Blocking errors:**\n")
- for _, err := range blockingErrors {
- md.Textf(" - %s\n", err.Error())
- }
+ writeGroupedValidationResults(blockingResults, md)
md.Text("")
}
md.Text("")
}
- // Only add blocking errors to the error list (warnings don't fail the job)
- errs = append(errs, blockingErrors...)
+ if len(blockingErrors) > 0 {
+ errs = append(errs, blockingErrors...)
+ }
featureGateHTMLData = append(featureGateHTMLData, buildHTMLFeatureGateData(enabledFeatureGate, testingResults, blockingErrors, release))
}
@@ -257,7 +304,10 @@ func (o *FeatureGateTestAnalyzerOptions) Run(ctx context.Context) error {
}
}
- return errors.Join(errs...)
+ if len(errs) > 0 {
+ return fmt.Errorf("feature gate promotion validation errors:\n%w", errors.Join(errs...))
+ }
+ return nil
}
func topologyDisplayName(topology string) string {
@@ -365,7 +415,7 @@ func writeHTMLFromTemplate(filename string, featureGateHTMLData []utils.HTMLFeat
return nil
}
-func checkIfTestingIsSufficient(featureGate string, testingResults map[JobVariant]*TestingResults) []ValidationResult {
+func checkIfTestingIsSufficient(featureGate string, testingResults map[JobVariant]*TestingResults, installTestLevelData map[JobVariant]*TestResults) []ValidationResult {
results := []ValidationResult{}
for jobVariant, testedVariant := range testingResults {
@@ -382,23 +432,45 @@ func checkIfTestingIsSufficient(featureGate string, testingResults map[JobVarian
Error: fmt.Errorf("warning: variant %v includes test data from candidate-tier jobs which are not covered by Component Readiness and lack standard regression protection",
jobVariant),
IsWarning: true,
+ Category: CategoryCandidateTier,
})
}
+ if len(testedVariant.TestResults) == 0 {
+ continue
+ }
+
if len(testedVariant.TestResults) < requiredNumberOfTests {
- results = append(results, ValidationResult{
- Error: fmt.Errorf("error: only %d tests found, need at least %d for %q on %v",
- len(testedVariant.TestResults), requiredNumberOfTests, featureGate, jobVariant),
- IsWarning: isOptional,
- })
+ if strings.Contains(featureGate, "Install") {
+ results = append(results, ValidationResult{
+ Error: fmt.Errorf("info: %d tests found for %q on %v",
+ len(testedVariant.TestResults), featureGate, jobVariant),
+ IsWarning: true,
+ IsInfo: true,
+ Category: CategoryInsufficientTests,
+ })
+ } else {
+ results = append(results, ValidationResult{
+ Error: fmt.Errorf("error: only %d tests found, need at least %d for %q on %v",
+ len(testedVariant.TestResults), requiredNumberOfTests, featureGate, jobVariant),
+ IsWarning: isOptional,
+ Category: CategoryInsufficientTests,
+ })
+ }
}
for _, testResults := range testedVariant.TestResults {
+ // Skip "install should succeed: overall" for Install feature gates - it has special validation below
+ if strings.Contains(featureGate, "Install") && testResults.TestName == "install should succeed: overall" {
+ continue
+ }
+
if testResults.TotalRuns < requiredNumberOfTestRunsPerVariant {
results = append(results, ValidationResult{
Error: fmt.Errorf("error: %q only has %d runs, need at least %d runs for %q on %v",
testResults.TestName, testResults.TotalRuns, requiredNumberOfTestRunsPerVariant, featureGate, jobVariant),
- IsWarning: isOptional,
+ IsWarning: isOptional,
+ Category: CategoryInsufficientRuns,
})
}
if testResults.TotalRuns == 0 {
@@ -412,14 +484,87 @@ func checkIfTestingIsSufficient(featureGate string, testingResults map[JobVarian
Error: fmt.Errorf("error: %q only passed %d%%, need at least %d%% for %q on %v",
testResults.TestName, displayActual, displayExpected, featureGate, jobVariant),
IsWarning: isOptional,
+ Category: CategoryPassRate,
})
}
}
+
+ // For Install feature gates, validate "install should succeed: overall" using test-level data from Sippy
+ if strings.Contains(featureGate, "Install") {
+ installTest := installTestLevelData[jobVariant]
+ if installTest == nil {
+ results = append(results, ValidationResult{
+ Error: fmt.Errorf("error: \"install should succeed: overall\" test data not found for Install feature gate %q on %v",
+ featureGate, jobVariant),
+ IsWarning: false,
+ Category: CategoryInstallTest,
+ })
+ } else {
+ if installTest.TotalRuns < requiredNumberOfTestRunsPerVariant {
+ results = append(results, ValidationResult{
+ Error: fmt.Errorf("error: \"install should succeed: overall\" only has %d runs, need at least %d runs for %q on %v",
+ installTest.TotalRuns, requiredNumberOfTestRunsPerVariant, featureGate, jobVariant),
+ IsWarning: isOptional,
+ Category: CategoryInstallTest,
+ })
+ }
+ if installTest.TotalRuns > 0 {
+ passPercent := float32(installTest.SuccessfulRuns) / float32(installTest.TotalRuns)
+ if passPercent < requiredPassRateForInstallTest {
+ displayExpected := int(requiredPassRateForInstallTest * 100)
+ displayActual := int(passPercent * 100)
+ results = append(results, ValidationResult{
+ Error: fmt.Errorf("error: \"install should succeed: overall\" only passed %d%%, need at least %d%% for %q on %v",
+ displayActual, displayExpected, featureGate, jobVariant),
+ IsWarning: isOptional,
+ Category: CategoryInstallTest,
+ })
+ }
+ }
+ }
+ }
}
return results
}
+func groupErrorsByCategory(results []ValidationResult) []error {
+ categoryOrder := []ValidationCategory{}
+ grouped := map[ValidationCategory][]ValidationResult{}
+ for _, vr := range results {
+ if _, seen := grouped[vr.Category]; !seen {
+ categoryOrder = append(categoryOrder, vr.Category)
+ }
+ grouped[vr.Category] = append(grouped[vr.Category], vr)
+ }
+ var errs []error
+ for _, cat := range categoryOrder {
+ for _, vr := range grouped[cat] {
+ errs = append(errs, vr.Error)
+ }
+ }
+ return errs
+}
+
+func writeGroupedValidationResults(results []ValidationResult, md *utils.Markdown) {
+ categoryOrder := []ValidationCategory{}
+ grouped := map[ValidationCategory][]ValidationResult{}
+ for _, vr := range results {
+ if _, seen := grouped[vr.Category]; !seen {
+ categoryOrder = append(categoryOrder, vr.Category)
+ }
+ grouped[vr.Category] = append(grouped[vr.Category], vr)
+ }
+ for i, cat := range categoryOrder {
+ if i > 0 {
+ md.Text("")
+ }
+ for _, vr := range grouped[cat] {
+ md.Textf(" - %s\n", vr.Error.Error())
+ }
+ }
+}
+
func writeTestingMarkDown(testingResults map[JobVariant]*TestingResults, md *utils.Markdown) {
jobVariantsSet := sets.KeySet(testingResults)
jobVariants := jobVariantsSet.UnsortedList()
@@ -599,6 +744,16 @@ var (
NetworkStack: "dual",
JobTiers: "candidate,standard,informing,blocking",
},
+ {
+ Cloud: "metal",
+ Architecture: "amd64",
+ Topology: "single",
+ },
+ {
+ Cloud: "metal",
+ Architecture: "amd64",
+ Topology: "compact",
+ },
}
nonHypershiftPlatforms = regexp.MustCompile("(?i)nutanix|metal|vsphere|openstack|azure|gcp")
@@ -622,6 +777,20 @@ type JobVariant struct {
Optional bool // If true, validation failures for this variant are non-blocking warnings
}
+func (jv JobVariant) String() string {
+ result := fmt.Sprintf("cloud=%s arch=%s topology=%s", jv.Cloud, jv.Architecture, jv.Topology)
+ if jv.NetworkStack != "" {
+ result += fmt.Sprintf(" network=%s", jv.NetworkStack)
+ }
+ if jv.OS != "" {
+ result += fmt.Sprintf(" os=%s", jv.OS)
+ }
+ if jv.Optional {
+ result += " optional=true"
+ }
+ return result
+}
+
type OrderedJobVariants []JobVariant
func (a OrderedJobVariants) Len() int { return len(a) }
@@ -690,10 +859,22 @@ type TestResults struct {
FlakedRuns int
}
+type ValidationCategory string
+
+const (
+ CategoryCandidateTier ValidationCategory = "candidate-tier"
+ CategoryInsufficientTests ValidationCategory = "insufficient-tests"
+ CategoryInsufficientRuns ValidationCategory = "insufficient-runs"
+ CategoryPassRate ValidationCategory = "pass-rate"
+ CategoryInstallTest ValidationCategory = "install-test"
+)
+
// ValidationResult represents a validation error or warning
type ValidationResult struct {
Error error
- IsWarning bool // if true, this is a non-blocking warning (for optional variants)
+ IsWarning bool // if true, this is a non-blocking warning (for optional variants)
+ IsInfo bool // if true, this is informational telemetry (e.g., install test pass percentage)
+ Category ValidationCategory // groups related results together in output
}
func testResultByName(results []TestResults, testName string) *TestResults {
@@ -736,10 +917,11 @@ func validateJobTiers(jobVariant JobVariant) error {
return nil
}
-func listTestResultFor(featureGate string, clusterProfiles sets.Set[string]) (map[JobVariant]*TestingResults, error) {
+func listTestResultFor(featureGate string, clusterProfiles sets.Set[string]) (map[JobVariant]*TestingResults, map[JobVariant]*TestResults, error) {
fmt.Printf("Query sippy for all test run results for feature gate %q on clusterProfile %q\n", featureGate, sets.List(clusterProfiles))
results := map[JobVariant]*TestingResults{}
+ installTestLevelData := map[JobVariant]*TestResults{}
var jobVariantsToCheck []JobVariant
if clusterProfiles.Has("Hypershift") && !nonHypershiftPlatforms.MatchString(featureGate) {
@@ -755,24 +937,41 @@ func listTestResultFor(featureGate string, clusterProfiles sets.Set[string]) (ma
}
jobVariantsToCheck = append(jobVariantsToCheck, selfManagedPlatformVariants...)
+
+ // Always include metal single and compact variants as optional checks
+ for _, v := range optionalSelfManagedPlatformVariants {
+ if strings.ToLower(v.Cloud) == "metal" && (strings.ToLower(v.Topology) == "single" || strings.ToLower(v.Topology) == "compact") {
+ jobVariantsToCheck = append(jobVariantsToCheck, v)
+ }
+ }
}
// Validate all variants before making expensive API calls
for _, jobVariant := range jobVariantsToCheck {
if err := validateJobTiers(jobVariant); err != nil {
- return nil, err
+ return nil, nil, err
}
}
for _, jobVariant := range jobVariantsToCheck {
jobVariantResults, err := listTestResultForVariant(featureGate, jobVariant)
if err != nil {
- return nil, err
+ return nil, nil, err
}
results[jobVariant] = jobVariantResults
+
+ // For Install feature gates, count "install should succeed: overall" results
+ // directly from individual job runs, excluding infrastructure failures entirely.
+ if strings.Contains(featureGate, "Install") {
+ installTestData, err := getInstallTestResultsFromJobRuns(featureGate, jobVariant)
+ if err != nil {
+ return nil, nil, err
+ }
+ installTestLevelData[jobVariant] = installTestData
+ }
}
- return results, nil
+ return results, installTestLevelData, nil
}
func filterVariants(featureGate string, variantsList ...[]JobVariant) []JobVariant {
@@ -862,15 +1061,174 @@ func getRelease() (string, error) {
return getLatestRelease()
}
-func listTestResultForVariant(featureGate string, jobVariant JobVariant) (*TestingResults, error) {
- // Substring here matches for both [OCPFeatureGate:...] and [FeatureGate:...]
- testPattern := fmt.Sprintf("FeatureGate:%s]", featureGate)
+func getInstallTestResultsFromJobRuns(featureGate string, jobVariant JobVariant) (*TestResults, error) {
+ release, err := getRelease()
+ if err != nil {
+ return nil, fmt.Errorf("couldn't determine release: %w", err)
+ }
+
+ defaultTransport := &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ ForceAttemptHTTP2: true,
+ MaxIdleConns: 100,
+ IdleConnTimeout: 90 * time.Second,
+ TLSHandshakeTimeout: 10 * time.Second,
+ ExpectContinueTimeout: 1 * time.Second,
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: true,
+ },
+ }
+ sippyClient := &http.Client{
+ Timeout: 2 * time.Minute,
+ Transport: defaultTransport,
+ }
+
+ jobs, err := getJobsForFeatureGateFromSippy(sippyClient, release, featureGate, jobVariant)
+ if err != nil {
+ return nil, fmt.Errorf("getting jobs for install test results: %w", err)
+ }
+ testResults := &TestResults{
+ TestName: "install should succeed: overall",
+ }
+
+ for _, job := range jobs {
+ jobRuns, err := getJobRunsFromSippy(sippyClient, release, job.Name)
+ if err != nil {
+ return nil, fmt.Errorf("getting job runs for %q: %w", job.Name, err)
+ }
+ for _, jobRun := range jobRuns {
+ if jobRun.OverallResult == "N" || jobRun.OverallResult == "n" {
+ continue
+ }
+ testResults.TotalRuns++
+ installFailed := false
+ for _, failure := range jobRun.FailedTestNames {
+ if failure == "install should succeed: overall" {
+ installFailed = true
+ break
+ }
+ }
+ if installFailed {
+ testResults.FailedRuns++
+ } else {
+ testResults.SuccessfulRuns++
+ }
+ }
+ }
+
+ if testResults.TotalRuns == 0 {
+ return nil, nil
+ }
+
+ return testResults, nil
+}
+
+func getInstallTestLevelData(featureGate string, jobVariant JobVariant) (*TestResults, error) {
+ testPattern := "install should succeed: overall"
+ queries := sippy.QueriesForWithCapability(jobVariant.Cloud, jobVariant.Architecture, jobVariant.Topology,
+ jobVariant.NetworkStack, jobVariant.OS, jobVariant.JobTiers, testPattern, featureGate)
+
+ defaultTransport := &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ ForceAttemptHTTP2: true,
+ MaxIdleConns: 100,
+ IdleConnTimeout: 90 * time.Second,
+ TLSHandshakeTimeout: 10 * time.Second,
+ ExpectContinueTimeout: 1 * time.Second,
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: true,
+ },
+ }
+
+ sippyClient := &http.Client{
+ Timeout: 2 * time.Minute,
+ Transport: defaultTransport,
+ }
+
+ release, err := getRelease()
+ if err != nil {
+ return nil, fmt.Errorf("couldn't fetch latest release version: %w", err)
+ }
+
+ var installTestResult *TestResults
+ for _, currQuery := range queries {
+ currURL := &url.URL{
+ Scheme: "https",
+ Host: "sippy.dptools.openshift.org",
+ Path: "api/tests",
+ }
+ queryParams := currURL.Query()
+ queryParams.Add("release", release)
+ queryParams.Add("period", "default")
+ filterJSON, err := json.Marshal(currQuery)
+ if err != nil {
+ return nil, err
+ }
+ queryParams.Add("filter", string(filterJSON))
+ currURL.RawQuery = queryParams.Encode()
+
+ req, err := http.NewRequest(http.MethodGet, currURL.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := sippyClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ if response.StatusCode < 200 || response.StatusCode > 299 {
+ return nil, fmt.Errorf("error getting sippy results (status=%d) for: %v", response.StatusCode, currURL.String())
+ }
+ queryResultBytes, err := io.ReadAll(response.Body)
+ if err != nil {
+ return nil, err
+ }
+ response.Body.Close()
+
+ testInfos := []sippy.SippyTestInfo{}
+ if err := json.Unmarshal(queryResultBytes, &testInfos); err != nil {
+ return nil, err
+ }
+
+ for _, currTest := range testInfos {
+ if installTestResult == nil {
+ installTestResult = &TestResults{
+ TestName: currTest.Name,
+ }
+ }
+
+ // Accumulate results across multiple JobTier queries
+ if currTest.CurrentRuns >= requiredNumberOfTestRunsPerVariant {
+ installTestResult.TotalRuns += currTest.CurrentRuns
+ installTestResult.SuccessfulRuns += currTest.CurrentSuccesses
+ installTestResult.FailedRuns += currTest.CurrentFailures
+ installTestResult.FlakedRuns += currTest.CurrentFlakes
+ } else {
+ installTestResult.TotalRuns += currTest.CurrentRuns + currTest.PreviousRuns
+ installTestResult.SuccessfulRuns += currTest.CurrentSuccesses + currTest.PreviousSuccesses
+ installTestResult.FailedRuns += currTest.CurrentFailures + currTest.PreviousFailures
+ installTestResult.FlakedRuns += currTest.CurrentFlakes + currTest.PreviousFlakes
+ }
+ }
+ }
+
+ return installTestResult, nil
+}
+
+func listTestResultForVariant(featureGate string, jobVariant JobVariant) (*TestingResults, error) {
// Feature gates used by the installer don't need separate tests, use the overall install tests
if strings.Contains(featureGate, "Install") {
return verifyJobBasedFeatureGatePromotion(featureGate, jobVariant)
}
+ var testPattern string
+ var queries []*sippy.SippyQueryStruct
+
+ // Substring here matches for both [OCPFeatureGate:...] and [FeatureGate:...]
+ testPattern = fmt.Sprintf("FeatureGate:%s]", featureGate)
+ queries = sippy.QueriesFor(jobVariant.Cloud, jobVariant.Architecture, jobVariant.Topology,
+ jobVariant.NetworkStack, jobVariant.OS, jobVariant.JobTiers, testPattern)
fmt.Printf("Query sippy for all test run results for pattern %q on variant %#v\n", testPattern, jobVariant)
defaultTransport := &http.Transport{
@@ -892,12 +1250,10 @@ func listTestResultForVariant(featureGate string, jobVariant JobVariant) (*Testi
testNameToResults := map[string]*TestResults{}
hasCandidateTierResults := false
- queries := sippy.QueriesFor(jobVariant.Cloud, jobVariant.Architecture, jobVariant.Topology, jobVariant.NetworkStack, jobVariant.OS, jobVariant.JobTiers, testPattern)
release, err := getRelease()
if err != nil {
return nil, fmt.Errorf("couldn't fetch latest release version: %w", err)
}
- fmt.Printf("Querying sippy release %s for test run results\n", release)
for _, currQuery := range queries {
currURL := &url.URL{
@@ -1091,17 +1447,25 @@ func verifyJobPassRate(client *http.Client, release string, job sippy.SippyJob,
return nil, fmt.Errorf("getting job %q results from sippy: %w", job.Name, err)
}
- testResults := &TestResults{
- TestName: job.Name,
- TotalRuns: len(jobRuns),
- }
-
triagedTestFailures, err := getTriagedTestFailuresFromSippy(client, release, variant)
if err != nil {
return nil, fmt.Errorf("getting triaged test failures from sippy: %w", err)
}
+ fmt.Printf("\nIgnoring job runs that have internal or external infrastructure failures from our analysis.\n\n")
+
+ infraFailures := 0
+ testResults := &TestResults{
+ TestName: job.Name,
+ TotalRuns: len(jobRuns),
+ }
+
for _, jobRun := range jobRuns {
+ if jobRun.OverallResult == "N" || jobRun.OverallResult == "n" {
+ infraFailures++
+ continue
+ }
+
if jobRun.OverallResult == "F" && !jobRun.KnownFailure {
untriagedTestFailures := []string{}
@@ -1128,6 +1492,8 @@ func verifyJobPassRate(client *http.Client, release string, job sippy.SippyJob,
testResults.SuccessfulRuns++
}
+ testResults.TotalRuns -= infraFailures
+
return testResults, nil
}
@@ -1139,7 +1505,7 @@ func getJobsForFeatureGateFromSippy(client *http.Client, release, featureGate st
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("expected a 200 OK status code but got %s", resp.StatusCode)
+ return nil, fmt.Errorf("expected a 200 OK status code but got %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
@@ -1165,7 +1531,7 @@ func getJobRunsFromSippy(client *http.Client, release, jobName string) ([]sippy.
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("expected a 200 OK status code but got %s", resp.StatusCode)
+ return nil, fmt.Errorf("expected a 200 OK status code but got %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
diff --git a/tools/codegen/cmd/featuregate-test-analyzer_test.go b/tools/codegen/cmd/featuregate-test-analyzer_test.go
index 24d2bad6c20..2c22e5da4e9 100644
--- a/tools/codegen/cmd/featuregate-test-analyzer_test.go
+++ b/tools/codegen/cmd/featuregate-test-analyzer_test.go
@@ -65,7 +65,7 @@ func Test_listTestResultFor(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Skip("this is for ease of manual testing")
- got, err := listTestResultFor(tt.args.featureGate, sets.New[string](tt.args.clusterProfile))
+ got, _, err := listTestResultFor(tt.args.featureGate, sets.New[string](tt.args.clusterProfile))
if (err != nil) != tt.wantErr {
t.Errorf("listTestResultFor() error = %v, wantErr %v", err, tt.wantErr)
return
@@ -481,6 +481,189 @@ func Test_checkIfTestingIsSufficient_OptionalVariants(t *testing.T) {
}
}
+func Test_checkIfTestingIsSufficient_InstallFeatureGates(t *testing.T) {
+ tests := []struct {
+ name string
+ featureGate string
+ testingResults map[JobVariant]*TestingResults
+ wantBlockingErrors int
+ wantWarnings int
+ }{
+ {
+ name: "Install feature gate with install should succeed: overall test failing 100% requirement",
+ featureGate: "FakeInstallFeature",
+ testingResults: map[JobVariant]*TestingResults{
+ {
+ Cloud: "metal",
+ Architecture: "amd64",
+ Topology: "ha",
+ }: {
+ TestResults: []TestResults{
+ {TestName: "install should succeed: overall", TotalRuns: 20, SuccessfulRuns: 19},
+ {TestName: "test1", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test2", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test3", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test4", TotalRuns: 15, SuccessfulRuns: 15},
+ },
+ },
+ },
+ wantBlockingErrors: 1, // Blocking error: install should succeed: overall must pass at 100%
+ wantWarnings: 0,
+ },
+ {
+ name: "Install feature gate without install should succeed: overall test - warning reported",
+ featureGate: "MockInstallGate",
+ testingResults: map[JobVariant]*TestingResults{
+ {
+ Cloud: "metal",
+ Architecture: "amd64",
+ Topology: "ha",
+ }: {
+ TestResults: []TestResults{
+ {TestName: "test1", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test2", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test3", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test4", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test5", TotalRuns: 15, SuccessfulRuns: 15},
+ },
+ },
+ },
+ wantBlockingErrors: 0,
+ wantWarnings: 1, // Warning about missing "install should succeed: overall" test
+ },
+ {
+ name: "Non-Install feature gate with install should succeed: overall test - no special validation",
+ featureGate: "SomeOtherFeature",
+ testingResults: map[JobVariant]*TestingResults{
+ {
+ Cloud: "aws",
+ Architecture: "amd64",
+ Topology: "ha",
+ }: {
+ TestResults: []TestResults{
+ {TestName: "install should succeed: overall", TotalRuns: 20, SuccessfulRuns: 19},
+ {TestName: "test1", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test2", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test3", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test4", TotalRuns: 15, SuccessfulRuns: 15},
+ },
+ },
+ },
+ wantBlockingErrors: 0,
+ wantWarnings: 0,
+ },
+ {
+ name: "Install feature gate with 100% pass rate - no errors",
+ featureGate: "FakeInstallFeature",
+ testingResults: map[JobVariant]*TestingResults{
+ {
+ Cloud: "aws",
+ Architecture: "amd64",
+ Topology: "ha",
+ }: {
+ TestResults: []TestResults{
+ {TestName: "install should succeed: overall", TotalRuns: 20, SuccessfulRuns: 20},
+ {TestName: "test1", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test2", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test3", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test4", TotalRuns: 15, SuccessfulRuns: 15},
+ },
+ },
+ },
+ wantBlockingErrors: 0,
+ wantWarnings: 0,
+ },
+ {
+ name: "Install feature gate with multiple variants - one fails 100% requirement",
+ featureGate: "FakeInstallFeature",
+ testingResults: map[JobVariant]*TestingResults{
+ {
+ Cloud: "metal",
+ Architecture: "amd64",
+ Topology: "ha",
+ }: {
+ TestResults: []TestResults{
+ {TestName: "install should succeed: overall", TotalRuns: 20, SuccessfulRuns: 19},
+ {TestName: "test1", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test2", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test3", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test4", TotalRuns: 15, SuccessfulRuns: 15},
+ },
+ },
+ {
+ Cloud: "metal",
+ Architecture: "amd64",
+ Topology: "single",
+ }: {
+ TestResults: []TestResults{
+ {TestName: "install should succeed: overall", TotalRuns: 18, SuccessfulRuns: 18},
+ {TestName: "test1", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test2", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test3", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test4", TotalRuns: 15, SuccessfulRuns: 15},
+ },
+ },
+ },
+ wantBlockingErrors: 1, // One variant (ha) fails 100% requirement
+ wantWarnings: 0,
+ },
+ {
+ name: "Install feature gate with insufficient runs for install test - blocking error",
+ featureGate: "MockInstallGate",
+ testingResults: map[JobVariant]*TestingResults{
+ {
+ Cloud: "aws",
+ Architecture: "amd64",
+ Topology: "ha",
+ }: {
+ TestResults: []TestResults{
+ {TestName: "install should succeed: overall", TotalRuns: 10, SuccessfulRuns: 10},
+ {TestName: "test1", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test2", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test3", TotalRuns: 15, SuccessfulRuns: 15},
+ {TestName: "test4", TotalRuns: 15, SuccessfulRuns: 15},
+ },
+ },
+ },
+ wantBlockingErrors: 1, // Blocking error for insufficient runs (< 14)
+ wantWarnings: 0,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ results := checkIfTestingIsSufficient(tt.featureGate, tt.testingResults)
+
+ blockingErrors := 0
+ warnings := 0
+ for _, result := range results {
+ if result.IsWarning {
+ warnings++
+ } else {
+ blockingErrors++
+ }
+ }
+
+ if blockingErrors != tt.wantBlockingErrors {
+ t.Errorf("got %d blocking errors, want %d", blockingErrors, tt.wantBlockingErrors)
+ for _, result := range results {
+ if !result.IsWarning {
+ t.Logf(" Blocking error: %v", result.Error)
+ }
+ }
+ }
+ if warnings != tt.wantWarnings {
+ t.Errorf("got %d warnings, want %d", warnings, tt.wantWarnings)
+ for _, result := range results {
+ if result.IsWarning {
+ t.Logf(" Warning: %v", result.Error)
+ }
+ }
+ }
+ })
+ }
+}
+
func Test_defaultQueriesIncludeCandidateTier(t *testing.T) {
// When JobTiers is empty, QueriesFor should generate queries for all tiers
// including candidate. This test is added to prevent regressions for candidate-tier
diff --git a/tools/codegen/cmd/root.go b/tools/codegen/cmd/root.go
index 55236924461..b35479e362f 100644
--- a/tools/codegen/cmd/root.go
+++ b/tools/codegen/cmd/root.go
@@ -61,7 +61,7 @@ var rootCmd = &cobra.Command{
func main() {
err := rootCmd.Execute()
if err != nil {
- klog.Fatalf("Error running codegen: %v", err)
+ klog.Fatalf("%v", err)
}
}
diff --git a/tools/codegen/pkg/sippy/json_types.go b/tools/codegen/pkg/sippy/json_types.go
index ad2012a3ef5..2242eab6ac9 100644
--- a/tools/codegen/pkg/sippy/json_types.go
+++ b/tools/codegen/pkg/sippy/json_types.go
@@ -179,6 +179,104 @@ func QueriesFor(cloud, architecture, topology, networkStack, os, jobTiers, testP
return queries
}
+func QueriesForWithCapability(cloud, architecture, topology, networkStack, os, jobTiers, testPattern, capability string) []*SippyQueryStruct {
+ // Build base query items that are common to all JobTier queries
+ baseItems := []SippyQueryItem{
+ {
+ ColumnField: "variants",
+ Not: false,
+ OperatorValue: "contains",
+ Value: fmt.Sprintf("Platform:%s", cloud),
+ },
+ {
+ ColumnField: "variants",
+ Not: false,
+ OperatorValue: "contains",
+ Value: fmt.Sprintf("Architecture:%s", architecture),
+ },
+ {
+ ColumnField: "variants",
+ Not: false,
+ OperatorValue: "contains",
+ Value: fmt.Sprintf("Topology:%s", topology),
+ },
+ {
+ ColumnField: "name",
+ Not: false,
+ OperatorValue: "contains",
+ Value: testPattern,
+ },
+ {
+ ColumnField: "variants",
+ Not: false,
+ OperatorValue: "contains",
+ Value: fmt.Sprintf("Capability:%s", capability),
+ },
+ }
+
+ if networkStack != "" {
+ baseItems = append(baseItems, SippyQueryItem{
+ ColumnField: "variants",
+ Not: false,
+ OperatorValue: "contains",
+ Value: fmt.Sprintf("NetworkStack:%s", networkStack),
+ })
+ }
+
+ if os != "" {
+ baseItems = append(baseItems, SippyQueryItem{
+ ColumnField: "variants",
+ Not: false,
+ OperatorValue: "contains",
+ Value: fmt.Sprintf("OS:%s", os),
+ })
+ }
+
+ // Parse JobTiers - comma-separated string, default to standard/informing/blocking/candidate if empty
+ var jobTiersList []string
+ if jobTiers == "" {
+ jobTiersList = []string{"standard", "informing", "blocking", "candidate"}
+ } else {
+ // Split by comma, trim whitespace, and deduplicate using sets
+ tierSet := sets.New[string]()
+ for _, tier := range strings.Split(jobTiers, ",") {
+ if trimmed := strings.TrimSpace(tier); trimmed != "" {
+ tierSet.Insert(trimmed)
+ }
+ }
+ // If all tiers were whitespace/empty after trimming, use defaults
+ if tierSet.Len() == 0 {
+ jobTiersList = []string{"standard", "informing", "blocking", "candidate"}
+ } else {
+ jobTiersList = sets.List(tierSet)
+ }
+ }
+
+ // Generate one query per JobTier (to work around API's single LinkOperator limitation)
+ var queries []*SippyQueryStruct
+ for _, jobTier := range jobTiersList {
+ // Copy base items for this query
+ items := make([]SippyQueryItem, len(baseItems))
+ copy(items, baseItems)
+
+ // Add JobTier filter
+ items = append(items, SippyQueryItem{
+ ColumnField: "variants",
+ Not: false,
+ OperatorValue: "contains",
+ Value: fmt.Sprintf("JobTier:%s", jobTier),
+ })
+
+ queries = append(queries, &SippyQueryStruct{
+ Items: items,
+ LinkOperator: "and",
+ TierName: jobTier,
+ })
+ }
+
+ return queries
+}
+
func BuildSippyTestAnalysisURL(release, testName, topology, cloud, architecture, networkStack, os string) string {
filterItems := []SippyQueryItem{
{