github.com/operator-framework/operator-lifecycle-manager@v0.30.0/test/e2e/user_defined_sa_test.go (about) 1 package e2e 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 8 "github.com/blang/semver/v4" 9 . "github.com/onsi/ginkgo/v2" 10 . "github.com/onsi/gomega" 11 v1 "github.com/operator-framework/api/pkg/operators/v1" 12 "github.com/operator-framework/api/pkg/operators/v1alpha1" 13 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned" 14 "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" 15 "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac" 16 "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient" 17 "github.com/operator-framework/operator-lifecycle-manager/test/e2e/ctx" 18 "github.com/stretchr/testify/assert" 19 "github.com/stretchr/testify/require" 20 corev1 "k8s.io/api/core/v1" 21 rbacv1 "k8s.io/api/rbac/v1" 22 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 23 apierrors "k8s.io/apimachinery/pkg/api/errors" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 ) 26 27 var _ = Describe("User defined service account", func() { 28 var ( 29 generatedNamespace corev1.Namespace 30 c operatorclient.ClientInterface 31 crc versioned.Interface 32 ) 33 34 BeforeEach(func() { 35 generatedNamespace = corev1.Namespace{ 36 ObjectMeta: metav1.ObjectMeta{ 37 Name: genName("user-defined-sa-e2e-"), 38 }, 39 } 40 Eventually(func() error { 41 return ctx.Ctx().Client().Create(context.Background(), &generatedNamespace) 42 }).Should(Succeed()) 43 44 c = ctx.Ctx().KubeClient() 45 crc = ctx.Ctx().OperatorClient() 46 }) 47 48 AfterEach(func() { 49 TeardownNamespace(generatedNamespace.GetName()) 50 }) 51 52 It("with no permission", func() { 53 54 By("Create a service account, but add no permission to it.") 55 saName := genName("scoped-sa-") 56 _, cleanupSA := newServiceAccount(c, generatedNamespace.GetName(), saName) 57 defer cleanupSA() 58 By("Create token secret for the serviceaccount") 59 _, cleanupSE := newTokenSecret(c, generatedNamespace.GetName(), saName) 60 defer cleanupSE() 61 62 By("Add an OperatorGroup and specify the service account.") 63 ogName := genName("scoped-og-") 64 _, cleanupOG := newOperatorGroupWithServiceAccount(crc, generatedNamespace.GetName(), ogName, saName) 65 defer cleanupOG() 66 67 permissions := deploymentPermissions() 68 catsrc, subSpec, catsrcCleanup := newCatalogSource(GinkgoT(), c, crc, "scoped", generatedNamespace.GetName(), permissions) 69 defer catsrcCleanup() 70 71 By("Ensure that the catalog source is resolved before we create a subscription.") 72 _, err := fetchCatalogSourceOnStatus(crc, catsrc.GetName(), generatedNamespace.GetName(), catalogSourceRegistryPodSynced()) 73 require.NoError(GinkgoT(), err) 74 75 subscriptionName := genName("scoped-sub-") 76 cleanupSubscription := createSubscriptionForCatalog(crc, generatedNamespace.GetName(), subscriptionName, catsrc.GetName(), subSpec.Package, subSpec.Channel, subSpec.StartingCSV, subSpec.InstallPlanApproval) 77 defer cleanupSubscription() 78 79 By("Wait until an install plan is created.") 80 subscription, err := fetchSubscription(crc, generatedNamespace.GetName(), subscriptionName, subscriptionHasInstallPlanChecker()) 81 require.NoError(GinkgoT(), err) 82 require.NotNil(GinkgoT(), subscription) 83 84 By("We expect the InstallPlan to be in status: Installing.") 85 ipName := subscription.Status.Install.Name 86 ipPhaseCheckerFunc := buildInstallPlanMessageCheckFunc(`cannot create resource`) 87 ipGot, err := fetchInstallPlanWithNamespace(GinkgoT(), crc, ipName, generatedNamespace.GetName(), ipPhaseCheckerFunc) 88 require.NoError(GinkgoT(), err) 89 90 By("Verify that all step resources are in Unknown state.") 91 for _, step := range ipGot.Status.Plan { 92 assert.Equal(GinkgoT(), v1alpha1.StepStatusUnknown, step.Status) 93 } 94 }) 95 It("with permission", func() { 96 97 By("Create the CatalogSource") 98 namespace := genName("scoped-ns-") 99 _, cleanupNS := newNamespace(c, namespace) 100 defer cleanupNS() 101 102 By("Create a service account, add enough permission to it so that operator install is successful.") 103 saName := genName("scoped-sa") 104 _, cleanupSA := newServiceAccount(c, generatedNamespace.GetName(), saName) 105 defer cleanupSA() 106 By("Create token secret for the serviceaccount") 107 _, cleanupSE := newTokenSecret(c, generatedNamespace.GetName(), saName) 108 defer cleanupSE() 109 cleanupPerm := grantPermission(GinkgoT(), c, generatedNamespace.GetName(), saName) 110 defer cleanupPerm() 111 112 By("Add an OperatorGroup and specify the service account.") 113 ogName := genName("scoped-og-") 114 _, cleanupOG := newOperatorGroupWithServiceAccount(crc, generatedNamespace.GetName(), ogName, saName) 115 defer cleanupOG() 116 117 permissions := deploymentPermissions() 118 catsrc, subSpec, catsrcCleanup := newCatalogSource(GinkgoT(), c, crc, "scoped", generatedNamespace.GetName(), permissions) 119 defer catsrcCleanup() 120 121 By("Ensure that the catalog source is resolved before we create a subscription.") 122 _, err := fetchCatalogSourceOnStatus(crc, catsrc.GetName(), generatedNamespace.GetName(), catalogSourceRegistryPodSynced()) 123 require.NoError(GinkgoT(), err) 124 125 subscriptionName := genName("scoped-sub-") 126 cleanupSubscription := createSubscriptionForCatalog(crc, generatedNamespace.GetName(), subscriptionName, catsrc.GetName(), subSpec.Package, subSpec.Channel, subSpec.StartingCSV, subSpec.InstallPlanApproval) 127 defer cleanupSubscription() 128 129 By("Wait until an install plan is created.") 130 subscription, err := fetchSubscription(crc, generatedNamespace.GetName(), subscriptionName, subscriptionHasInstallPlanChecker()) 131 require.NoError(GinkgoT(), err) 132 require.NotNil(GinkgoT(), subscription) 133 134 By("We expect the InstallPlan to be in status: Complete.") 135 ipName := subscription.Status.Install.Name 136 ipPhaseCheckerFunc := buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete) 137 ipGot, err := fetchInstallPlanWithNamespace(GinkgoT(), crc, ipName, generatedNamespace.GetName(), ipPhaseCheckerFunc) 138 require.NoError(GinkgoT(), err) 139 140 conditionGot := mustHaveCondition(GinkgoT(), ipGot, v1alpha1.InstallPlanInstalled) 141 assert.Equal(GinkgoT(), v1alpha1.InstallPlanConditionReason(""), conditionGot.Reason) 142 assert.Equal(GinkgoT(), corev1.ConditionTrue, conditionGot.Status) 143 assert.Equal(GinkgoT(), "", conditionGot.Message) 144 145 By("Verify that all step resources are in Created state.") 146 for _, step := range ipGot.Status.Plan { 147 // TODO: switch back to commented assertion once InstallPlan status is being patched instead of updated 148 // assert.Equal(GinkgoT(), v1alpha1.StepStatusCreated, step.Status) 149 Expect(step.Status).To(Or(Equal(v1alpha1.StepStatusCreated), Equal(v1alpha1.StepStatusPresent))) 150 } 151 }) 152 It("with retry", func() { 153 154 By("Create a service account, but add no permission to it.") 155 saName := genName("scoped-sa-") 156 _, cleanupSA := newServiceAccount(c, generatedNamespace.GetName(), saName) 157 defer cleanupSA() 158 By("Create token secret for the serviceaccount") 159 _, cleanupSE := newTokenSecret(c, generatedNamespace.GetName(), saName) 160 defer cleanupSE() 161 162 By("Add an OperatorGroup and specify the service account.") 163 ogName := genName("scoped-og-") 164 _, cleanupOG := newOperatorGroupWithServiceAccount(crc, generatedNamespace.GetName(), ogName, saName) 165 defer cleanupOG() 166 167 permissions := deploymentPermissions() 168 catsrc, subSpec, catsrcCleanup := newCatalogSource(GinkgoT(), c, crc, "scoped", generatedNamespace.GetName(), permissions) 169 defer catsrcCleanup() 170 171 By("Ensure that the catalog source is resolved before we create a subscription.") 172 _, err := fetchCatalogSourceOnStatus(crc, catsrc.GetName(), generatedNamespace.GetName(), catalogSourceRegistryPodSynced()) 173 require.NoError(GinkgoT(), err) 174 175 subscriptionName := genName("scoped-sub-") 176 cleanupSubscription := createSubscriptionForCatalog(crc, generatedNamespace.GetName(), subscriptionName, catsrc.GetName(), subSpec.Package, subSpec.Channel, subSpec.StartingCSV, subSpec.InstallPlanApproval) 177 defer cleanupSubscription() 178 179 By("Wait until an install plan is created.") 180 subscription, err := fetchSubscription(crc, generatedNamespace.GetName(), subscriptionName, subscriptionHasInstallPlanChecker()) 181 require.NoError(GinkgoT(), err) 182 require.NotNil(GinkgoT(), subscription) 183 184 By("We expect the InstallPlan to expose the permissions error.") 185 ipNameOld := subscription.Status.InstallPlanRef.Name 186 ipPhaseCheckerFunc := buildInstallPlanMessageCheckFunc(`cannot create resource "clusterserviceversions" in API group "operators.coreos.com" in the namespace`) 187 _, err = fetchInstallPlanWithNamespace(GinkgoT(), crc, ipNameOld, generatedNamespace.GetName(), ipPhaseCheckerFunc) 188 require.NoError(GinkgoT(), err) 189 190 By("Grant permission now and this should trigger an retry of InstallPlan.") 191 cleanupPerm := grantPermission(GinkgoT(), c, generatedNamespace.GetName(), saName) 192 defer cleanupPerm() 193 194 ipPhaseCheckerFunc = buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete) 195 ipGotNew, err := fetchInstallPlanWithNamespace(GinkgoT(), crc, ipNameOld, generatedNamespace.GetName(), ipPhaseCheckerFunc) 196 require.NoError(GinkgoT(), err) 197 require.Equal(GinkgoT(), v1alpha1.InstallPlanPhaseComplete, ipGotNew.Status.Phase) 198 }) 199 }) 200 201 func newNamespace(client operatorclient.ClientInterface, name string) (ns *corev1.Namespace, cleanup cleanupFunc) { 202 request := &corev1.Namespace{ 203 ObjectMeta: metav1.ObjectMeta{ 204 Name: name, 205 }, 206 } 207 208 Eventually(func() (err error) { 209 ns, err = client.KubernetesInterface().CoreV1().Namespaces().Create(context.TODO(), request, metav1.CreateOptions{}) 210 return 211 }).Should(Succeed()) 212 213 cleanup = func() { 214 Eventually(func() error { 215 err := client.KubernetesInterface().CoreV1().Namespaces().Delete(context.TODO(), ns.GetName(), metav1.DeleteOptions{}) 216 if apierrors.IsNotFound(err) { 217 err = nil 218 } 219 220 return err 221 }).Should(Succeed()) 222 } 223 224 return 225 } 226 227 func newServiceAccount(client operatorclient.ClientInterface, namespace, name string) (sa *corev1.ServiceAccount, cleanup cleanupFunc) { 228 request := &corev1.ServiceAccount{ 229 ObjectMeta: metav1.ObjectMeta{ 230 Namespace: namespace, 231 Name: name, 232 }, 233 } 234 235 sa, err := client.KubernetesInterface().CoreV1().ServiceAccounts(namespace).Create(context.TODO(), request, metav1.CreateOptions{}) 236 Expect(err).ToNot(HaveOccurred()) 237 Expect(sa).ToNot(BeNil()) 238 239 cleanup = func() { 240 if env := os.Getenv("SKIP_CLEANUP"); env != "" { 241 fmt.Printf("Skipping cleanup of service account %s/%s...\n", sa.GetNamespace(), sa.GetName()) 242 return 243 } 244 err := client.KubernetesInterface().CoreV1().ServiceAccounts(sa.GetNamespace()).Delete(context.TODO(), sa.GetName(), metav1.DeleteOptions{}) 245 Expect(err).ToNot(HaveOccurred()) 246 } 247 248 return 249 } 250 251 func newOperatorGroupWithServiceAccount(client versioned.Interface, namespace, name, serviceAccountName string) (og *v1.OperatorGroup, cleanup cleanupFunc) { 252 request := &v1.OperatorGroup{ 253 ObjectMeta: metav1.ObjectMeta{ 254 Namespace: namespace, 255 Name: name, 256 }, 257 Spec: v1.OperatorGroupSpec{ 258 TargetNamespaces: []string{ 259 namespace, 260 }, 261 ServiceAccountName: serviceAccountName, 262 }, 263 } 264 265 og, err := client.OperatorsV1().OperatorGroups(namespace).Create(context.TODO(), request, metav1.CreateOptions{}) 266 Expect(err).ToNot(HaveOccurred()) 267 Expect(og).ToNot(BeNil()) 268 269 cleanup = func() { 270 if env := os.Getenv("SKIP_CLEANUP"); env != "" { 271 fmt.Printf("Skipping cleanup of operator group %s/%s...\n", og.GetNamespace(), og.GetName()) 272 return 273 } 274 err := client.OperatorsV1().OperatorGroups(og.GetNamespace()).Delete(context.TODO(), og.GetName(), metav1.DeleteOptions{}) 275 Expect(err).ToNot(HaveOccurred()) 276 } 277 278 return 279 } 280 281 func newCatalogSource(t GinkgoTInterface, kubeclient operatorclient.ClientInterface, crclient versioned.Interface, prefix, namespace string, permissions []v1alpha1.StrategyDeploymentPermissions) (catsrc *v1alpha1.CatalogSource, subscriptionSpec *v1alpha1.SubscriptionSpec, cleanup cleanupFunc) { 282 crdPlural := genName("ins") 283 crdName := crdPlural + ".cluster.com" 284 285 crd := apiextensionsv1.CustomResourceDefinition{ 286 ObjectMeta: metav1.ObjectMeta{ 287 Name: crdName, 288 }, 289 Spec: apiextensionsv1.CustomResourceDefinitionSpec{ 290 Group: "cluster.com", 291 Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ 292 { 293 Name: "v1alpha1", 294 Served: true, 295 Storage: true, 296 Schema: &apiextensionsv1.CustomResourceValidation{ 297 OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ 298 Type: "object", 299 Description: "my crd schema", 300 }, 301 }, 302 }, 303 }, 304 Names: apiextensionsv1.CustomResourceDefinitionNames{ 305 Plural: crdPlural, 306 Singular: crdPlural, 307 Kind: crdPlural, 308 ListKind: "list" + crdPlural, 309 }, 310 Scope: apiextensionsv1.NamespaceScoped, 311 }, 312 } 313 314 prefixFunc := func(s string) string { 315 return fmt.Sprintf("%s-%s-", prefix, s) 316 } 317 318 // Create CSV 319 packageName := genName(prefixFunc("package")) 320 stableChannel := "stable" 321 322 namedStrategy := newNginxInstallStrategy(genName(prefixFunc("dep")), permissions, nil) 323 csvA := newCSV("nginx-a", namespace, "", semver.MustParse("0.1.0"), []apiextensionsv1.CustomResourceDefinition{crd}, nil, &namedStrategy) 324 csvB := newCSV("nginx-b", namespace, "nginx-a", semver.MustParse("0.2.0"), []apiextensionsv1.CustomResourceDefinition{crd}, nil, &namedStrategy) 325 326 // Create PackageManifests 327 manifests := []registry.PackageManifest{ 328 { 329 PackageName: packageName, 330 Channels: []registry.PackageChannel{ 331 {Name: stableChannel, CurrentCSVName: csvB.GetName()}, 332 }, 333 DefaultChannelName: stableChannel, 334 }, 335 } 336 337 catalogSourceName := genName(prefixFunc("catsrc")) 338 catsrc, cleanup = createInternalCatalogSource(kubeclient, crclient, catalogSourceName, namespace, manifests, []apiextensionsv1.CustomResourceDefinition{crd}, []v1alpha1.ClusterServiceVersion{csvA, csvB}) 339 require.NotNil(t, catsrc) 340 require.NotNil(t, cleanup) 341 342 subscriptionSpec = &v1alpha1.SubscriptionSpec{ 343 CatalogSource: catsrc.GetName(), 344 CatalogSourceNamespace: catsrc.GetNamespace(), 345 Package: packageName, 346 Channel: stableChannel, 347 StartingCSV: csvB.GetName(), 348 InstallPlanApproval: v1alpha1.ApprovalAutomatic, 349 } 350 return 351 } 352 353 func newCatalogSourceWithDependencies(t GinkgoTInterface, kubeclient operatorclient.ClientInterface, crclient versioned.Interface, prefix, namespace string, permissions []v1alpha1.StrategyDeploymentPermissions) (catsrc *v1alpha1.CatalogSource, subscriptionSpec *v1alpha1.SubscriptionSpec, cleanup cleanupFunc) { 354 crdPlural := genName("ins") 355 crdName := crdPlural + ".cluster.com" 356 357 crd := apiextensionsv1.CustomResourceDefinition{ 358 ObjectMeta: metav1.ObjectMeta{ 359 Name: crdName, 360 }, 361 Spec: apiextensionsv1.CustomResourceDefinitionSpec{ 362 Group: "cluster.com", 363 Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ 364 { 365 Name: "v1alpha1", 366 Served: true, 367 Storage: true, 368 Schema: &apiextensionsv1.CustomResourceValidation{ 369 OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ 370 Type: "object", 371 Description: "my crd schema", 372 }, 373 }, 374 }, 375 }, 376 Names: apiextensionsv1.CustomResourceDefinitionNames{ 377 Plural: crdPlural, 378 Singular: crdPlural, 379 Kind: crdPlural, 380 ListKind: "list" + crdPlural, 381 }, 382 Scope: apiextensionsv1.NamespaceScoped, 383 }, 384 } 385 386 prefixFunc := func(s string) string { 387 return fmt.Sprintf("%s-%s-", prefix, s) 388 } 389 390 // Create CSV 391 packageName1 := genName(prefixFunc("package")) 392 packageName2 := genName(prefixFunc("package")) 393 stableChannel := "stable" 394 395 namedStrategy := newNginxInstallStrategy(genName(prefixFunc("dep")), permissions, nil) 396 csvA := newCSV("nginx-req-dep", namespace, "", semver.MustParse("0.1.0"), nil, []apiextensionsv1.CustomResourceDefinition{crd}, &namedStrategy) 397 csvB := newCSV("nginx-dependency", namespace, "", semver.MustParse("0.1.0"), []apiextensionsv1.CustomResourceDefinition{crd}, nil, &namedStrategy) 398 399 // Create PackageManifests 400 manifests := []registry.PackageManifest{ 401 { 402 PackageName: packageName1, 403 Channels: []registry.PackageChannel{ 404 {Name: stableChannel, CurrentCSVName: csvA.GetName()}, 405 }, 406 DefaultChannelName: stableChannel, 407 }, 408 { 409 PackageName: packageName2, 410 Channels: []registry.PackageChannel{ 411 {Name: stableChannel, CurrentCSVName: csvB.GetName()}, 412 }, 413 DefaultChannelName: stableChannel, 414 }, 415 } 416 417 catalogSourceName := genName(prefixFunc("catsrc")) 418 catsrc, cleanup = createInternalCatalogSource(kubeclient, crclient, catalogSourceName, namespace, manifests, []apiextensionsv1.CustomResourceDefinition{crd}, []v1alpha1.ClusterServiceVersion{csvA, csvB}) 419 require.NotNil(t, catsrc) 420 require.NotNil(t, cleanup) 421 422 subscriptionSpec = &v1alpha1.SubscriptionSpec{ 423 CatalogSource: catsrc.GetName(), 424 CatalogSourceNamespace: catsrc.GetNamespace(), 425 Package: packageName1, 426 Channel: stableChannel, 427 StartingCSV: csvA.GetName(), 428 InstallPlanApproval: v1alpha1.ApprovalAutomatic, 429 } 430 return 431 } 432 433 func mustHaveCondition(t GinkgoTInterface, ip *v1alpha1.InstallPlan, conditionType v1alpha1.InstallPlanConditionType) (condition *v1alpha1.InstallPlanCondition) { 434 for i := range ip.Status.Conditions { 435 if ip.Status.Conditions[i].Type == conditionType { 436 condition = &ip.Status.Conditions[i] 437 break 438 } 439 } 440 441 require.NotNil(t, condition) 442 return 443 } 444 445 func deploymentPermissions() []v1alpha1.StrategyDeploymentPermissions { 446 // Generate permissions 447 serviceAccountName := genName("nginx-sa-") 448 permissions := []v1alpha1.StrategyDeploymentPermissions{ 449 { 450 ServiceAccountName: serviceAccountName, 451 Rules: []rbacv1.PolicyRule{ 452 { 453 Verbs: []string{rbac.VerbAll}, 454 APIGroups: []string{rbac.APIGroupAll}, 455 Resources: []string{rbac.ResourceAll}}, 456 }, 457 }, 458 } 459 460 return permissions 461 } 462 463 func grantPermission(t GinkgoTInterface, client operatorclient.ClientInterface, namespace, serviceAccountName string) (cleanup cleanupFunc) { 464 role := &rbacv1.Role{ 465 ObjectMeta: metav1.ObjectMeta{ 466 Name: genName("scoped-role-"), 467 Namespace: namespace, 468 }, 469 Rules: []rbacv1.PolicyRule{ 470 { 471 Verbs: []string{rbac.VerbAll}, 472 APIGroups: []string{rbac.APIGroupAll}, 473 Resources: []string{rbac.ResourceAll}, 474 }, 475 }, 476 } 477 478 role, err := client.KubernetesInterface().RbacV1().Roles(namespace).Create(context.TODO(), role, metav1.CreateOptions{}) 479 require.NoError(t, err) 480 481 clusterrole := &rbacv1.ClusterRole{ 482 ObjectMeta: metav1.ObjectMeta{ 483 Name: genName("scoped-clusterrole-"), 484 Namespace: namespace}, 485 Rules: []rbacv1.PolicyRule{ 486 { 487 Verbs: []string{rbac.VerbAll}, 488 APIGroups: []string{rbac.APIGroupAll}, 489 Resources: []string{rbac.ResourceAll}, 490 }, 491 }, 492 } 493 494 clusterrole, err = client.KubernetesInterface().RbacV1().ClusterRoles().Create(context.TODO(), clusterrole, metav1.CreateOptions{}) 495 require.NoError(t, err) 496 497 binding := &rbacv1.RoleBinding{ 498 ObjectMeta: metav1.ObjectMeta{ 499 Name: genName("scoped-rolebinding-"), 500 Namespace: namespace, 501 }, 502 Subjects: []rbacv1.Subject{ 503 { 504 Kind: "ServiceAccount", 505 APIGroup: "", 506 Name: serviceAccountName, 507 Namespace: namespace, 508 }, 509 }, 510 RoleRef: rbacv1.RoleRef{ 511 APIGroup: "rbac.authorization.k8s.io", 512 Kind: "Role", 513 Name: role.GetName(), 514 }, 515 } 516 517 clusterbinding := &rbacv1.ClusterRoleBinding{ 518 ObjectMeta: metav1.ObjectMeta{ 519 Name: genName("scoped-clusterrolebinding-"), 520 Namespace: namespace, 521 }, 522 Subjects: []rbacv1.Subject{ 523 { 524 Kind: "ServiceAccount", 525 APIGroup: "", 526 Name: serviceAccountName, 527 Namespace: namespace, 528 }, 529 }, 530 RoleRef: rbacv1.RoleRef{ 531 APIGroup: "rbac.authorization.k8s.io", 532 Kind: "ClusterRole", 533 Name: clusterrole.GetName(), 534 }, 535 } 536 537 binding, err = client.KubernetesInterface().RbacV1().RoleBindings(namespace).Create(context.TODO(), binding, metav1.CreateOptions{}) 538 require.NoError(t, err) 539 540 clusterbinding, err = client.KubernetesInterface().RbacV1().ClusterRoleBindings().Create(context.TODO(), clusterbinding, metav1.CreateOptions{}) 541 require.NoError(t, err) 542 543 cleanup = func() { 544 if env := os.Getenv("SKIP_CLEANUP"); env != "" { 545 fmt.Printf("Skipping cleanup of role %s/%s...\n", role.GetNamespace(), role.GetName()) 546 fmt.Printf("Skipping cleanup of role binding %s/%s...\n", binding.GetNamespace(), binding.GetName()) 547 fmt.Printf("Skipping cleanup of cluster role %s...\n", clusterrole.GetName()) 548 fmt.Printf("Skipping cleanup of cluster role binding %s...\n", clusterbinding.GetName()) 549 return 550 } 551 552 err := client.KubernetesInterface().RbacV1().Roles(role.GetNamespace()).Delete(context.TODO(), role.GetName(), metav1.DeleteOptions{}) 553 require.NoError(t, err) 554 555 err = client.KubernetesInterface().RbacV1().RoleBindings(binding.GetNamespace()).Delete(context.TODO(), binding.GetName(), metav1.DeleteOptions{}) 556 require.NoError(t, err) 557 558 err = client.KubernetesInterface().RbacV1().ClusterRoles().Delete(context.TODO(), clusterrole.GetName(), metav1.DeleteOptions{}) 559 require.NoError(t, err) 560 561 err = client.KubernetesInterface().RbacV1().ClusterRoleBindings().Delete(context.TODO(), clusterbinding.GetName(), metav1.DeleteOptions{}) 562 require.NoError(t, err) 563 } 564 565 return 566 }