@@ -13,6 +13,8 @@ import (
1313 k8errors "k8s.io/apimachinery/pkg/api/errors"
1414 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1515 "k8s.io/apimachinery/pkg/types"
16+ "k8s.io/apimachinery/pkg/util/uuid"
17+ "k8s.io/apimachinery/pkg/util/validation"
1618 "k8s.io/apimachinery/pkg/util/wait"
1719 "k8s.io/client-go/util/retry"
1820 "sigs.k8s.io/controller-runtime/pkg/client"
@@ -26,7 +28,8 @@ import (
2628)
2729
2830const (
29- drainEvictionNameFormat = "drain-eviction-%s-%s"
31+ uuidLength = 8
32+ drainEvictionNameFormat = "drain-eviction-%s-%s-%s"
3033 resourceIdentifierKeyFormat = "%s/%s/%s/%s/%s"
3134)
3235
@@ -40,6 +43,7 @@ func (h *Helper) Drain(ctx context.Context) (bool, error) {
4043 if err := h .cordon (ctx ); err != nil {
4144 return false , fmt .Errorf ("failed to cordon member cluster %s: %w" , h .ClusterName , err )
4245 }
46+ log .Printf ("Successfully cordoned member cluster %s by adding cordon taint" , h .ClusterName )
4347
4448 if err := h .fetchClusterResourcePlacementToEvict (ctx ); err != nil {
4549 return false , err
@@ -50,15 +54,15 @@ func (h *Helper) Drain(ctx context.Context) (bool, error) {
5054 return true , nil
5155 }
5256
57+ isDrainSuccessful := true
5358 // create eviction objects for all <crpName, targetCluster>.
5459 for crpName := range h .ClusterResourcePlacementResourcesMap {
55- evictionName := fmt .Sprintf (drainEvictionNameFormat , crpName , h .ClusterName )
56-
57- if err := removeExistingEviction (ctx , h .HubClient , evictionName ); err != nil {
58- return false , fmt .Errorf ("failed to remove existing eviction for CRP %s" , crpName )
60+ evictionName , err := generateDrainEvictionName (crpName , h .ClusterName )
61+ if err != nil {
62+ return false , err
5963 }
6064
61- err : = retry .OnError (retry .DefaultBackoff , func (err error ) bool {
65+ err = retry .OnError (retry .DefaultBackoff , func (err error ) bool {
6266 return k8errors .IsAlreadyExists (err )
6367 }, func () error {
6468 eviction := placementv1beta1.ClusterResourcePlacementEviction {
@@ -76,13 +80,10 @@ func (h *Helper) Drain(ctx context.Context) (bool, error) {
7680 if err != nil {
7781 return false , fmt .Errorf ("failed to create eviction for CRP %s: %w" , crpName , err )
7882 }
79- }
8083
81- // wait until all evictions reach a terminal state.
82- for crpName := range h .ClusterResourcePlacementResourcesMap {
83- err := wait .ExponentialBackoffWithContext (ctx , retry .DefaultBackoff , func (ctx context.Context ) (bool , error ) {
84- evictionName := fmt .Sprintf (drainEvictionNameFormat , crpName , h .ClusterName )
85- eviction := placementv1beta1.ClusterResourcePlacementEviction {}
84+ // wait until evictions reach a terminal state.
85+ var eviction placementv1beta1.ClusterResourcePlacementEviction
86+ err = wait .ExponentialBackoffWithContext (ctx , retry .DefaultBackoff , func (ctx context.Context ) (bool , error ) {
8687 if err := h .HubClient .Get (ctx , types.NamespacedName {Name : evictionName }, & eviction ); err != nil {
8788 return false , fmt .Errorf ("failed to get eviction %s: %w" , evictionName , err )
8889 }
@@ -92,15 +93,7 @@ func (h *Helper) Drain(ctx context.Context) (bool, error) {
9293 if err != nil {
9394 return false , fmt .Errorf ("failed to wait for evictions to reach terminal state: %w" , err )
9495 }
95- }
9696
97- isDrainSuccessful := true
98- for crpName := range h .ClusterResourcePlacementResourcesMap {
99- evictionName := fmt .Sprintf (drainEvictionNameFormat , crpName , h .ClusterName )
100- eviction := placementv1beta1.ClusterResourcePlacementEviction {}
101- if err := h .HubClient .Get (ctx , types.NamespacedName {Name : evictionName }, & eviction ); err != nil {
102- return false , fmt .Errorf ("failed to get eviction %s: %w" , evictionName , err )
103- }
10497 validCondition := eviction .GetCondition (string (placementv1beta1 .PlacementEvictionConditionTypeValid ))
10598 if validCondition != nil && validCondition .Status == metav1 .ConditionFalse {
10699 // check to see if CRP is missing or CRP is being deleted or CRB is missing.
@@ -120,7 +113,7 @@ func (h *Helper) Drain(ctx context.Context) (bool, error) {
120113 // log each resource evicted by CRP.
121114 for i := range h .ClusterResourcePlacementResourcesMap [crpName ] {
122115 resourceIdentifier := h.ClusterResourcePlacementResourcesMap [crpName ][i ]
123- log .Printf ("evicted resource %s propagated by CRP %s" , fmt . Sprintf ( resourceIdentifierKeyFormat , resourceIdentifier . Group , resourceIdentifier . Version , resourceIdentifier . Kind , resourceIdentifier . Name , resourceIdentifier . Namespace ), crpName )
116+ log .Printf ("evicted resource %s propagated by CRP %s" , generateResourceIdentifierKey ( resourceIdentifier ), crpName )
124117 }
125118 }
126119
@@ -163,16 +156,24 @@ func (h *Helper) fetchClusterResourcePlacementToEvict(ctx context.Context) error
163156 targetBinding = & crb
164157 }
165158
159+ ignoreBinding := false
166160 if targetBinding != nil {
167161 err := wait .ExponentialBackoffWithContext (ctx , retry .DefaultBackoff , func (ctx context.Context ) (bool , error ) {
168- if getErr := h .HubClient .Get (ctx , types.NamespacedName {Name : targetBinding .Name }, targetBinding ); getErr != nil {
162+ var binding placementv1beta1.ClusterResourceBinding
163+ if getErr := h .HubClient .Get (ctx , types.NamespacedName {Name : targetBinding .Name }, & binding ); getErr != nil {
169164 // binding may have been deleted.
170165 if k8errors .IsNotFound (getErr ) {
166+ ignoreBinding = true
171167 return true , nil
172168 }
173169 return false , getErr
174170 }
175- if ! evictionutils .IsPlacementPresent (targetBinding ) {
171+ // binding is being deleted.
172+ if binding .DeletionTimestamp != nil {
173+ ignoreBinding = true
174+ return true , nil
175+ }
176+ if ! evictionutils .IsPlacementPresent (& binding ) {
176177 // need to wait until placement is present on member cluster.
177178 return false , nil
178179 }
@@ -181,9 +182,7 @@ func (h *Helper) fetchClusterResourcePlacementToEvict(ctx context.Context) error
181182
182183 if err != nil {
183184 return fmt .Errorf ("failed to wait for placement to be present on member cluster: %w" , err )
184- } else {
185- // At this point, the binding could be deleting or deleted we will still try to collect resources
186- // propagated by the CRP and issue eviction.
185+ } else if ! ignoreBinding {
187186 // get all successfully applied resources for the CRP.
188187 crpName := crb .GetLabels ()[placementv1beta1 .CRPTrackingLabel ]
189188 resourcesPropagated , err := h .collectResourcesPropagatedByCRP (ctx , crpName )
@@ -231,14 +230,21 @@ func (h *Helper) collectResourcesPropagatedByCRP(ctx context.Context, crpName st
231230 return resourcesPropagated , nil
232231}
233232
234- func removeExistingEviction (ctx context.Context , client client.Client , evictionName string ) error {
235- eviction := placementv1beta1.ClusterResourcePlacementEviction {}
236- if err := client .Get (ctx , types.NamespacedName {Name : evictionName }, & eviction ); err != nil {
237- if k8errors .IsNotFound (err ) {
238- return nil
239- }
240- return err
233+ func generateDrainEvictionName (crpName , targetCluster string ) (string , error ) {
234+ evictionName := fmt .Sprintf (drainEvictionNameFormat , crpName , targetCluster , uuid .NewUUID ()[:uuidLength ])
235+
236+ if errs := validation .IsQualifiedName (evictionName ); len (errs ) != 0 {
237+ return "" , fmt .Errorf ("failed to format a qualified name for drain eviction object with CRP name %s, cluster name %s: %v" , crpName , targetCluster , errs )
241238 }
239+ return evictionName , nil
240+ }
242241
243- return client .Delete (ctx , & eviction )
242+ func generateResourceIdentifierKey (r placementv1beta1.ResourceIdentifier ) string {
243+ if len (r .Group ) == 0 && len (r .Namespace ) == 0 {
244+ return fmt .Sprintf (resourceIdentifierKeyFormat , "''" , r .Version , r .Kind , "''" , r .Name )
245+ }
246+ if len (r .Namespace ) == 0 {
247+ return fmt .Sprintf (resourceIdentifierKeyFormat , r .Group , r .Version , r .Kind , "''" , r .Name )
248+ }
249+ return fmt .Sprintf (resourceIdentifierKeyFormat , r .Group , r .Version , r .Kind , r .Namespace , r .Name )
244250}
0 commit comments