@@ -41,6 +41,7 @@ import (
41
41
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2"
42
42
clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
43
43
logf "sigs.k8s.io/cluster-api/cmd/clusterctl/log"
44
+ "sigs.k8s.io/cluster-api/util/annotations"
44
45
"sigs.k8s.io/cluster-api/util/conditions"
45
46
"sigs.k8s.io/cluster-api/util/patch"
46
47
"sigs.k8s.io/cluster-api/util/yaml"
@@ -297,6 +298,25 @@ func getClusterObj(ctx context.Context, proxy Proxy, cluster *node, clusterObj *
297
298
return nil
298
299
}
299
300
301
+ // getClusterClassObj retrieves the clusterClassObj corresponding to a node with type ClusterClass.
302
+ func getClusterClassObj (ctx context.Context , proxy Proxy , cluster * node , clusterClassObj * clusterv1.ClusterClass ) error {
303
+ c , err := proxy .NewClient (ctx )
304
+ if err != nil {
305
+ return err
306
+ }
307
+
308
+ clusterClassObjKey := client.ObjectKey {
309
+ Namespace : cluster .identity .Namespace ,
310
+ Name : cluster .identity .Name ,
311
+ }
312
+
313
+ if err := c .Get (ctx , clusterClassObjKey , clusterClassObj ); err != nil {
314
+ return errors .Wrapf (err , "error reading ClusterClass %s/%s" ,
315
+ cluster .identity .Namespace , cluster .identity .Name )
316
+ }
317
+ return nil
318
+ }
319
+
300
320
// getMachineObj retrieves the machineObj corresponding to a node with type Machine.
301
321
func getMachineObj (ctx context.Context , proxy Proxy , machine * node , machineObj * clusterv1.Machine ) error {
302
322
c , err := proxy .NewClient (ctx )
@@ -320,9 +340,17 @@ func (o *objectMover) move(ctx context.Context, graph *objectGraph, toProxy Prox
320
340
log := logf .Log
321
341
322
342
clusters := graph .getClusters ()
343
+ if err := checkClustersNotPaused (ctx , o .fromProxy , clusters ); err != nil {
344
+ return err
345
+ }
346
+
323
347
log .Info ("Moving Cluster API objects" , "Clusters" , len (clusters ))
324
348
325
349
clusterClasses := graph .getClusterClasses ()
350
+ if err := checkClusterClassesNotPaused (ctx , o .fromProxy , clusterClasses ); err != nil {
351
+ return err
352
+ }
353
+
326
354
log .Info ("Moving Cluster API objects" , "ClusterClasses" , len (clusterClasses ))
327
355
328
356
// Sets the pause field on the Cluster object in the source management cluster, so the controllers stop reconciling it.
@@ -395,9 +423,17 @@ func (o *objectMover) toDirectory(ctx context.Context, graph *objectGraph, direc
395
423
log := logf .Log
396
424
397
425
clusters := graph .getClusters ()
426
+ if err := checkClustersNotPaused (ctx , o .fromProxy , clusters ); err != nil {
427
+ return err
428
+ }
429
+
398
430
log .Info ("Starting move of Cluster API objects" , "Clusters" , len (clusters ))
399
431
400
432
clusterClasses := graph .getClusterClasses ()
433
+ if err := checkClusterClassesNotPaused (ctx , o .fromProxy , clusterClasses ); err != nil {
434
+ return err
435
+ }
436
+
401
437
log .Info ("Moving Cluster API objects" , "ClusterClasses" , len (clusterClasses ))
402
438
403
439
// Sets the pause field on the Cluster object in the source management cluster, so the controllers stop reconciling it.
@@ -611,6 +647,40 @@ func setClusterClassPause(ctx context.Context, proxy Proxy, clusterclasses []*no
611
647
return nil
612
648
}
613
649
650
+ // checkClustersNotPaused checks that no cluster in the graph is paused before proceeding.
651
+ func checkClustersNotPaused (ctx context.Context , proxy Proxy , clusters []* node ) error {
652
+ for i := range clusters {
653
+ cluster := clusters [i ]
654
+ clusterObj := & clusterv1.Cluster {}
655
+ if err := getClusterObj (ctx , proxy , cluster , clusterObj ); err != nil {
656
+ return err
657
+ }
658
+
659
+ if ptr .Deref (clusterObj .Spec .Paused , false ) || annotations .HasPaused (clusterObj ) {
660
+ return errors .Errorf ("cannot start operation while Cluster %s/%s is paused" , clusterObj .Namespace , clusterObj .Name )
661
+ }
662
+ }
663
+
664
+ return nil
665
+ }
666
+
667
+ // checkClusterClassesNotPaused checks that no clusterClass in the graph is paused before proceeding.
668
+ func checkClusterClassesNotPaused (ctx context.Context , proxy Proxy , clusterClasses []* node ) error {
669
+ for i := range clusterClasses {
670
+ clusterClass := clusterClasses [i ]
671
+ clusterClassObj := & clusterv1.ClusterClass {}
672
+ if err := getClusterClassObj (ctx , proxy , clusterClass , clusterClassObj ); err != nil {
673
+ return err
674
+ }
675
+
676
+ if annotations .HasPaused (clusterClassObj ) {
677
+ return errors .Errorf ("cannot start operation while ClusterClass %s/%s is paused" , clusterClassObj .Namespace , clusterClassObj .Name )
678
+ }
679
+ }
680
+
681
+ return nil
682
+ }
683
+
614
684
func waitReadyForMove (ctx context.Context , proxy Proxy , nodes []* node , dryRun bool , backoff wait.Backoff ) error {
615
685
if dryRun {
616
686
return nil
@@ -723,7 +793,8 @@ func pauseClusterClass(ctx context.Context, proxy Proxy, n *node, pause bool, mu
723
793
ObjectMeta : metav1.ObjectMeta {
724
794
Name : n .identity .Name ,
725
795
Namespace : n .identity .Namespace ,
726
- }}, mutators ... )
796
+ },
797
+ }, mutators ... )
727
798
if err != nil {
728
799
return err
729
800
}
@@ -1072,7 +1143,7 @@ func (o *objectMover) backupTargetObject(ctx context.Context, nodeToCreate *node
1072
1143
}
1073
1144
}
1074
1145
1075
- err = os .WriteFile (objectFile , byObj , 0600 )
1146
+ err = os .WriteFile (objectFile , byObj , 0o600 )
1076
1147
if err != nil {
1077
1148
return err
1078
1149
}
@@ -1173,7 +1244,6 @@ func (o *objectMover) deleteGroup(ctx context.Context, group moveGroup) error {
1173
1244
err := retryWithExponentialBackoff (ctx , deleteSourceObjectBackoff , func (ctx context.Context ) error {
1174
1245
return o .deleteSourceObject (ctx , nodeToDelete )
1175
1246
})
1176
-
1177
1247
if err != nil {
1178
1248
errList = append (errList , err )
1179
1249
}
0 commit comments