@@ -32,10 +32,10 @@ const (
32
32
var ErrInvalidLabelValue = errors .New ("unexpected format of label value" )
33
33
34
34
// IsInClusterNamespace check if policy is in cluster namespace
35
- func IsInClusterNamespace (c client.Client , ns string ) (bool , error ) {
35
+ func IsInClusterNamespace (ctx context. Context , c client.Client , ns string ) (bool , error ) {
36
36
cluster := & clusterv1.ManagedCluster {}
37
37
38
- err := c .Get (context . TODO () , types.NamespacedName {Name : ns }, cluster )
38
+ err := c .Get (ctx , types.NamespacedName {Name : ns }, cluster )
39
39
if k8serrors .IsNotFound (err ) {
40
40
return false , nil
41
41
}
@@ -58,7 +58,7 @@ func IsReplicatedPolicy(c client.Client, policy client.Object) (bool, error) {
58
58
return false , fmt .Errorf ("invalid value set in %s: %w" , RootPolicyLabel , err )
59
59
}
60
60
61
- return IsInClusterNamespace (c , policy .GetNamespace ())
61
+ return IsInClusterNamespace (context . TODO (), c , policy .GetNamespace ())
62
62
}
63
63
64
64
// IsForPolicyOrPolicySet returns true if any of the subjects of the PlacementBinding are Policies
@@ -96,11 +96,11 @@ func IsPbForPolicySet(pb *policiesv1.PlacementBinding) bool {
96
96
97
97
// GetPoliciesInPlacementBinding returns a list of the Policies that are either direct subjects of
98
98
// the given PlacementBinding, or are in PolicySets that are subjects of the PlacementBinding.
99
- // The list items are not guaranteed to be unique (for example if a policy is in multiple sets).
99
+ // The list items are guaranteed to be unique (for example if a policy is in multiple sets).
100
100
func GetPoliciesInPlacementBinding (
101
101
ctx context.Context , c client.Client , pb * policiesv1.PlacementBinding ,
102
102
) []reconcile.Request {
103
- result := make ([] reconcile.Request , 0 )
103
+ table := map [ reconcile.Request ] bool {}
104
104
105
105
for _ , subject := range pb .Subjects {
106
106
if subject .APIGroup != policiesv1 .SchemeGroupVersion .Group {
@@ -109,10 +109,12 @@ func GetPoliciesInPlacementBinding(
109
109
110
110
switch subject .Kind {
111
111
case policiesv1 .Kind :
112
- result = append ( result , reconcile.Request {NamespacedName : types.NamespacedName {
112
+ req := reconcile.Request {NamespacedName : types.NamespacedName {
113
113
Name : subject .Name ,
114
114
Namespace : pb .GetNamespace (),
115
- }})
115
+ }}
116
+
117
+ table [req ] = true
116
118
case policiesv1 .PolicySetKind :
117
119
setNN := types.NamespacedName {
118
120
Name : subject .Name ,
@@ -125,14 +127,22 @@ func GetPoliciesInPlacementBinding(
125
127
}
126
128
127
129
for _ , plc := range policySet .Spec .Policies {
128
- result = append ( result , reconcile.Request {NamespacedName : types.NamespacedName {
130
+ req := reconcile.Request {NamespacedName : types.NamespacedName {
129
131
Name : string (plc ),
130
132
Namespace : pb .GetNamespace (),
131
- }})
133
+ }}
134
+
135
+ table [req ] = true
132
136
}
133
137
}
134
138
}
135
139
140
+ result := make ([]reconcile.Request , 0 , len (table ))
141
+
142
+ for k := range table {
143
+ result = append (result , k )
144
+ }
145
+
136
146
return result
137
147
}
138
148
@@ -162,7 +172,9 @@ func HasValidPlacementRef(pb *policiesv1.PlacementBinding) bool {
162
172
163
173
// GetDecisions returns the placement decisions from the Placement or PlacementRule referred to by
164
174
// the PlacementBinding
165
- func GetDecisions (c client.Client , pb * policiesv1.PlacementBinding ) ([]appsv1.PlacementDecision , error ) {
175
+ func GetDecisions (
176
+ ctx context.Context , c client.Client , pb * policiesv1.PlacementBinding ,
177
+ ) ([]appsv1.PlacementDecision , error ) {
166
178
if ! HasValidPlacementRef (pb ) {
167
179
return nil , fmt .Errorf ("placement binding %s/%s reference is not valid" , pb .Name , pb .Namespace )
168
180
}
@@ -176,7 +188,7 @@ func GetDecisions(c client.Client, pb *policiesv1.PlacementBinding) ([]appsv1.Pl
176
188
case "Placement" :
177
189
pl := & clusterv1beta1.Placement {}
178
190
179
- err := c .Get (context . TODO () , refNN , pl )
191
+ err := c .Get (ctx , refNN , pl )
180
192
if err != nil && ! k8serrors .IsNotFound (err ) {
181
193
return nil , fmt .Errorf ("failed to get Placement '%v': %w" , pb .PlacementRef .Name , err )
182
194
}
@@ -191,7 +203,7 @@ func GetDecisions(c client.Client, pb *policiesv1.PlacementBinding) ([]appsv1.Pl
191
203
opts := client.MatchingLabels {"cluster.open-cluster-management.io/placement" : pl .GetName ()}
192
204
opts .ApplyToList (lopts )
193
205
194
- err = c .List (context . TODO () , list , lopts )
206
+ err = c .List (ctx , list , lopts )
195
207
if err != nil && ! k8serrors .IsNotFound (err ) {
196
208
return nil , fmt .Errorf ("failed to list the PlacementDecisions for '%v', %w" , pb .PlacementRef .Name , err )
197
209
}
@@ -210,7 +222,7 @@ func GetDecisions(c client.Client, pb *policiesv1.PlacementBinding) ([]appsv1.Pl
210
222
return decisions , nil
211
223
case "PlacementRule" :
212
224
plr := & appsv1.PlacementRule {}
213
- if err := c .Get (context . TODO () , refNN , plr ); err != nil && ! k8serrors .IsNotFound (err ) {
225
+ if err := c .Get (ctx , refNN , plr ); err != nil && ! k8serrors .IsNotFound (err ) {
214
226
return nil , fmt .Errorf ("failed to get PlacementRule '%v': %w" , pb .PlacementRef .Name , err )
215
227
}
216
228
@@ -245,6 +257,33 @@ func FullNameForPolicy(plc *policiesv1.Policy) string {
245
257
return plc .GetNamespace () + "." + plc .GetName ()
246
258
}
247
259
260
+ // GetRepPoliciesInPlacementBinding returns a list of the replicated policies that are either direct subjects of
261
+ // the given PlacementBinding, or are in PolicySets that are subjects of the PlacementBinding.
262
+ // The list items are guaranteed to be unique (for example if a policy is in multiple sets).
263
+ func GetRepPoliciesInPlacementBinding (
264
+ ctx context.Context , c client.Client , pb * policiesv1.PlacementBinding ,
265
+ ) []reconcile.Request {
266
+ decisions , err := GetDecisions (ctx , c , pb )
267
+ if err != nil {
268
+ return []reconcile.Request {}
269
+ }
270
+ // Use this for removing duplicated policies
271
+ rootPolicyRequest := GetPoliciesInPlacementBinding (ctx , c , pb )
272
+
273
+ result := []reconcile.Request {}
274
+
275
+ for _ , rp := range rootPolicyRequest {
276
+ for _ , pd := range decisions {
277
+ result = append (result , reconcile.Request {NamespacedName : types.NamespacedName {
278
+ Name : rp .Namespace + "." + rp .Name ,
279
+ Namespace : pd .ClusterName ,
280
+ }})
281
+ }
282
+ }
283
+
284
+ return result
285
+ }
286
+
248
287
// TypeConverter is a helper function to converter type struct a to b
249
288
func TypeConverter (a , b interface {}) error {
250
289
js , err := json .Marshal (a )
@@ -254,3 +293,68 @@ func TypeConverter(a, b interface{}) error {
254
293
255
294
return json .Unmarshal (js , b )
256
295
}
296
+
297
+ // Select objects that are deleted or created
298
+ func GetAffectedObjs [T comparable ](oldObjs []T , newObjs []T ) []T {
299
+ table := make (map [T ]int )
300
+
301
+ for _ , oldObj := range oldObjs {
302
+ table [oldObj ] = 1
303
+ }
304
+
305
+ for _ , newObj := range newObjs {
306
+ table [newObj ]++
307
+ }
308
+
309
+ result := []T {}
310
+
311
+ for key , val := range table {
312
+ if val == 1 {
313
+ result = append (result , key )
314
+ }
315
+ }
316
+
317
+ return result
318
+ }
319
+
320
+ type PlacementRefKinds string
321
+
322
+ const (
323
+ Placement PlacementRefKinds = "Placement"
324
+ PlacementRule PlacementRefKinds = "PlacementRule"
325
+ )
326
+
327
+ // GetRootPolicyResult find and filter placementbindings which have namespace and placementRef.name.
328
+ // Gather all root policies under placementbindings
329
+ func GetRootPolicyResult (ctx context.Context , c client.Client ,
330
+ namespace , placementRefName string , refKind PlacementRefKinds ,
331
+ ) ([]reconcile.Request , error ) {
332
+ kindGroupMap := map [PlacementRefKinds ]string {
333
+ Placement : clusterv1beta1 .SchemeGroupVersion .Group ,
334
+ PlacementRule : appsv1 .SchemeGroupVersion .Group ,
335
+ }
336
+
337
+ pbList := & policiesv1.PlacementBindingList {}
338
+ // Find pb in the same namespace of placementrule
339
+ lopts := & client.ListOptions {Namespace : namespace }
340
+ opts := client.MatchingFields {"placementRef.name" : placementRefName }
341
+ opts .ApplyToList (lopts )
342
+
343
+ err := c .List (ctx , pbList , lopts )
344
+ if err != nil {
345
+ return nil , err
346
+ }
347
+ var rootPolicyResults []reconcile.Request
348
+
349
+ for i , pb := range pbList .Items {
350
+ if pb .PlacementRef .APIGroup != kindGroupMap [refKind ] ||
351
+ pb .PlacementRef .Kind != string (refKind ) || pb .PlacementRef .Name != placementRefName {
352
+ continue
353
+ }
354
+ // GetPoliciesInPlacementBinding only pick root-policy name
355
+ rootPolicyResults = append (rootPolicyResults ,
356
+ GetPoliciesInPlacementBinding (ctx , c , & pbList .Items [i ])... )
357
+ }
358
+
359
+ return rootPolicyResults , nil
360
+ }
0 commit comments