Skip to content

Commit 92bc593

Browse files
committed
fixup! test(e2e): Add ownership assertions for AWS resources
1 parent aad485d commit 92bc593

File tree

9 files changed

+120
-61
lines changed

9 files changed

+120
-61
lines changed

make/go.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ endif
114114
test/e2e/... -- \
115115
-e2e.artifacts-folder="$(ARTIFACTS)" \
116116
-e2e.config="$(E2E_CONF_FILE_ENVSUBST)" \
117+
$(if $(filter $(E2E_SKIP_CLEANUP),true),-e2e.skip-resource-cleanup)
117118
go tool cover \
118119
-html=coverage-e2e.out \
119120
-o coverage-e2e.html

test/e2e/common.go

Lines changed: 0 additions & 30 deletions
This file was deleted.

test/e2e/config/cre.yaml

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -159,18 +159,12 @@ variables:
159159

160160
intervals:
161161
default/wait-controllers: ["3m", "10s"]
162-
default/wait-cluster: ["5m", "10s"]
162+
default/wait-cluster: ["10m", "10s"]
163163
default/wait-control-plane: ["10m", "10s"]
164-
default/wait-worker-nodes: ["5m", "10s"]
165-
default/wait-machine-pool-nodes: ["5m", "10s"]
166-
default/wait-delete-cluster: ["3m", "10s"]
167-
default/wait-machine-upgrade: ["20m", "10s"]
168-
default/wait-machine-pool-upgrade: ["5m", "10s"]
164+
default/wait-worker-nodes: ["10m", "10s"]
165+
default/wait-delete-cluster: ["30m", "10s"]
169166
default/wait-nodes-ready: ["10m", "10s"]
170-
default/wait-machine-remediation: ["5m", "10s"]
171-
default/wait-deployment: ["15m", "10s"]
172-
default/wait-daemonset: [ "15m", "10s" ]
173-
default/wait-clusterresourceset: [ "15m", "10s" ]
174-
default/wait-helmrelease: [ "15m", "10s" ]
175-
default/wait-job: [ "5m", "10s" ]
176-
default/wait-service: [ "15m", "10s" ]
167+
default/wait-deployment: ["10m", "10s"]
168+
default/wait-daemonset: [ "5m", "10s" ]
169+
default/wait-clusterresourceset: [ "5m", "10s" ]
170+
default/wait-helmrelease: [ "5m", "10s" ]

