@@ -14,6 +14,7 @@ import (
14
14
"k8s.io/apimachinery/pkg/api/errors"
15
15
k8serrors "k8s.io/apimachinery/pkg/api/errors"
16
16
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17
+ "k8s.io/apimachinery/pkg/labels"
17
18
"k8s.io/apimachinery/pkg/util/wait"
18
19
"k8s.io/client-go/informers"
19
20
"k8s.io/client-go/tools/cache"
@@ -22,6 +23,7 @@ import (
22
23
. "github.com/onsi/ginkgo"
23
24
v1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1"
24
25
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
26
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
25
27
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
26
28
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry"
27
29
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
@@ -2043,6 +2045,169 @@ var _ = Describe("Operator Group", func() {
2043
2045
})
2044
2046
require .NoError (GinkgoT (), err )
2045
2047
})
2048
+ It ("OperatorGroupLabels" , func () {
2049
+ c := newKubeClient (GinkgoT ())
2050
+ crc := newCRClient (GinkgoT ())
2051
+
2052
+ // Create the namespaces that will have an OperatorGroup Label applied.
2053
+ testNamespaceA := genName ("namespace-a-" )
2054
+ testNamespaceB := genName ("namespace-b-" )
2055
+ testNamespaceC := genName ("namespace-c-" )
2056
+ testNamespaces := []string {
2057
+ testNamespaceA , testNamespaceB , testNamespaceC ,
2058
+ }
2059
+
2060
+ // Create the namespaces
2061
+ for _ , namespace := range testNamespaces {
2062
+ _ , err := c .KubernetesInterface ().CoreV1 ().Namespaces ().Create (& corev1.Namespace {
2063
+ ObjectMeta : metav1.ObjectMeta {
2064
+ Name : namespace ,
2065
+ },
2066
+ })
2067
+ require .NoError (GinkgoT (), err )
2068
+ }
2069
+
2070
+ // Cleanup namespaces
2071
+ defer func () {
2072
+ for _ , namespace := range testNamespaces {
2073
+ err := c .KubernetesInterface ().CoreV1 ().Namespaces ().Delete (namespace , & metav1.DeleteOptions {})
2074
+ require .NoError (GinkgoT (), err )
2075
+ }
2076
+ }()
2077
+
2078
+ // Create an OperatorGroup
2079
+ operatorGroup := & v1.OperatorGroup {
2080
+ ObjectMeta : metav1.ObjectMeta {
2081
+ Name : genName ("e2e-operator-group-" ),
2082
+ Namespace : testNamespaceA ,
2083
+ },
2084
+ Spec : v1.OperatorGroupSpec {
2085
+ TargetNamespaces : []string {},
2086
+ },
2087
+ }
2088
+ _ , err := crc .OperatorsV1 ().OperatorGroups (testNamespaceA ).Create (operatorGroup )
2089
+ require .NoError (GinkgoT (), err )
2090
+
2091
+ // Cleanup OperatorGroup
2092
+ defer func () {
2093
+ err := crc .OperatorsV1 ().OperatorGroups (testNamespaceA ).Delete (operatorGroup .GetName (), & metav1.DeleteOptions {})
2094
+ require .NoError (GinkgoT (), err )
2095
+ }()
2096
+
2097
+ // Create the OperatorGroup Label
2098
+ ogLabel := fmt .Sprintf ("olm.operatorgroup/%s.%s" , testNamespaceA , operatorGroup .GetName ())
2099
+
2100
+ // Create list options
2101
+ listOptions := metav1.ListOptions {
2102
+ LabelSelector : labels .Set (map [string ]string {ogLabel : "" }).String (),
2103
+ }
2104
+
2105
+ namespaceList , err := pollForListCount (c , listOptions , 0 )
2106
+ require .NoError (GinkgoT (), err )
2107
+
2108
+ // Update the OperatorGroup to include a single namespace
2109
+ operatorGroup .Spec .TargetNamespaces = []string {testNamespaceA }
2110
+ updateOGSpecFunc := updateOperatorGroupSpecFunc (GinkgoT (), crc , testNamespaceA , operatorGroup .GetName ())
2111
+ require .NoError (GinkgoT (), retry .RetryOnConflict (retry .DefaultBackoff , updateOGSpecFunc (operatorGroup .Spec )))
2112
+
2113
+ namespaceList , err = pollForListCount (c , listOptions , 1 )
2114
+ require .NoError (GinkgoT (), err )
2115
+ require .True (GinkgoT (), checkForOperatorGroupLabels (operatorGroup , namespaceList .Items ))
2116
+
2117
+ // Update the OperatorGroup to include two namespaces
2118
+ operatorGroup .Spec .TargetNamespaces = []string {testNamespaceA , testNamespaceC }
2119
+ require .NoError (GinkgoT (), retry .RetryOnConflict (retry .DefaultBackoff , updateOGSpecFunc (operatorGroup .Spec )))
2120
+
2121
+ namespaceList , err = pollForListCount (c , listOptions , 2 )
2122
+ require .NoError (GinkgoT (), err )
2123
+ require .True (GinkgoT (), checkForOperatorGroupLabels (operatorGroup , namespaceList .Items ))
2124
+
2125
+ // Update the OperatorGroup to include three namespaces
2126
+ operatorGroup .Spec .TargetNamespaces = []string {testNamespaceA , testNamespaceB , testNamespaceC }
2127
+ require .NoError (GinkgoT (), retry .RetryOnConflict (retry .DefaultBackoff , updateOGSpecFunc (operatorGroup .Spec )))
2128
+
2129
+ namespaceList , err = pollForListCount (c , listOptions , 3 )
2130
+ require .NoError (GinkgoT (), err )
2131
+ require .True (GinkgoT (), checkForOperatorGroupLabels (operatorGroup , namespaceList .Items ))
2132
+
2133
+ // Update the OperatorGroup to include two namespaces
2134
+ operatorGroup .Spec .TargetNamespaces = []string {testNamespaceA , testNamespaceC }
2135
+ require .NoError (GinkgoT (), retry .RetryOnConflict (retry .DefaultBackoff , updateOGSpecFunc (operatorGroup .Spec )))
2136
+
2137
+ namespaceList , err = pollForListCount (c , listOptions , 2 )
2138
+ require .NoError (GinkgoT (), err )
2139
+ require .True (GinkgoT (), checkForOperatorGroupLabels (operatorGroup , namespaceList .Items ))
2140
+
2141
+ // Make the OperatorGroup a Cluster OperatorGroup.
2142
+ operatorGroup .Spec .TargetNamespaces = []string {}
2143
+ require .NoError (GinkgoT (), retry .RetryOnConflict (retry .DefaultBackoff , updateOGSpecFunc (operatorGroup .Spec )))
2144
+
2145
+ namespaceList , err = pollForListCount (c , listOptions , 0 )
2146
+ require .NoError (GinkgoT (), err )
2147
+ })
2148
+ It ("CleanupDeletedOperatorGroupLabels" , func () {
2149
+ c := newKubeClient (GinkgoT ())
2150
+ crc := newCRClient (GinkgoT ())
2151
+
2152
+ // Create the namespaces that will have an OperatorGroup Label applied.
2153
+ testNamespaceA := genName ("namespace-a-" )
2154
+ testNamespaceB := genName ("namespace-b-" )
2155
+ testNamespaceC := genName ("namespace-c-" )
2156
+ testNamespaces := []string {
2157
+ testNamespaceA , testNamespaceB , testNamespaceC ,
2158
+ }
2159
+
2160
+ // Create the namespaces
2161
+ for _ , namespace := range testNamespaces {
2162
+ _ , err := c .KubernetesInterface ().CoreV1 ().Namespaces ().Create (& corev1.Namespace {
2163
+ ObjectMeta : metav1.ObjectMeta {
2164
+ Name : namespace ,
2165
+ },
2166
+ })
2167
+ require .NoError (GinkgoT (), err )
2168
+ }
2169
+
2170
+ // Cleanup namespaces
2171
+ defer func () {
2172
+ for _ , namespace := range testNamespaces {
2173
+ err := c .KubernetesInterface ().CoreV1 ().Namespaces ().Delete (namespace , & metav1.DeleteOptions {})
2174
+ require .NoError (GinkgoT (), err )
2175
+ }
2176
+ }()
2177
+
2178
+ // Create an OperatorGroup with three target namespaces.
2179
+ operatorGroup := & v1.OperatorGroup {
2180
+ ObjectMeta : metav1.ObjectMeta {
2181
+ Name : genName ("e2e-operator-group-" ),
2182
+ Namespace : testNamespaceA ,
2183
+ },
2184
+ Spec : v1.OperatorGroupSpec {
2185
+ TargetNamespaces : testNamespaces ,
2186
+ },
2187
+ }
2188
+ _ , err := crc .OperatorsV1 ().OperatorGroups (testNamespaceA ).Create (operatorGroup )
2189
+ require .NoError (GinkgoT (), err )
2190
+
2191
+ // Create the OperatorGroup Label
2192
+ ogLabel := fmt .Sprintf ("olm.operatorgroup/%s.%s" , testNamespaceA , operatorGroup .GetName ())
2193
+
2194
+ // Create list options
2195
+ listOptions := metav1.ListOptions {
2196
+ LabelSelector : labels .Set (map [string ]string {ogLabel : "" }).String (),
2197
+ }
2198
+
2199
+ namespaceList , err := pollForListCount (c , listOptions , 3 )
2200
+ require .NoError (GinkgoT (), err )
2201
+ require .True (GinkgoT (), checkForOperatorGroupLabels (operatorGroup , namespaceList .Items ))
2202
+
2203
+ // Delete the operatorGroup.
2204
+ err = crc .OperatorsV1 ().OperatorGroups (testNamespaceA ).Delete (operatorGroup .GetName (), & metav1.DeleteOptions {})
2205
+ require .NoError (GinkgoT (), err )
2206
+
2207
+ // Check that no namespaces have the OperatorGroup.
2208
+ namespaceList , err = pollForListCount (c , listOptions , 0 )
2209
+ require .NoError (GinkgoT (), err )
2210
+ })
2046
2211
})
2047
2212
2048
2213
func checkOperatorGroupAnnotations (obj metav1.Object , op * v1.OperatorGroup , checkTargetNamespaces bool , targetNamespaces string ) error {
@@ -2115,3 +2280,47 @@ func createProjectAdmin(t GinkgoTInterface, c operatorclient.ClientInterface, na
2115
2280
_ = c .DeleteRoleBinding (rb .GetNamespace (), rb .GetName (), metav1 .NewDeleteOptions (0 ))
2116
2281
}
2117
2282
}
2283
+
2284
+ func checkForOperatorGroupLabels (operatorGroup * v1.OperatorGroup , namespaces []corev1.Namespace ) bool {
2285
+ for _ , ns := range operatorGroup .Spec .TargetNamespaces {
2286
+ if ! containsNamespace (namespaces , ns ) {
2287
+ return false
2288
+ }
2289
+ }
2290
+ return true
2291
+ }
2292
+
2293
+ func updateOperatorGroupSpecFunc (t GinkgoTInterface , crc versioned.Interface , namespace , operatorGroupName string ) func (v1.OperatorGroupSpec ) func () error {
2294
+ return func (operatorGroupSpec v1.OperatorGroupSpec ) func () error {
2295
+ return func () error {
2296
+ fetchedOG , err := crc .OperatorsV1 ().OperatorGroups (namespace ).Get (operatorGroupName , metav1.GetOptions {})
2297
+ require .NoError (t , err )
2298
+ fetchedOG .Spec = operatorGroupSpec
2299
+ _ , err = crc .OperatorsV1 ().OperatorGroups (namespace ).Update (fetchedOG )
2300
+ return err
2301
+ }
2302
+ }
2303
+ }
2304
+
2305
+ func pollForListCount (c operatorclient.ClientInterface , listOptions metav1.ListOptions , expectedLength int ) (list * corev1.NamespaceList , err error ) {
2306
+ wait .PollImmediate (pollInterval , pollDuration , func () (bool , error ) {
2307
+ list , err = c .KubernetesInterface ().CoreV1 ().Namespaces ().List (listOptions )
2308
+ if err != nil {
2309
+ return false , err
2310
+ }
2311
+ if len (list .Items ) == expectedLength {
2312
+ return true , nil
2313
+ }
2314
+ return false , nil
2315
+ })
2316
+ return
2317
+ }
2318
+
2319
+ func containsNamespace (namespaces []corev1.Namespace , namespaceName string ) bool {
2320
+ for i := range namespaces {
2321
+ if namespaces [i ].GetName () == namespaceName {
2322
+ return true
2323
+ }
2324
+ }
2325
+ return false
2326
+ }
0 commit comments