@@ -93,19 +93,23 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
93
93
reqNsOld := "ibm-common-services"
94
94
opNameV3 := "ibm-iam"
95
95
opChannelV3 := "v3"
96
+ opConfigV3 := "ibm-iam"
96
97
97
98
reqNameB := "other-request"
98
99
reqNsNew := "other-namespace"
99
100
opNameV4 := "ibm-im"
100
101
opChannelV4 := "v4.0"
102
+ opConfigV4 := "ibm-im"
101
103
102
104
reqNameC := "common-service-postgresql"
103
105
opNameC := "common-service-postgresql"
104
106
opChannelC := "stable-v1.22"
107
+ opConfigC := "common-service-postgresql"
105
108
106
109
reqNameD := "edb-keycloak"
107
110
opNameD := "edb-keycloak"
108
111
opChannelD := "stable"
112
+ opConfigD := "edb-keycloak"
109
113
110
114
// The annotation key has prefix: <requestNamespace>.<requestName>.<operatorName>/*
111
115
@@ -115,7 +119,9 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
115
119
// When one of following conditions are met, the operand will NOT be uninstalled:
116
120
// 1. operator is not uninstalled AND intallMode is no-op.
117
121
// 2. operator is uninstalled AND at least one other <prefix>/operatorNamespace annotation exists.
118
- // 2. remaining <prefix>/request annotation's values contain the same operator name
122
+ // 3. remaining <prefix>/request annotation's values contain the same operator name
123
+ // 4. currentConfigName is found AND remaining <prefix>/config annotation's values contain the same configName as this operator
124
+ // 5. currentConfigName is empty (not found in annotations)
119
125
120
126
// Test case 1: uninstallOperator is true, uninstallOperand is true for uninstalling operator with v3 no-op installMode
121
127
// The operator and operand should be uninstalled because no remaining annotation is left.
@@ -125,6 +131,7 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
125
131
Annotations : map [string ]string {
126
132
reqNsOld + "." + reqNameA + "." + opNameV3 + "/request" : opChannelV3 ,
127
133
reqNsOld + "." + reqNameA + "." + opNameV3 + "/operatorNamespace" : reqNsOld ,
134
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/config" : opConfigV3 ,
128
135
},
129
136
Labels : map [string ]string {
130
137
constant .OpreqLabel : "true" ,
@@ -139,6 +146,7 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
139
146
140
147
assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/request" )
141
148
assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/operatorNamespace" )
149
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/config" )
142
150
143
151
// Test case 2: uninstallOperator is true, uninstallOperand is true for uninstalling operator with general installMode
144
152
// The operator and operand should be uninstalled because no remaining annotation is left.
@@ -148,6 +156,7 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
148
156
Annotations : map [string ]string {
149
157
reqNsOld + "." + reqNameA + "." + opNameV4 + "/request" : opChannelV4 ,
150
158
reqNsOld + "." + reqNameA + "." + opNameV4 + "/operatorNamespace" : reqNsOld ,
159
+ reqNsOld + "." + reqNameA + "." + opNameV4 + "/config" : opConfigV4 ,
151
160
},
152
161
Labels : map [string ]string {
153
162
constant .OpreqLabel : "true" ,
@@ -162,6 +171,7 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
162
171
163
172
assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV4 + "/request" )
164
173
assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV4 + "/operatorNamespace" )
174
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV4 + "/config" )
165
175
166
176
// Test case 3: uninstallOperator is true, uninstallOperand is false for all namespace migration
167
177
// where operator is uninstalled and will be reinstalled in new namespace and operand is not for old operator with v3 no-op installMode
@@ -227,8 +237,10 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
227
237
Annotations : map [string ]string {
228
238
reqNsOld + "." + reqNameC + "." + opNameC + "/request" : opChannelC ,
229
239
reqNsOld + "." + reqNameC + "." + opNameC + "/operatorNamespace" : reqNsOld ,
240
+ reqNsOld + "." + reqNameC + "." + opNameC + "/config" : opConfigC ,
230
241
reqNsOld + "." + reqNameD + "." + opNameD + "/request" : opChannelD ,
231
242
reqNsOld + "." + reqNameD + "." + opNameD + "/operatorNamespace" : reqNsOld ,
243
+ reqNsOld + "." + reqNameD + "." + opNameD + "/config" : opConfigD ,
232
244
},
233
245
Labels : map [string ]string {
234
246
constant .OpreqLabel : "true" ,
@@ -243,8 +255,10 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
243
255
244
256
assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameC + "." + opNameC + "/request" )
245
257
assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameC + "." + opNameC + "/operatorNamespace" )
258
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameC + "." + opNameC + "/config" )
246
259
assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameD + "." + opNameD + "/request" )
247
260
assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameD + "." + opNameD + "/operatorNamespace" )
261
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameD + "." + opNameD + "/config" )
248
262
249
263
// Test case 6: uninstallOperator is false, uninstallOperand is false for removing one no-op operand only for upgrade scenario
250
264
// The operator should not be uninstalled because the remaining request is requesting operator is in the same namespace as the Subscription.
@@ -284,8 +298,10 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
284
298
Annotations : map [string ]string {
285
299
reqNsNew + "." + reqNameA + "." + opNameV4 + "/request" : opChannelV4 ,
286
300
reqNsNew + "." + reqNameA + "." + opNameV4 + "/operatorNamespace" : reqNsNew ,
301
+ reqNsNew + "." + reqNameA + "." + opNameV4 + "/config" : opConfigV4 ,
287
302
reqNsNew + "." + reqNameB + "." + opNameV4 + "/request" : opChannelV4 ,
288
303
reqNsNew + "." + reqNameB + "." + opNameV4 + "/operatorNamespace" : reqNsNew ,
304
+ reqNsNew + "." + reqNameB + "." + opNameV4 + "/config" : opConfigV4 ,
289
305
},
290
306
Labels : map [string ]string {
291
307
constant .OpreqLabel : "true" ,
@@ -300,6 +316,7 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
300
316
301
317
assert .NotContains (t , sub .Annotations , reqNsNew + "." + reqNameA + "." + opNameV4 + "/request" )
302
318
assert .NotContains (t , sub .Annotations , reqNsNew + "." + reqNameA + "." + opNameV4 + "/operatorNamespace" )
319
+ assert .NotContains (t , sub .Annotations , reqNsNew + "." + reqNameA + "." + opNameV4 + "/config" )
303
320
assert .Contains (t , sub .Annotations , reqNsNew + "." + reqNameB + "." + opNameV4 + "/request" )
304
321
assert .Contains (t , sub .Annotations , reqNsNew + "." + reqNameB + "." + opNameV4 + "/operatorNamespace" )
305
322
@@ -312,6 +329,7 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
312
329
Annotations : map [string ]string {
313
330
reqNsOld + "." + reqNameA + "." + opNameV4 + "/request" : opChannelV4 ,
314
331
reqNsOld + "." + reqNameA + "." + opNameV4 + "/operatorNamespace" : reqNsOld ,
332
+ reqNsOld + "." + reqNameA + "." + opNameV4 + "/config" : opConfigV4 ,
315
333
},
316
334
Labels : map [string ]string {
317
335
constant .OpreqLabel : "false" ,
@@ -326,4 +344,102 @@ func TestCheckSubAnnotationsForUninstall(t *testing.T) {
326
344
327
345
assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV4 + "/request" )
328
346
assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV4 + "/operatorNamespace" )
347
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV4 + "/config" )
348
+
349
+ // Test case 9: Config name sharing test - operands should be preserved when config names match
350
+ // When uninstalling one operator but another operator shares the same config name,
351
+ // the operands should NOT be uninstalled since they're shared
352
+ sub = & olmv1alpha1.Subscription {
353
+ ObjectMeta : metav1.ObjectMeta {
354
+ Namespace : reqNsOld ,
355
+ Annotations : map [string ]string {
356
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/request" : opChannelV3 ,
357
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/operatorNamespace" : reqNsOld ,
358
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/config" : opConfigV3 ,
359
+ reqNsOld + "." + reqNameB + "." + opNameV4 + "/request" : opChannelV4 ,
360
+ reqNsOld + "." + reqNameB + "." + opNameV4 + "/operatorNamespace" : reqNsOld ,
361
+ reqNsOld + "." + reqNameB + "." + opNameV4 + "/config" : opConfigV3 ,
362
+ },
363
+ Labels : map [string ]string {
364
+ constant .OpreqLabel : "true" ,
365
+ },
366
+ },
367
+ }
368
+
369
+ uninstallOperator , uninstallOperand = checkSubAnnotationsForUninstall (reqNameA , reqNsOld , opNameV3 , operatorv1alpha1 .InstallModeNamespace , sub )
370
+
371
+ assert .False (t , uninstallOperator )
372
+ assert .False (t , uninstallOperand )
373
+
374
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/request" )
375
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/operatorNamespace" )
376
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/config" )
377
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameB + "." + opNameV4 + "/request" )
378
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameB + "." + opNameV4 + "/operatorNamespace" )
379
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameB + "." + opNameV4 + "/config" )
380
+
381
+ // Test case 10: Different config names - operands SHOULD be uninstalled
382
+ // When uninstalling one operator and other operators have different config names,
383
+ // the operands SHOULD be uninstalled
384
+ sub = & olmv1alpha1.Subscription {
385
+ ObjectMeta : metav1.ObjectMeta {
386
+ Namespace : reqNsOld ,
387
+ Annotations : map [string ]string {
388
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/request" : opChannelV3 ,
389
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/operatorNamespace" : reqNsOld ,
390
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/config" : opConfigV3 ,
391
+ reqNsOld + "." + reqNameB + "." + opNameV4 + "/request" : opChannelV4 ,
392
+ reqNsOld + "." + reqNameB + "." + opNameV4 + "/operatorNamespace" : reqNsOld ,
393
+ reqNsOld + "." + reqNameB + "." + opNameV4 + "/config" : opConfigV4 ,
394
+ },
395
+ Labels : map [string ]string {
396
+ constant .OpreqLabel : "true" ,
397
+ },
398
+ },
399
+ }
400
+
401
+ uninstallOperator , uninstallOperand = checkSubAnnotationsForUninstall (reqNameA , reqNsOld , opNameV3 , operatorv1alpha1 .InstallModeNamespace , sub )
402
+
403
+ assert .False (t , uninstallOperator )
404
+ assert .True (t , uninstallOperand )
405
+
406
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/request" )
407
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/operatorNamespace" )
408
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/config" )
409
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameB + "." + opNameV4 + "/request" )
410
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameB + "." + opNameV4 + "/operatorNamespace" )
411
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameB + "." + opNameV4 + "/config" )
412
+
413
+ // Test case 11: Same operator with different channels shared the same config name - operands should be preserved
414
+ // When uninstalling one operator but another operator shares the same config name,
415
+ // the operands should NOT be uninstalled since they're shared
416
+ sub = & olmv1alpha1.Subscription {
417
+ ObjectMeta : metav1.ObjectMeta {
418
+ Namespace : reqNsOld ,
419
+ Annotations : map [string ]string {
420
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/request" : opChannelV3 ,
421
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/operatorNamespace" : reqNsOld ,
422
+ reqNsOld + "." + reqNameA + "." + opNameV3 + "/config" : opConfigV3 ,
423
+ reqNsOld + "." + reqNameB + "." + opNameV4 + "/request" : opChannelV4 ,
424
+ reqNsOld + "." + reqNameB + "." + opNameV4 + "/operatorNamespace" : reqNsOld ,
425
+ reqNsOld + "." + reqNameB + "." + opNameV4 + "/config" : opConfigV3 ,
426
+ },
427
+ Labels : map [string ]string {
428
+ constant .OpreqLabel : "true" ,
429
+ },
430
+ },
431
+ }
432
+
433
+ uninstallOperator , uninstallOperand = checkSubAnnotationsForUninstall (reqNameA , reqNsOld , opNameV3 , operatorv1alpha1 .InstallModeNamespace , sub )
434
+
435
+ assert .False (t , uninstallOperator )
436
+ assert .False (t , uninstallOperand )
437
+
438
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/request" )
439
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/operatorNamespace" )
440
+ assert .NotContains (t , sub .Annotations , reqNsOld + "." + reqNameA + "." + opNameV3 + "/config" )
441
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameB + "." + opNameV4 + "/request" )
442
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameB + "." + opNameV4 + "/operatorNamespace" )
443
+ assert .Contains (t , sub .Annotations , reqNsOld + "." + reqNameB + "." + opNameV4 + "/config" )
444
+
329
445
}
0 commit comments