From 1d6057e5ffbca6c42d50c11c80bd84e281f70c23 Mon Sep 17 00:00:00 2001 From: Jimmi Dyson Date: Tue, 19 Mar 2024 16:11:53 +0000 Subject: [PATCH] :seedling: Fix CRS e2e helper with multiple bindings (#10191) * test(e2e): Fix CRS helper with multiple bindings Check the relevant ResourceSetBinding to see if the resource is applied. If multiple ClusterResourceSets match a cluster, the ClusterResourceSetBinding will have multiple bindings and so only the relevant ResourceSetBinding should be checked. * fixup! refactor: Apply review suggestions * fixup! test: Add test for CRS e2e helper --- test/framework/clusterresourceset_helpers.go | 19 ++- .../clusterresourceset_helpers_test.go | 135 ++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 test/framework/clusterresourceset_helpers_test.go diff --git a/test/framework/clusterresourceset_helpers.go b/test/framework/clusterresourceset_helpers.go index 2cadcf6ad848..95343370c86e 100644 --- a/test/framework/clusterresourceset_helpers.go +++ b/test/framework/clusterresourceset_helpers.go @@ -150,10 +150,27 @@ func WaitForClusterResourceSetToApplyResources(ctx context.Context, input WaitFo continue } - if len(binding.Spec.Bindings) == 0 || !binding.Spec.Bindings[0].IsApplied(resource) { + // Check relevant ResourceSetBinding to see if the resource is applied. If no ResourceSetBinding is found for + // the specified ClusterResourceSet, the resource has not applied. + resourceSetBinding := getResourceSetBindingForClusterResourceSet(binding, input.ClusterResourceSet) + if resourceSetBinding == nil || !resourceSetBinding.IsApplied(resource) { return false } } return true }, intervals...).Should(BeTrue()) } + +func getResourceSetBindingForClusterResourceSet( + clusterResourceSetBinding *addonsv1.ClusterResourceSetBinding, clusterResourceSet *addonsv1.ClusterResourceSet, +) *addonsv1.ResourceSetBinding { + if clusterResourceSetBinding == nil || clusterResourceSet == nil { + return nil + } + for _, binding := range clusterResourceSetBinding.Spec.Bindings { + if binding.ClusterResourceSetName == clusterResourceSet.Name { + return binding + } + } + return nil +} diff --git a/test/framework/clusterresourceset_helpers_test.go b/test/framework/clusterresourceset_helpers_test.go new file mode 100644 index 000000000000..57e5d7ce3147 --- /dev/null +++ b/test/framework/clusterresourceset_helpers_test.go @@ -0,0 +1,135 @@ +/* +Copyright 2020 The Kubernetes Authors. + +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 framework + +import ( + "testing" + + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + addonsv1 "sigs.k8s.io/cluster-api/exp/addons/api/v1beta1" +) + +func Test_getResourceSetBindingForClusterResourceSet(t *testing.T) { + tests := []struct { + name string + inputCRSB *addonsv1.ClusterResourceSetBinding + inputCRS *addonsv1.ClusterResourceSet + want *addonsv1.ResourceSetBinding + }{{ + name: "nil inputs", + want: nil, + }, { + name: "nil CRS", + inputCRSB: &addonsv1.ClusterResourceSetBinding{}, + want: nil, + }, { + name: "nil CRSB", + inputCRS: &addonsv1.ClusterResourceSet{}, + want: nil, + }, { + name: "CRSB with no bindings", + inputCRSB: &addonsv1.ClusterResourceSetBinding{}, + inputCRS: &addonsv1.ClusterResourceSet{}, + want: nil, + }, { + name: "CRSB with no matching bindings", + inputCRSB: &addonsv1.ClusterResourceSetBinding{ + Spec: addonsv1.ClusterResourceSetBindingSpec{ + Bindings: []*addonsv1.ResourceSetBinding{ + {ClusterResourceSetName: "bar"}, + }, + }, + }, + inputCRS: &addonsv1.ClusterResourceSet{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, + want: nil, + }, { + name: "CRSB with single matching bindings", + inputCRSB: &addonsv1.ClusterResourceSetBinding{ + Spec: addonsv1.ClusterResourceSetBindingSpec{ + Bindings: []*addonsv1.ResourceSetBinding{ + {ClusterResourceSetName: "foo"}, + }, + }, + }, + inputCRS: &addonsv1.ClusterResourceSet{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, + want: &addonsv1.ResourceSetBinding{ClusterResourceSetName: "foo"}, + }, { + name: "CRSB with multiple bindings with match at index 0", + inputCRSB: &addonsv1.ClusterResourceSetBinding{ + Spec: addonsv1.ClusterResourceSetBindingSpec{ + Bindings: []*addonsv1.ResourceSetBinding{ + {ClusterResourceSetName: "foo"}, + {ClusterResourceSetName: "bar"}, + }, + }, + }, + inputCRS: &addonsv1.ClusterResourceSet{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, + want: &addonsv1.ResourceSetBinding{ClusterResourceSetName: "foo"}, + }, { + name: "CRSB with multiple bindings with match at index 1", + inputCRSB: &addonsv1.ClusterResourceSetBinding{ + Spec: addonsv1.ClusterResourceSetBindingSpec{ + Bindings: []*addonsv1.ResourceSetBinding{ + {ClusterResourceSetName: "bar"}, + {ClusterResourceSetName: "foo"}, + }, + }, + }, + inputCRS: &addonsv1.ClusterResourceSet{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, + want: &addonsv1.ResourceSetBinding{ClusterResourceSetName: "foo"}, + }, { + name: "CRSB with multiple bindings with match at middle index", + inputCRSB: &addonsv1.ClusterResourceSetBinding{ + Spec: addonsv1.ClusterResourceSetBindingSpec{ + Bindings: []*addonsv1.ResourceSetBinding{ + {ClusterResourceSetName: "bar"}, + {ClusterResourceSetName: "foo"}, + {ClusterResourceSetName: "baz"}, + }, + }, + }, + inputCRS: &addonsv1.ClusterResourceSet{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, + want: &addonsv1.ResourceSetBinding{ClusterResourceSetName: "foo"}, + }, { + name: "CRSB with multiple bindings with match at last index", + inputCRSB: &addonsv1.ClusterResourceSetBinding{ + Spec: addonsv1.ClusterResourceSetBindingSpec{ + Bindings: []*addonsv1.ResourceSetBinding{ + {ClusterResourceSetName: "bar"}, + {ClusterResourceSetName: "baz"}, + {ClusterResourceSetName: "foo"}, + }, + }, + }, + inputCRS: &addonsv1.ClusterResourceSet{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, + want: &addonsv1.ResourceSetBinding{ClusterResourceSetName: "foo"}, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + + g.Expect( + getResourceSetBindingForClusterResourceSet( + tt.inputCRSB, + tt.inputCRS, + ), + ).To(Equal(tt.want)) + }) + } +}