From 3bc201a6a98e52f6d8580ae733f0a6d7c1627b43 Mon Sep 17 00:00:00 2001 From: Pedro Almeida Date: Wed, 1 Jul 2026 10:36:11 +0100 Subject: [PATCH] OCPCLOUD-3571: Add OTE e2e tests for ClusterAPIMachineManagementAWS feature gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds 5 blocking OTE tests validating the CAPI AWS stack when ClusterAPIMachineManagementAWS is enabled, plus a generic platform Walk in the OTE extension registration. ## Tests | # | Test | What it proves | Gated by | |---|---|---|---| | 1 | capa-controller-manager deployment available | AWS provider controller deployed by capi-installer | AWS gate only | | 2 | Core AWS CRDs established (awsclusters, awsmachines, awsmachinetemplates) | CAPA CRD bundle installed by capi-installer | AWS gate only | | 3 | AWSCluster.Spec.Region matches Infrastructure region | InfraClusterController correctly read Infrastructure CR | Both gates | | 4 | AWSCluster.Status.Ready=True | InfraClusterController reconciled AWS infra end-to-end | Both gates | | 5 | Cluster.InfrastructureReady=True | CAPI core accepted the AWS infra, completing the stack | Both gates | Tests 1-2 are directly controlled by ClusterAPIMachineManagementAWS (capi-installer deploys the CAPA bundle). Tests 3-5 require both gates — ClusterAPIMachineManagement for capi-controllers to run and ClusterAPIMachineManagementAWS for the AWS CRDs to exist. In practice the base gate is promoted first, so both are always enabled together. ## Platform restriction (two-layer) Layer 1 — OTE environmentSelector (periodic jobs): A generic Walk over all specs reads Label("platform:") and adds spec.Include(PlatformEquals(platform)). This avoids per-platform clauses in main.go — adding GCP/Azure tests only requires a Label on the Describe. Layer 2 — BeforeEach guard (make e2e presubmits): The Ginkgo BeforeEach checks both the feature gate and the cluster platform. OTE environmentSelector is not evaluated in the make e2e path. ## Design decisions - assertDeploymentAvailable not extracted: used once, no abstraction benefit. - AWSClusterControllerIdentity object test excluded: it is created by CAPA internals (not by this gate), and its absence is caught transitively by AWSCluster.Status.Ready=True. - metav1.ConditionTrue used directly instead of metav1.ConditionStatus("True"). - string() cast on ClusterInfrastructureReadyCondition removed (untyped const). ## Validation Validated on a TechPreview AWS cluster-bot cluster: OTE binary (run-suite capio/parallel): passed — capa-controller-manager deployment available passed — core AWS Cluster API CRDs installed and established passed — AWSCluster region matching the cluster infrastructure region passed — AWSCluster object present and ready passed — management Cluster object with InfrastructureReady=True make e2e (--focus=ClusterAPIMachineManagementAWS): Ran 5 of 54 Specs in 2.423 seconds SUCCESS! -- 5 Passed | 0 Failed | 2 Pending | 47 Skipped Co-Authored-By: Claude Sonnet 4.6 (1M context) --- e2e/cluster_api_machine_management_aws.go | 90 +++++++++++++++++++++++ openshift-tests-extension/cmd/main.go | 11 +++ 2 files changed, 101 insertions(+) create mode 100644 e2e/cluster_api_machine_management_aws.go diff --git a/e2e/cluster_api_machine_management_aws.go b/e2e/cluster_api_machine_management_aws.go new file mode 100644 index 000000000..0dc1fc0f1 --- /dev/null +++ b/e2e/cluster_api_machine_management_aws.go @@ -0,0 +1,90 @@ +// Copyright 2026 Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2" + "sigs.k8s.io/controller-runtime/pkg/envtest/komega" + + configv1 "github.com/openshift/api/config/v1" + "github.com/openshift/api/features" + "github.com/openshift/cluster-capi-operator/e2e/framework" +) + +var _ = Describe("[sig-cluster-lifecycle][OCPFeatureGate:ClusterAPIMachineManagementAWS] Cluster API Machine Management AWS", + Label("platform:aws"), + func() { + BeforeEach(func() { + if !framework.IsFeatureGateEnabled(ctx, cl, features.FeatureGateClusterAPIMachineManagementAWS) { + Skip("Feature gate ClusterAPIMachineManagementAWS is not enabled.") + } + if platform != configv1.AWSPlatformType { + Skip("Skipping AWS-specific tests on non-AWS platform.") + } + }) + + Context("AWS provider deployment", func() { + It("should have the capa-controller-manager deployment available", func() { + deployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "capa-controller-manager", Namespace: framework.CAPINamespace}} + Eventually(komega.Object(deployment)).WithTimeout(framework.WaitMedium).WithPolling(framework.RetryMedium).Should( + HaveField("Status.Conditions", ContainElement(SatisfyAll( + HaveField("Type", Equal(appsv1.DeploymentAvailable)), + HaveField("Status", Equal(corev1.ConditionTrue)), + ))), + ) + }) + }) + + Context("AWS infrastructure CRDs", func() { + DescribeTable("should have core AWS Cluster API CRDs installed and established", + func(name string) { + crd := &apiextensionsv1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: name}} + Eventually(komega.Object(crd)).WithTimeout(framework.WaitMedium).WithPolling(framework.RetryMedium).Should( + HaveField("Status.Conditions", ContainElement(SatisfyAll( + HaveField("Type", Equal(apiextensionsv1.Established)), + HaveField("Status", Equal(apiextensionsv1.ConditionTrue)), + ))), + ) + }, + Entry("awsclusters CRD", "awsclusters.infrastructure.cluster.x-k8s.io"), + Entry("awsmachines CRD", "awsmachines.infrastructure.cluster.x-k8s.io"), + Entry("awsmachinetemplates CRD", "awsmachinetemplates.infrastructure.cluster.x-k8s.io"), + Entry("awsclustercontrolleridentities CRD", "awsclustercontrolleridentities.infrastructure.cluster.x-k8s.io"), + ) + + }) + + Context("Management cluster AWS resources", func() { + It("should have the management Cluster object with InfrastructureReady=True", func() { + cluster := &clusterv1.Cluster{ObjectMeta: metav1.ObjectMeta{ + Name: clusterName, + Namespace: framework.CAPINamespace, + }} + Eventually(komega.Object(cluster)).WithTimeout(framework.WaitLong).WithPolling(framework.RetryMedium).Should( + HaveField("Status.Conditions", ContainElement(SatisfyAll( + HaveField("Type", Equal(clusterv1.ClusterInfrastructureReadyCondition)), + HaveField("Status", Equal(metav1.ConditionTrue)), + ))), + ) + }) + }) + }) diff --git a/openshift-tests-extension/cmd/main.go b/openshift-tests-extension/cmd/main.go index a5f2f7e15..d11e62eae 100644 --- a/openshift-tests-extension/cmd/main.go +++ b/openshift-tests-extension/cmd/main.go @@ -19,10 +19,12 @@ package main import ( "fmt" "os" + "strings" "time" "github.com/openshift-eng/openshift-tests-extension/pkg/cmd" e "github.com/openshift-eng/openshift-tests-extension/pkg/extension" + et "github.com/openshift-eng/openshift-tests-extension/pkg/extension/extensiontests" g "github.com/openshift-eng/openshift-tests-extension/pkg/ginkgo" "github.com/spf13/cobra" @@ -70,6 +72,15 @@ func main() { e2e.InitCommonVariables() }) + // Auto-apply platform environment selectors from Ginkgo Label("platform:") annotations. + specs.Walk(func(spec *et.ExtensionTestSpec) { + for label := range spec.Labels { + if platform, ok := strings.CutPrefix(label, "platform:"); ok { + spec.Include(et.PlatformEquals(platform)) + } + } + }) + ext.AddSpecs(specs) extensionRegistry.Register(ext)