@@ -17,12 +17,14 @@ import (
17
17
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18
18
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
19
19
"k8s.io/apimachinery/pkg/util/wait"
20
+ "k8s.io/apimachinery/pkg/watch"
20
21
"k8s.io/kubernetes/pkg/apis/rbac"
21
22
22
23
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
23
24
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
24
25
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
25
26
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry"
27
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
26
28
opver "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/version"
27
29
)
28
30
@@ -1449,6 +1451,96 @@ func TestCreateInstallPlanWithPermissions(t *testing.T) {
1449
1451
1450
1452
// Should have removed every matching step
1451
1453
require .Equal (t , 0 , len (expectedSteps ), "Actual resource steps do not match expected: %#v" , expectedSteps )
1454
+
1455
+ // the test from here out verifies created RBAC is removed after CSV deletion
1456
+ createdClusterRoles , err := c .KubernetesInterface ().RbacV1 ().ClusterRoles ().List (metav1.ListOptions {LabelSelector : fmt .Sprintf ("%v=%v" , ownerutil .OwnerKey , stableCSVName )})
1457
+ createdClusterRoleNames := map [string ]struct {}{}
1458
+ for _ , role := range createdClusterRoles .Items {
1459
+ createdClusterRoleNames [role .GetName ()] = struct {}{}
1460
+ t .Logf ("Monitoring cluster role %v" , role .GetName ())
1461
+ }
1462
+
1463
+ createdClusterRoleBindings , err := c .KubernetesInterface ().RbacV1 ().ClusterRoleBindings ().List (metav1.ListOptions {LabelSelector : fmt .Sprintf ("%v=%v" , ownerutil .OwnerKey , stableCSVName )})
1464
+ createdClusterRoleBindingNames := map [string ]struct {}{}
1465
+ for _ , binding := range createdClusterRoleBindings .Items {
1466
+ createdClusterRoleBindingNames [binding .GetName ()] = struct {}{}
1467
+ t .Logf ("Monitoring cluster role binding %v" , binding .GetName ())
1468
+ }
1469
+
1470
+ // can't query by owner reference, so just use the name we know is in the install plan
1471
+ createdServiceAccountNames := map [string ]struct {}{serviceAccountName : struct {}{}}
1472
+ t .Logf ("Monitoring service account %v" , serviceAccountName )
1473
+
1474
+ crWatcher , err := c .KubernetesInterface ().RbacV1 ().ClusterRoles ().Watch (metav1.ListOptions {LabelSelector : fmt .Sprintf ("%v=%v" , ownerutil .OwnerKey , stableCSVName )})
1475
+ require .NoError (t , err )
1476
+ crbWatcher , err := c .KubernetesInterface ().RbacV1 ().ClusterRoleBindings ().Watch (metav1.ListOptions {LabelSelector : fmt .Sprintf ("%v=%v" , ownerutil .OwnerKey , stableCSVName )})
1477
+ require .NoError (t , err )
1478
+ saWatcher , err := c .KubernetesInterface ().CoreV1 ().ServiceAccounts (testNamespace ).Watch (metav1.ListOptions {})
1479
+ require .NoError (t , err )
1480
+
1481
+ done := make (chan struct {})
1482
+ quit := make (chan struct {})
1483
+ defer close (quit )
1484
+ go func () {
1485
+ for {
1486
+ select {
1487
+ case <- quit :
1488
+ return
1489
+ case evt , ok := <- crWatcher .ResultChan ():
1490
+ if ! ok {
1491
+ t .Fatal ("cr watch channel closed unexpectedly" )
1492
+ }
1493
+ if evt .Type == watch .Deleted {
1494
+ cr , ok := evt .Object .(* rbacv1.ClusterRole )
1495
+ if ! ok {
1496
+ continue
1497
+ }
1498
+ delete (createdClusterRoleNames , cr .GetName ())
1499
+ if len (createdClusterRoleNames ) == 0 && len (createdClusterRoleBindingNames ) == 0 && len (createdServiceAccountNames ) == 0 {
1500
+ done <- struct {}{}
1501
+ }
1502
+ }
1503
+ case evt , ok := <- crbWatcher .ResultChan ():
1504
+ if ! ok {
1505
+ t .Fatal ("crb watch channel closed unexpectedly" )
1506
+ }
1507
+ if evt .Type == watch .Deleted {
1508
+ crb , ok := evt .Object .(* rbacv1.ClusterRoleBinding )
1509
+ if ! ok {
1510
+ continue
1511
+ }
1512
+ delete (createdClusterRoleBindingNames , crb .GetName ())
1513
+ if len (createdClusterRoleNames ) == 0 && len (createdClusterRoleBindingNames ) == 0 && len (createdServiceAccountNames ) == 0 {
1514
+ done <- struct {}{}
1515
+ }
1516
+ }
1517
+ case evt , ok := <- saWatcher .ResultChan ():
1518
+ if ! ok {
1519
+ t .Fatal ("sa watch channel closed unexpectedly" )
1520
+ }
1521
+ if evt .Type == watch .Deleted {
1522
+ sa , ok := evt .Object .(* corev1.ServiceAccount )
1523
+ if ! ok {
1524
+ continue
1525
+ }
1526
+ delete (createdServiceAccountNames , sa .GetName ())
1527
+ if len (createdClusterRoleNames ) == 0 && len (createdClusterRoleBindingNames ) == 0 && len (createdServiceAccountNames ) == 0 {
1528
+ done <- struct {}{}
1529
+ }
1530
+ }
1531
+ case <- time .After (pollDuration ):
1532
+ done <- struct {}{}
1533
+ }
1534
+ }
1535
+ }()
1536
+
1537
+ t .Logf ("Deleting CSV '%v' in namespace %v" , stableCSVName , testNamespace )
1538
+ require .NoError (t , crc .OperatorsV1alpha1 ().ClusterServiceVersions (testNamespace ).DeleteCollection (& metav1.DeleteOptions {}, metav1.ListOptions {}))
1539
+ <- done
1540
+
1541
+ require .Emptyf (t , createdClusterRoleNames , "unexpected cluster role remain: %v" , createdClusterRoleNames )
1542
+ require .Emptyf (t , createdClusterRoleBindingNames , "unexpected cluster role binding remain: %v" , createdClusterRoleBindingNames )
1543
+ require .Emptyf (t , createdServiceAccountNames , "unexpected service account remain: %v" , createdServiceAccountNames )
1452
1544
}
1453
1545
1454
1546
func TestInstallPlanCRDValidation (t * testing.T ) {
0 commit comments