test/e2e/daemonset_helpers.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
. "github.com/onsi/gomega"
1313
appsv1 "k8s.io/api/apps/v1"
14+
capie2e "sigs.k8s.io/cluster-api/test/e2e"
1415
"sigs.k8s.io/cluster-api/test/framework"
1516
"sigs.k8s.io/controller-runtime/pkg/client"
1617
)
@@ -28,7 +29,7 @@ func WaitForDaemonSetsAvailable(
2829
) {
2930
start := time.Now()
3031
namespace, name := input.DaemonSet.GetNamespace(), input.DaemonSet.GetName()
31-
Byf("waiting for deployment %s/%s to be available", namespace, name)
32+
capie2e.Byf("waiting for deployment %s/%s to be available", namespace, name)
3233
Log("starting to wait for deployment to become available")
3334
Eventually(func() bool {
3435
key := client.ObjectKey{Namespace: namespace, Name: name}

test/e2e/deployment_helpers.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
. "github.com/onsi/gomega"
1313
appsv1 "k8s.io/api/apps/v1"
1414
corev1 "k8s.io/api/core/v1"
15+
capie2e "sigs.k8s.io/cluster-api/test/e2e"
1516
"sigs.k8s.io/cluster-api/test/framework"
1617
"sigs.k8s.io/controller-runtime/pkg/client"
1718
)
@@ -23,7 +24,7 @@ func WaitForDeploymentsAvailable(
2324
) {
2425
start := time.Now()
2526
key := client.ObjectKeyFromObject(input.Deployment)
26-
Byf("waiting for deployment %s to be available", key)
27+
capie2e.Byf("waiting for deployment %s to be available", key)
2728
Log("starting to wait for deployment to become available")
2829
Eventually(func() bool {
2930
if err := input.Getter.Get(ctx, key, input.Deployment); err == nil {

test/e2e/e2e_suite_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ var _ = SynchronizedBeforeSuite(func() []byte {
9191
By("Initializing a runtime.Scheme with all the GVK relevant for this test")
9292
scheme := initScheme()
9393

94-
Byf("Loading the e2e test configuration from %q", configPath)
94+
capie2e.Byf("Loading the e2e test configuration from %q", configPath)
9595
e2eConfig = loadE2EConfig(configPath)
9696

97-
Byf("Creating a clusterctl local repository into %q", artifactFolder)
97+
capie2e.Byf("Creating a clusterctl local repository into %q", artifactFolder)
9898
clusterctlConfigPath = createClusterctlLocalRepository(
9999
e2eConfig,
100100
filepath.Join(artifactFolder, "repository"),

test/e2e/helmreleaseproxy_helpers.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
. "github.com/onsi/gomega"
1414
addonsv1 "sigs.k8s.io/cluster-api-addon-provider-helm/api/v1alpha1"
1515
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
16+
capie2e "sigs.k8s.io/cluster-api/test/e2e"
1617
"sigs.k8s.io/cluster-api/test/framework"
1718
"sigs.k8s.io/cluster-api/util/conditions"
1819
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -43,7 +44,7 @@ func WaitForHelmReleaseProxyReadyForCluster(
4344
Expect(err).ToNot(HaveOccurred())
4445
hrpKey := ctrlclient.ObjectKeyFromObject(hrp)
4546

46-
Byf("waiting for HelmReleaseProxy for %s to be ready", hrpKey)
47+
capie2e.Byf("waiting for HelmReleaseProxy for %s to be ready", hrpKey)
4748
Log("starting to wait for HelmReleaseProxy to become available")
4849
Eventually(func() bool {
4950
err := input.GetLister.Get(ctx, hrpKey, hrp)

test/e2e/ownerreference_helpers.go

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,60 @@
66
package e2e
77

88
import (
9+
"slices"
10+
911
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1012
"k8s.io/utils/ptr"
1113
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
14+
addonsv1 "sigs.k8s.io/cluster-api/exp/addons/api/v1beta1"
1215
"sigs.k8s.io/cluster-api/test/framework"
1316

1417
caaphv1 "github.com/d2iq-labs/capi-runtime-extensions/api/external/sigs.k8s.io/cluster-api-addon-provider-helm/api/v1alpha1"
1518
)
1619

1720
const (
18-
clusterKind = "Cluster"
19-
clusterResourceSetKind = "ClusterResourceSet"
20-
helmChartProxyKind = "HelmChartProxy"
21-
helmReleaseProxyKind = "HelmReleaseProxy"
21+
clusterKind = "Cluster"
22+
clusterClassKind = "ClusterClass"
23+
machineDeploymentKind = "MachineDeployment"
24+
machineSetKind = "MachineSet"
25+
machineKind = "Machine"
26+
clusterResourceSetKind = "ClusterResourceSet"
27+
clusterResourceSetBindingKind = "ClusterResourceSetBinding"
28+
29+
awsMachineKind = "AWSMachine"
30+
awsMachineTemplateKind = "AWSMachineTemplate"
31+
awsClusterKind = "AWSCluster"
32+
awsClusterTemplateKind = "AWSClusterTemplate"
33+
awsClusterControllerIdentityKind = "AWSClusterControllerIdentity"
34+
35+
helmChartProxyKind = "HelmChartProxy"
36+
helmReleaseProxyKind = "HelmReleaseProxy"
2237
)
2338

2439
var (
40+
coreGroupVersion = clusterv1.GroupVersion.String()
41+
2542
clusterOwner = metav1.OwnerReference{
2643
Kind: clusterKind,
27-
APIVersion: clusterv1.GroupVersion.String(),
44+
APIVersion: coreGroupVersion,
45+
}
46+
clusterController = metav1.OwnerReference{
47+
Kind: clusterKind,
48+
APIVersion: coreGroupVersion,
49+
Controller: ptr.To(true),
50+
}
51+
clusterClassOwner = metav1.OwnerReference{
52+
Kind: clusterClassKind,
53+
APIVersion: coreGroupVersion,
54+
}
55+
machineController = metav1.OwnerReference{
56+
Kind: machineKind,
57+
APIVersion: coreGroupVersion,
58+
Controller: ptr.To(true),
59+
}
60+
clusterResourceSetOwner = metav1.OwnerReference{
61+
Kind: clusterResourceSetKind,
62+
APIVersion: addonsv1.GroupVersion.String(),
2863
}
2964
helmChartProxyOwner = metav1.OwnerReference{
3065
Kind: helmChartProxyKind,
@@ -43,6 +78,8 @@ var (
4378
)
4479
},
4580

81+
clusterResourceSetBindingKind: clusterResourceSetBindingIsOnlyOwnedByClusterResourceSets,
82+
4683
helmChartProxyKind: func(owners []metav1.OwnerReference) error {
4784
// The HelmChartProxies that we create are cluster specific and so should be owned by the cluster.
4885
return framework.HasExactOwners(
@@ -59,4 +96,51 @@ var (
5996
)
6097
},
6198
}
99+
100+
// AWSInfraOwnerReferenceAssertions maps AWS Infrastructure types to functions which return an error if the passed
101+
// OwnerReferences aren't as expected.
102+
AWSInfraOwnerReferenceAssertions = map[string]func([]metav1.OwnerReference) error{
103+
awsMachineKind: func(owners []metav1.OwnerReference) error {
104+
// The AWSMachine must be owned and controlled by a Machine.
105+
return framework.HasExactOwners(owners, machineController)
106+
},
107+
awsMachineTemplateKind: func(owners []metav1.OwnerReference) error {
108+
// Base AWSrMachineTemplates referenced in a ClusterClass must be owned by the ClusterClass.
109+
// AWSMachineTemplates created for specific Clusters in the Topology controller must be owned by a Cluster.
110+
return framework.HasOneOfExactOwners(
111+
owners,
112+
[]metav1.OwnerReference{clusterOwner},
113+
[]metav1.OwnerReference{clusterClassOwner},
114+
)
115+
},
116+
awsClusterKind: func(owners []metav1.OwnerReference) error {
117+
// AWSCluster must be owned and controlled by a Cluster.
118+
return framework.HasExactOwners(owners, clusterController)
119+
},
120+
awsClusterTemplateKind: func(owners []metav1.OwnerReference) error {
121+
// AWSClusterTemplate must be owned by a ClusterClass.
122+
return framework.HasExactOwners(owners, clusterClassOwner)
123+
},
124+
awsClusterControllerIdentityKind: func(owners []metav1.OwnerReference) error {
125+
// AWSClusterControllerIdentity should have no owners.
126+
return framework.HasExactOwners(owners)
127+
},
128+
}
62129
)
130+
131+
// dedupeOwners returns a a list of owners without duplicate owner types. Only the fields used in the
132+
// CAPI e2e owner comparison funcs are used in the comparison here to assert equality.
133+
func dedupeOwners(owners []metav1.OwnerReference) []metav1.OwnerReference {
134+
return slices.CompactFunc(owners, func(a, b metav1.OwnerReference) bool {
135+
return a.APIVersion == b.APIVersion && a.Kind == b.Kind &&
136+
ptr.Equal(a.Controller, b.Controller)
137+
})
138+
}
139+
140+
// clusterResourceSetBindingIsOnlyOwnedByClusterResourceSets returns a function that checks that the passed
141+
// OwnerReferences are as expected, which means only owned by ClusterResourceSets and not by any other kinds.
142+
func clusterResourceSetBindingIsOnlyOwnedByClusterResourceSets(
143+
gotOwners []metav1.OwnerReference,
144+
) error {
145+
return framework.HasExactOwners(dedupeOwners(gotOwners), clusterResourceSetOwner)
146+
}

test/e2e/quick_start_test.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
. "github.com/onsi/ginkgo/v2"
1414
. "github.com/onsi/gomega"
1515
"k8s.io/utils/ptr"
16-
"sigs.k8s.io/cluster-api/test/e2e"
16+
capie2e "sigs.k8s.io/cluster-api/test/e2e"
1717
"sigs.k8s.io/cluster-api/test/framework"
1818

1919
"github.com/d2iq-labs/capi-runtime-extensions/api/v1alpha1"
@@ -23,6 +23,7 @@ import (
2323

2424
var _ = Describe("Quick start", Serial, func() {
2525
for _, provider := range []string{"Docker", "AWS"} {
26+
lowercaseProvider := strings.ToLower(provider)
2627
for _, cniProvider := range []string{"Cilium", "Calico"} {
2728
for _, addonStrategy := range []string{"HelmAddon", "ClusterResourceSet"} {
2829
strategy := ""
@@ -47,20 +48,25 @@ var _ = Describe("Quick start", Serial, func() {
4748
Label("cni:"+cniProvider),
4849
Label("addonStrategy:"+addonStrategy),
4950
func() {
50-
e2e.QuickStartSpec(ctx, func() e2e.QuickStartSpecInput {
51-
prov := strings.ToLower(provider)
52-
if !slices.Contains(e2eConfig.InfrastructureProviders(), prov) {
53-
Skip(fmt.Sprintf("provider %s is not enabled", prov))
51+
capie2e.QuickStartSpec(ctx, func() capie2e.QuickStartSpecInput {
52+
if !slices.Contains(
53+
e2eConfig.InfrastructureProviders(),
54+
lowercaseProvider,
55+
) {
56+
Fail(fmt.Sprintf(
57+
"provider %s is not enabled - check environment setup for provider specific requirements",
58+
lowercaseProvider,
59+
))
5460
}
5561

56-
return e2e.QuickStartSpecInput{
62+
return capie2e.QuickStartSpecInput{
5763
E2EConfig: e2eConfig,
5864
ClusterctlConfigPath: clusterctlConfigPath,
5965
BootstrapClusterProxy: bootstrapClusterProxy,
6066
ArtifactFolder: artifactFolder,
6167
SkipCleanup: skipCleanup,
6268
Flavor: ptr.To(flavour),
63-
InfrastructureProvider: ptr.To(prov),
69+
InfrastructureProvider: ptr.To(lowercaseProvider),
6470
PostMachinesProvisioned: func(proxy framework.ClusterProxy, namespace, clusterName string) {
6571
framework.AssertOwnerReferences(
6672
namespace,
@@ -71,6 +77,7 @@ var _ = Describe("Quick start", Serial, func() {
7177
framework.KubeadmBootstrapOwnerReferenceAssertions,
7278
framework.KubeadmControlPlaneOwnerReferenceAssertions,
7379
framework.KubernetesReferenceAssertions,
80+
AWSInfraOwnerReferenceAssertions,
7481
AddonReferenceAssertions,
7582
)
7683

@@ -86,7 +93,7 @@ var _ = Describe("Quick start", Serial, func() {
8693
framework.WaitForNodesReadyInput{
8794
Lister: workloadClient,
8895
KubernetesVersion: e2eConfig.GetVariable(
89-
KubernetesVersion,
96+
capie2e.KubernetesVersion,
9097
),
9198
Count: 2,
9299
WaitForNodesReady: e2eConfig.GetIntervals(

0 commit comments

Comments
 (0)