github.com/verrazzano/verrazzano@v1.7.0/cluster-operator/internal/operatorinit/run_operator_test.go (about) 1 // Copyright (c) 2022, 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package operatorinit 5 6 import ( 7 "context" 8 "os" 9 "strconv" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 "go.uber.org/zap" 14 apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 15 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake" 16 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 17 ) 18 19 // TestShouldSyncClusters tests the shouldSyncClusters function 20 func TestShouldSyncClusters(t *testing.T) { 21 asserts := assert.New(t) 22 23 // when this test is done, reset the cluster sync env var 24 envValue, envValueExists := os.LookupEnv(syncClustersEnvVarName) 25 defer func() { 26 if envValueExists { 27 os.Setenv(syncClustersEnvVarName, envValue) 28 } else { 29 os.Unsetenv(syncClustersEnvVarName) 30 } 31 }() 32 33 var tests = []struct { 34 testName string 35 enabled bool 36 clusterSelectorText string 37 expectedLabelSelector *metav1.LabelSelector 38 expectedError bool 39 }{ 40 // GIVEN cluster sync is disabled 41 // WHEN shouldSyncClusters is called 42 // THEN the call returns that cluster sync is disabled, a nil label selector, and no error 43 { 44 "Sync Rancher clusters is disabled", 45 false, 46 "", 47 nil, 48 false, 49 }, 50 // GIVEN cluster sync is enabled and no label selector yaml is provided 51 // WHEN shouldSyncClusters is called 52 // THEN the call returns that cluster sync is enabled, a nil label selector, and no error 53 { 54 "Sync Rancher clusters is enabled, no label selector specified", 55 true, 56 "", 57 nil, 58 false, 59 }, 60 // GIVEN cluster sync is enabled and a label selector yaml is provided 61 // WHEN shouldSyncClusters is called 62 // THEN the call returns that cluster sync is enabled, a populated label selector, and no error 63 { 64 "Sync Rancher clusters is enabled, simple label selector specified", 65 true, 66 "matchLabels:\n foo: bar\n", 67 &metav1.LabelSelector{ 68 MatchLabels: map[string]string{"foo": "bar"}, 69 }, 70 false, 71 }, 72 // GIVEN cluster sync is enabled and a more complex label selector yaml is provided 73 // WHEN shouldSyncClusters is called 74 // THEN the call returns that cluster sync is enabled, a populated label selector, and no error 75 { 76 "Sync Rancher clusters is enabled, complex label selector specified", 77 true, 78 "matchLabels:\n foo: bar\nmatchExpressions:\n- key: clustertype\n operator: In\n values: [special, reallyspecial]", 79 &metav1.LabelSelector{ 80 MatchLabels: map[string]string{"foo": "bar"}, 81 MatchExpressions: []metav1.LabelSelectorRequirement{ 82 { 83 Key: "clustertype", 84 Operator: metav1.LabelSelectorOpIn, 85 Values: []string{"special", "reallyspecial"}, 86 }, 87 }, 88 }, 89 false, 90 }, 91 // GIVEN cluster sync is enabled and malformed label selector yaml is provided 92 // WHEN shouldSyncClusters is called 93 // THEN the call returns that cluster sync is enabled, a nil label selector, and an error 94 { 95 "Sync Rancher clusters is enabled, invalid label selector", 96 true, 97 "matchLabels:\n bogus\n", 98 nil, 99 true, 100 }, 101 } 102 103 for _, tt := range tests { 104 t.Run(tt.testName, func(t *testing.T) { 105 // if cluster selector text is specified, write it to a temp file 106 var filename string 107 if len(tt.clusterSelectorText) > 0 { 108 var err error 109 filename, err = writeTempFile(tt.clusterSelectorText) 110 asserts.NoError(err) 111 defer os.Remove(filename) 112 } 113 os.Setenv(syncClustersEnvVarName, strconv.FormatBool(tt.enabled)) 114 115 enabled, labelSelector, err := shouldSyncClusters(filename) 116 117 if tt.expectedError { 118 asserts.Error(err, tt.testName) 119 } else { 120 asserts.NoError(err, tt.testName) 121 } 122 asserts.Equal(tt.enabled, enabled, tt.testName) 123 asserts.Equal(tt.expectedLabelSelector, labelSelector, tt.testName) 124 }) 125 } 126 } 127 128 // TestIsCattleClustersCRDInstalled tests the isCRDInstalled function 129 func TestIsCattleClustersCRDInstalled(t *testing.T) { 130 asserts := assert.New(t) 131 132 // GIVEN a cluster that does not have the cattle clusters CRD installed 133 // WHEN a call is made to isCRDInstalled 134 // THEN the function returns false 135 client := fake.NewSimpleClientset().ApiextensionsV1() 136 isInstalled, err := isCRDInstalled(client, cattleClustersCRDName) 137 asserts.NoError(err) 138 asserts.False(isInstalled) 139 140 // GIVEN a cluster that does have the cattle clusters CRD installed 141 // WHEN a call is made to isCRDInstalled 142 // THEN the function returns true 143 crd := &apiextv1.CustomResourceDefinition{ 144 ObjectMeta: metav1.ObjectMeta{ 145 Name: cattleClustersCRDName, 146 }, 147 } 148 client = fake.NewSimpleClientset(crd).ApiextensionsV1() 149 isInstalled, err = isCRDInstalled(client, cattleClustersCRDName) 150 asserts.NoError(err) 151 asserts.True(isInstalled) 152 } 153 154 // TestWatchCattleClustersCRD tests the watchCattleClustersCRD function 155 func TestWatchCattleClustersCRD(t *testing.T) { 156 asserts := assert.New(t) 157 158 // GIVEN the cattle clusters CRD is installed after the cluster operator starts up 159 // WHEN the watchCattleClustersCRD function is called 160 // THEN the context Done channel has been closed due to the context cancel function being called 161 crd := &apiextv1.CustomResourceDefinition{ 162 ObjectMeta: metav1.ObjectMeta{ 163 Name: cattleClustersCRDName, 164 }, 165 } 166 client := fake.NewSimpleClientset(crd).ApiextensionsV1() 167 168 ctx, cancel := context.WithCancel(context.TODO()) 169 watchCattleClustersCRD(cancel, client, false, zap.L().Sugar()) 170 _, open := <-ctx.Done() 171 asserts.False(open) 172 173 // GIVEN the cattle clusters CRD is uninstalled after the cluster operator starts up 174 // WHEN the watchCattleClustersCRD function is called 175 // THEN the context Done channel has been closed due to the context cancel function being called 176 client = fake.NewSimpleClientset().ApiextensionsV1() 177 178 ctx, cancel = context.WithCancel(context.TODO()) 179 watchCattleClustersCRD(cancel, client, true, zap.L().Sugar()) 180 _, open = <-ctx.Done() 181 asserts.False(open) 182 } 183 184 // writeTempFile creates a temp file with the specified string content. It returns the 185 // file name. 186 func writeTempFile(clusterSelectorText string) (string, error) { 187 f, err := os.CreateTemp("", "") 188 if err != nil { 189 return "", err 190 } 191 f.Write([]byte(clusterSelectorText)) 192 f.Close() 193 return f.Name(), nil 194 }