Skip to content

Commit 10ab78d

Browse files
authored
Use a separate namespace for each e2e test (#1428)
Fixes #1307 Create and use a new namespace for every e2e test. This means that extension resources are placed in their own namespace. The tests deletes the namespace, and then waits until completion. This ensures that _most_ of an extension's resources are deleted. It does guarantee that global resources (e.g. CRDs, CRs, CRBs) are deleted. And would eventually allow the tests to be run in parallel (assuming the installed extensions allow for that). Signed-off-by: Todd Short <[email protected]>
1 parent f68f3f4 commit 10ab78d

File tree

2 files changed

+105
-37
lines changed

2 files changed

+105
-37
lines changed

test/e2e/cluster_extension_install_test.go

Lines changed: 103 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ import (
1717
appsv1 "k8s.io/api/apps/v1"
1818
corev1 "k8s.io/api/core/v1"
1919
rbacv1 "k8s.io/api/rbac/v1"
20+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2021
"k8s.io/apimachinery/pkg/api/errors"
2122
apimeta "k8s.io/apimachinery/pkg/api/meta"
2223
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
"k8s.io/apimachinery/pkg/labels"
2325
"k8s.io/apimachinery/pkg/types"
2426
"k8s.io/apimachinery/pkg/util/rand"
2527
kubeclient "k8s.io/client-go/kubernetes"
@@ -38,6 +40,19 @@ const (
3840
var pollDuration = time.Minute
3941
var pollInterval = time.Second
4042

43+
func createNamespace(ctx context.Context, name string) (*corev1.Namespace, error) {
44+
ns := &corev1.Namespace{
45+
ObjectMeta: metav1.ObjectMeta{
46+
Name: name,
47+
},
48+
}
49+
err := c.Create(ctx, ns)
50+
if err != nil {
51+
return nil, err
52+
}
53+
return ns, nil
54+
}
55+
4156
func createServiceAccount(ctx context.Context, name types.NamespacedName, clusterExtensionName string) (*corev1.ServiceAccount, error) {
4257
sa := &corev1.ServiceAccount{
4358
ObjectMeta: metav1.ObjectMeta{
@@ -177,44 +192,93 @@ func createClusterRoleAndBindingForSA(ctx context.Context, name string, sa *core
177192
return nil
178193
}
179194

180-
func testInit(t *testing.T) (*ocv1alpha1.ClusterExtension, *catalogd.ClusterCatalog, *corev1.ServiceAccount) {
195+
func testInit(t *testing.T) (*ocv1alpha1.ClusterExtension, *catalogd.ClusterCatalog, *corev1.ServiceAccount, *corev1.Namespace) {
181196
var err error
182-
extensionCatalog, err := createTestCatalog(context.Background(), testCatalogName, os.Getenv(testCatalogRefEnvVar))
183-
require.NoError(t, err)
184197

185198
clusterExtensionName := fmt.Sprintf("clusterextension-%s", rand.String(8))
199+
200+
ns, err := createNamespace(context.Background(), clusterExtensionName)
201+
require.NoError(t, err)
202+
186203
clusterExtension := &ocv1alpha1.ClusterExtension{
187204
ObjectMeta: metav1.ObjectMeta{
188205
Name: clusterExtensionName,
189206
},
190207
}
191208

192-
defaultNamespace := types.NamespacedName{
209+
extensionCatalog, err := createTestCatalog(context.Background(), testCatalogName, os.Getenv(testCatalogRefEnvVar))
210+
require.NoError(t, err)
211+
212+
name := types.NamespacedName{
193213
Name: clusterExtensionName,
194-
Namespace: "default",
214+
Namespace: ns.GetName(),
195215
}
196216

197-
sa, err := createServiceAccount(context.Background(), defaultNamespace, clusterExtensionName)
217+
sa, err := createServiceAccount(context.Background(), name, clusterExtensionName)
198218
require.NoError(t, err)
199-
return clusterExtension, extensionCatalog, sa
219+
return clusterExtension, extensionCatalog, sa, ns
200220
}
201221

202-
func testCleanup(t *testing.T, cat *catalogd.ClusterCatalog, clusterExtension *ocv1alpha1.ClusterExtension, sa *corev1.ServiceAccount) {
222+
func ensureNoExtensionResources(t *testing.T, clusterExtensionName string) {
223+
ls := labels.Set{"olm.operatorframework.io/owner-name": clusterExtensionName}
224+
225+
// CRDs may take an extra long time to be deleted, and may run into the following error:
226+
// Condition=Terminating Status=True Reason=InstanceDeletionFailed Message="could not list instances: storage is (re)initializing"
227+
t.Logf("By waiting for CustomResourceDefinitions of %q to be deleted", clusterExtensionName)
228+
require.EventuallyWithT(t, func(ct *assert.CollectT) {
229+
list := &apiextensionsv1.CustomResourceDefinitionList{}
230+
err := c.List(context.Background(), list, client.MatchingLabelsSelector{Selector: ls.AsSelector()})
231+
assert.NoError(ct, err)
232+
assert.Empty(ct, list.Items)
233+
}, 5*pollDuration, pollInterval)
234+
235+
t.Logf("By waiting for ClusterRoleBindings of %q to be deleted", clusterExtensionName)
236+
require.EventuallyWithT(t, func(ct *assert.CollectT) {
237+
list := &rbacv1.ClusterRoleBindingList{}
238+
err := c.List(context.Background(), list, client.MatchingLabelsSelector{Selector: ls.AsSelector()})
239+
assert.NoError(ct, err)
240+
assert.Empty(ct, list.Items)
241+
}, 2*pollDuration, pollInterval)
242+
243+
t.Logf("By waiting for ClusterRoles of %q to be deleted", clusterExtensionName)
244+
require.EventuallyWithT(t, func(ct *assert.CollectT) {
245+
list := &rbacv1.ClusterRoleList{}
246+
err := c.List(context.Background(), list, client.MatchingLabelsSelector{Selector: ls.AsSelector()})
247+
assert.NoError(ct, err)
248+
assert.Empty(ct, list.Items)
249+
}, 2*pollDuration, pollInterval)
250+
}
251+
252+
func testCleanup(t *testing.T, cat *catalogd.ClusterCatalog, clusterExtension *ocv1alpha1.ClusterExtension, sa *corev1.ServiceAccount, ns *corev1.Namespace) {
253+
t.Logf("By deleting ClusterCatalog %q", cat.Name)
203254
require.NoError(t, c.Delete(context.Background(), cat))
204255
require.Eventually(t, func() bool {
205256
err := c.Get(context.Background(), types.NamespacedName{Name: cat.Name}, &catalogd.ClusterCatalog{})
206257
return errors.IsNotFound(err)
207258
}, pollDuration, pollInterval)
259+
260+
t.Logf("By deleting ClusterExtension %q", clusterExtension.Name)
208261
require.NoError(t, c.Delete(context.Background(), clusterExtension))
209262
require.Eventually(t, func() bool {
210263
err := c.Get(context.Background(), types.NamespacedName{Name: clusterExtension.Name}, &ocv1alpha1.ClusterExtension{})
211264
return errors.IsNotFound(err)
212265
}, pollDuration, pollInterval)
266+
267+
t.Logf("By deleting ServiceAccount %q", sa.Name)
213268
require.NoError(t, c.Delete(context.Background(), sa))
214269
require.Eventually(t, func() bool {
215270
err := c.Get(context.Background(), types.NamespacedName{Name: sa.Name, Namespace: sa.Namespace}, &corev1.ServiceAccount{})
216271
return errors.IsNotFound(err)
217272
}, pollDuration, pollInterval)
273+
274+
ensureNoExtensionResources(t, clusterExtension.Name)
275+
276+
t.Logf("By deleting Namespace %q", ns.Name)
277+
require.NoError(t, c.Delete(context.Background(), ns))
278+
require.Eventually(t, func() bool {
279+
err := c.Get(context.Background(), types.NamespacedName{Name: ns.Name}, &corev1.Namespace{})
280+
return errors.IsNotFound(err)
281+
}, pollDuration, pollInterval)
218282
}
219283

220284
func TestClusterExtensionInstallRegistry(t *testing.T) {
@@ -240,8 +304,8 @@ func TestClusterExtensionInstallRegistry(t *testing.T) {
240304
t.Log("When a cluster extension is installed from a catalog")
241305
t.Log("When the extension bundle format is registry+v1")
242306

243-
clusterExtension, extensionCatalog, sa := testInit(t)
244-
defer testCleanup(t, extensionCatalog, clusterExtension, sa)
307+
clusterExtension, extensionCatalog, sa, ns := testInit(t)
308+
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
245309
defer getArtifactsOutput(t)
246310

247311
clusterExtension.Spec = ocv1alpha1.ClusterExtensionSpec{
@@ -255,7 +319,7 @@ func TestClusterExtensionInstallRegistry(t *testing.T) {
255319
},
256320
},
257321
Install: ocv1alpha1.ClusterExtensionInstallConfig{
258-
Namespace: "default",
322+
Namespace: ns.Name,
259323
ServiceAccount: ocv1alpha1.ServiceAccountReference{
260324
Name: sa.Name,
261325
},
@@ -298,8 +362,8 @@ func TestClusterExtensionInstallRegistry(t *testing.T) {
298362
func TestClusterExtensionInstallRegistryMultipleBundles(t *testing.T) {
299363
t.Log("When a cluster extension is installed from a catalog")
300364

301-
clusterExtension, extensionCatalog, sa := testInit(t)
302-
defer testCleanup(t, extensionCatalog, clusterExtension, sa)
365+
clusterExtension, extensionCatalog, sa, ns := testInit(t)
366+
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
303367
defer getArtifactsOutput(t)
304368

305369
clusterExtension.Spec = ocv1alpha1.ClusterExtensionSpec{
@@ -310,7 +374,7 @@ func TestClusterExtensionInstallRegistryMultipleBundles(t *testing.T) {
310374
},
311375
},
312376
Install: ocv1alpha1.ClusterExtensionInstallConfig{
313-
Namespace: "default",
377+
Namespace: ns.Name,
314378
ServiceAccount: ocv1alpha1.ServiceAccountReference{
315379
Name: sa.Name,
316380
},
@@ -341,8 +405,8 @@ func TestClusterExtensionBlockInstallNonSuccessorVersion(t *testing.T) {
341405
t.Log("When a cluster extension is installed from a catalog")
342406
t.Log("When resolving upgrade edges")
343407

344-
clusterExtension, extensionCatalog, sa := testInit(t)
345-
defer testCleanup(t, extensionCatalog, clusterExtension, sa)
408+
clusterExtension, extensionCatalog, sa, ns := testInit(t)
409+
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
346410
defer getArtifactsOutput(t)
347411

348412
t.Log("By creating an ClusterExtension at a specified version")
@@ -356,7 +420,7 @@ func TestClusterExtensionBlockInstallNonSuccessorVersion(t *testing.T) {
356420
},
357421
},
358422
Install: ocv1alpha1.ClusterExtensionInstallConfig{
359-
Namespace: "default",
423+
Namespace: ns.Name,
360424
ServiceAccount: ocv1alpha1.ServiceAccountReference{
361425
Name: sa.Name,
362426
},
@@ -406,8 +470,8 @@ func TestClusterExtensionForceInstallNonSuccessorVersion(t *testing.T) {
406470
t.Log("When a cluster extension is installed from a catalog")
407471
t.Log("When resolving upgrade edges")
408472

409-
clusterExtension, extensionCatalog, sa := testInit(t)
410-
defer testCleanup(t, extensionCatalog, clusterExtension, sa)
473+
clusterExtension, extensionCatalog, sa, ns := testInit(t)
474+
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
411475
defer getArtifactsOutput(t)
412476

413477
t.Log("By creating an ClusterExtension at a specified version")
@@ -420,7 +484,7 @@ func TestClusterExtensionForceInstallNonSuccessorVersion(t *testing.T) {
420484
},
421485
},
422486
Install: ocv1alpha1.ClusterExtensionInstallConfig{
423-
Namespace: "default",
487+
Namespace: ns.Name,
424488
ServiceAccount: ocv1alpha1.ServiceAccountReference{
425489
Name: sa.Name,
426490
},
@@ -457,8 +521,8 @@ func TestClusterExtensionForceInstallNonSuccessorVersion(t *testing.T) {
457521
func TestClusterExtensionInstallSuccessorVersion(t *testing.T) {
458522
t.Log("When a cluster extension is installed from a catalog")
459523
t.Log("When resolving upgrade edges")
460-
clusterExtension, extensionCatalog, sa := testInit(t)
461-
defer testCleanup(t, extensionCatalog, clusterExtension, sa)
524+
clusterExtension, extensionCatalog, sa, ns := testInit(t)
525+
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
462526
defer getArtifactsOutput(t)
463527

464528
t.Log("By creating an ClusterExtension at a specified version")
@@ -471,7 +535,7 @@ func TestClusterExtensionInstallSuccessorVersion(t *testing.T) {
471535
},
472536
},
473537
Install: ocv1alpha1.ClusterExtensionInstallConfig{
474-
Namespace: "default",
538+
Namespace: ns.Name,
475539
ServiceAccount: ocv1alpha1.ServiceAccountReference{
476540
Name: sa.Name,
477541
},
@@ -507,8 +571,8 @@ func TestClusterExtensionInstallSuccessorVersion(t *testing.T) {
507571
func TestClusterExtensionInstallReResolvesWhenCatalogIsPatched(t *testing.T) {
508572
t.Log("When a cluster extension is installed from a catalog")
509573
t.Log("It resolves again when a catalog is patched with new ImageRef")
510-
clusterExtension, extensionCatalog, sa := testInit(t)
511-
defer testCleanup(t, extensionCatalog, clusterExtension, sa)
574+
clusterExtension, extensionCatalog, sa, ns := testInit(t)
575+
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
512576
defer getArtifactsOutput(t)
513577

514578
clusterExtension.Spec = ocv1alpha1.ClusterExtensionSpec{
@@ -528,7 +592,7 @@ func TestClusterExtensionInstallReResolvesWhenCatalogIsPatched(t *testing.T) {
528592
},
529593
},
530594
Install: ocv1alpha1.ClusterExtensionInstallConfig{
531-
Namespace: "default",
595+
Namespace: ns.Name,
532596
ServiceAccount: ocv1alpha1.ServiceAccountReference{
533597
Name: sa.Name,
534598
},
@@ -593,9 +657,11 @@ func TestClusterExtensionInstallReResolvesWhenNewCatalog(t *testing.T) {
593657
Name: clusterExtensionName,
594658
},
595659
}
596-
sa, err := createServiceAccount(context.Background(), types.NamespacedName{Name: clusterExtensionName, Namespace: "default"}, clusterExtensionName)
660+
ns, err := createNamespace(context.Background(), clusterExtensionName)
661+
require.NoError(t, err)
662+
sa, err := createServiceAccount(context.Background(), types.NamespacedName{Name: clusterExtensionName, Namespace: ns.Name}, clusterExtensionName)
597663
require.NoError(t, err)
598-
defer testCleanup(t, extensionCatalog, clusterExtension, sa)
664+
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
599665
defer getArtifactsOutput(t)
600666

601667
clusterExtension.Spec = ocv1alpha1.ClusterExtensionSpec{
@@ -609,7 +675,7 @@ func TestClusterExtensionInstallReResolvesWhenNewCatalog(t *testing.T) {
609675
},
610676
},
611677
Install: ocv1alpha1.ClusterExtensionInstallConfig{
612-
Namespace: "default",
678+
Namespace: ns.Name,
613679
ServiceAccount: ocv1alpha1.ServiceAccountReference{
614680
Name: sa.Name,
615681
},
@@ -657,8 +723,8 @@ func TestClusterExtensionInstallReResolvesWhenNewCatalog(t *testing.T) {
657723
func TestClusterExtensionInstallReResolvesWhenManagedContentChanged(t *testing.T) {
658724
t.Log("When a cluster extension is installed from a catalog")
659725
t.Log("It resolves again when managed content is changed")
660-
clusterExtension, extensionCatalog, sa := testInit(t)
661-
defer testCleanup(t, extensionCatalog, clusterExtension, sa)
726+
clusterExtension, extensionCatalog, sa, ns := testInit(t)
727+
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
662728
defer getArtifactsOutput(t)
663729

664730
clusterExtension.Spec = ocv1alpha1.ClusterExtensionSpec{
@@ -672,7 +738,7 @@ func TestClusterExtensionInstallReResolvesWhenManagedContentChanged(t *testing.T
672738
},
673739
},
674740
Install: ocv1alpha1.ClusterExtensionInstallConfig{
675-
Namespace: "default",
741+
Namespace: ns.Name,
676742
ServiceAccount: ocv1alpha1.ServiceAccountReference{
677743
Name: sa.Name,
678744
},
@@ -712,18 +778,18 @@ func TestClusterExtensionRecoversFromInitialInstallFailedWhenFailureFixed(t *tes
712778
t.Log("When a cluster extension is installed from a catalog")
713779
t.Log("When the extension bundle format is registry+v1")
714780

715-
clusterExtension, extensionCatalog, _ := testInit(t)
781+
clusterExtension, extensionCatalog, _, ns := testInit(t)
782+
716783
name := rand.String(10)
717784
sa := &corev1.ServiceAccount{
718785
ObjectMeta: metav1.ObjectMeta{
719786
Name: name,
720-
Namespace: "default",
787+
Namespace: ns.Name,
721788
},
722789
}
723790
err := c.Create(context.Background(), sa)
724791
require.NoError(t, err)
725-
726-
defer testCleanup(t, extensionCatalog, clusterExtension, sa)
792+
defer testCleanup(t, extensionCatalog, clusterExtension, sa, ns)
727793
defer getArtifactsOutput(t)
728794

729795
clusterExtension.Spec = ocv1alpha1.ClusterExtensionSpec{
@@ -737,7 +803,7 @@ func TestClusterExtensionRecoversFromInitialInstallFailedWhenFailureFixed(t *tes
737803
},
738804
},
739805
Install: ocv1alpha1.ClusterExtensionInstallConfig{
740-
Namespace: "default",
806+
Namespace: ns.Name,
741807
ServiceAccount: ocv1alpha1.ServiceAccountReference{
742808
Name: sa.Name,
743809
},

test/e2e/e2e_suite_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"os"
66
"testing"
77

8+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
1011
"k8s.io/client-go/rest"
@@ -32,6 +33,7 @@ func TestMain(m *testing.M) {
3233
cfg = ctrl.GetConfigOrDie()
3334

3435
var err error
36+
utilruntime.Must(apiextensionsv1.AddToScheme(scheme.Scheme))
3537
c, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
3638
utilruntime.Must(err)
3739

0 commit comments

Comments
 (0)