@@ -231,6 +231,106 @@ var _ = Describe("Exceptions", func() {
231231 })
232232 }
233233 })
234+
235+ Context ("Update the descendant namespaces after 'select' exception annotation is set" , func () {
236+ const (
237+ label = "propagate-label"
238+ p = "parent"
239+ labeledchild = "labeledchild"
240+ nolabelchild = "nolabelchild"
241+ labeledns = "labeledns"
242+ nolabelns = "nolabelns"
243+ )
244+ tests := []struct {
245+ name string
246+ toLabel string
247+ toUnlabel string
248+ toAddChild string
249+ want []string
250+ notWant []string
251+ }{{
252+ name : "propagate object only to children with the label" ,
253+ want : []string {labeledchild },
254+ notWant : []string {nolabelchild },
255+ }, {
256+ name : "propagate object to a newly-labeled child - issue #1448" ,
257+ toLabel : nolabelchild ,
258+ want : []string {labeledchild , nolabelchild },
259+ notWant : []string {},
260+ }, {
261+ name : "not propagate object to a newly-unlabeled child - issue #1448" ,
262+ toUnlabel : labeledchild ,
263+ want : []string {},
264+ notWant : []string {labeledchild , nolabelchild },
265+ }, {
266+ name : "propagate object to a new child with the label" ,
267+ toAddChild : labeledns ,
268+ want : []string {labeledchild , labeledns },
269+ notWant : []string {nolabelchild },
270+ }, {
271+ name : "not propagate object to a new child without the label" ,
272+ toAddChild : nolabelns ,
273+ want : []string {labeledchild },
274+ notWant : []string {nolabelchild , nolabelns },
275+ }}
276+
277+ for _ , tc := range tests {
278+ // Making a local copy of tc is necessary to ensure the correct value is passed to the closure,
279+ // for more details look at https://onsi.github.io/ginkgo/ and search for 'closure'
280+ tc := tc
281+ It ("Should " + tc .name , func () {
282+ // Set up namespaces
283+ names := map [string ]string {
284+ p : createNS (ctx , p ),
285+ labeledchild : createNSWithLabel (ctx , labeledchild , map [string ]string {label : "true" }),
286+ nolabelchild : createNS (ctx , nolabelchild ),
287+ labeledns : createNSWithLabel (ctx , labeledns , map [string ]string {label : "true" }),
288+ nolabelns : createNS (ctx , nolabelns ),
289+ }
290+ setParent (ctx , names [labeledchild ], names [p ])
291+ setParent (ctx , names [nolabelchild ], names [p ])
292+
293+ // Create a Role and verify it's propagated to all children.
294+ makeObject (ctx , api .RoleResource , names [p ], "testrole" )
295+ Eventually (hasObject (ctx , api .RoleResource , names [labeledchild ], "testrole" )).Should (BeTrue (), "When propagating testrole to %s" , names [labeledchild ])
296+ Eventually (hasObject (ctx , api .RoleResource , names [nolabelchild ], "testrole" )).Should (BeTrue (), "When propagating testrole to %s" , names [nolabelchild ])
297+ // Add `select` exception annotation with propagate label and verify the
298+ // object is only propagated to children with the label.
299+ updateObjectWithAnnotation (ctx , api .RoleResource , names [p ], "testrole" , map [string ]string {
300+ api .AnnotationSelector : label ,
301+ })
302+ Eventually (hasObject (ctx , api .RoleResource , names [nolabelchild ], "testrole" )).Should (BeFalse (), "When propagating testrole to %s" , names [nolabelchild ])
303+ Consistently (hasObject (ctx , api .RoleResource , names [nolabelchild ], "testrole" )).Should (BeFalse (), "When propagating testrole to %s" , names [nolabelchild ])
304+ Consistently (hasObject (ctx , api .RoleResource , names [labeledchild ], "testrole" )).Should (BeTrue (), "When propagating testrole to %s" , names [labeledchild ])
305+
306+ // Add the label to the namespace if the value is not empty.
307+ if tc .toLabel != "" {
308+ addNamespaceLabel (ctx , names [tc .toLabel ], label , "true" )
309+ }
310+
311+ // Unlabel the namespace if the value is not empty.
312+ if tc .toUnlabel != "" {
313+ removeNamespaceLabel (ctx , names [tc .toUnlabel ], label )
314+ }
315+
316+ // Set a new child if the value is not empty.
317+ if tc .toAddChild != "" {
318+ setParent (ctx , names [tc .toAddChild ], names [p ])
319+ }
320+
321+ // then check that the objects are kept in these namespaces
322+ for _ , ns := range tc .want {
323+ ns = replaceStrings (ns , names )
324+ Eventually (hasObject (ctx , api .RoleResource , ns , "testrole" )).Should (BeTrue (), "When propagating testrole to %s" , ns )
325+ }
326+ // make sure the changes are propagated
327+ for _ , ns := range tc .notWant {
328+ ns = replaceStrings (ns , names )
329+ Eventually (hasObject (ctx , api .RoleResource , ns , "testrole" )).Should (BeFalse (), "When propagating testrole to %s" , ns )
330+ }
331+ })
332+ }
333+ })
234334})
235335
236336var _ = Describe ("Basic propagation" , func () {
0 commit comments