From d69fa38aeb831e10ed1b2c867551755ebc107c38 Mon Sep 17 00:00:00 2001 From: Jon Huhn Date: Fri, 18 Aug 2023 10:39:10 -0500 Subject: [PATCH] :seedling: check resource blocking clusterctl move during discovery --- cmd/clusterctl/client/cluster/mover.go | 4 ++++ cmd/clusterctl/client/cluster/mover_test.go | 21 ++++++++++++++++++++ cmd/clusterctl/client/cluster/objectgraph.go | 6 ++++++ 3 files changed, 31 insertions(+) diff --git a/cmd/clusterctl/client/cluster/mover.go b/cmd/clusterctl/client/cluster/mover.go index 5b9ba98dc4cc..f399fb18a6a4 100644 --- a/cmd/clusterctl/client/cluster/mover.go +++ b/cmd/clusterctl/client/cluster/mover.go @@ -623,6 +623,10 @@ func waitReadyForMove(proxy Proxy, nodes []*node, dryRun bool, backoff wait.Back } for _, n := range nodes { + if !n.blockingMove { + continue + } + obj := &metav1.PartialObjectMetadata{ ObjectMeta: metav1.ObjectMeta{ Name: n.identity.Name, diff --git a/cmd/clusterctl/client/cluster/mover_test.go b/cmd/clusterctl/client/cluster/mover_test.go index 823ffb432990..bbcb847978f1 100644 --- a/cmd/clusterctl/client/cluster/mover_test.go +++ b/cmd/clusterctl/client/cluster/mover_test.go @@ -2296,6 +2296,7 @@ func TestWaitReadyForMove(t *testing.T) { tests := []struct { name string moveBlocked bool + doUnblock bool wantErr bool }{ { @@ -2308,6 +2309,12 @@ func TestWaitReadyForMove(t *testing.T) { moveBlocked: false, wantErr: false, }, + { + name: "moving blocked cluster that is eventually unblocked should succeed", + moveBlocked: true, + doUnblock: true, + wantErr: false, + }, } for _, tt := range tests { @@ -2337,6 +2344,14 @@ func TestWaitReadyForMove(t *testing.T) { cluster.SetAnnotations(anns) g.Expect(c.Update(ctx, cluster)).To(Succeed()) + + if tt.doUnblock { + go func() { + time.Sleep(50 * time.Millisecond) + delete(cluster.Annotations, clusterctlv1.BlockMoveAnnotation) + g.Expect(c.Update(ctx, cluster)).To(Succeed()) + }() + } } // Get all the types to be considered for discovery @@ -2348,6 +2363,12 @@ func TestWaitReadyForMove(t *testing.T) { backoff := wait.Backoff{ Steps: 1, } + if tt.doUnblock { + backoff = wait.Backoff{ + Duration: 20 * time.Millisecond, + Steps: 10, + } + } err := waitReadyForMove(graph.proxy, graph.getMoveNodes(), false, backoff) if tt.wantErr { g.Expect(err).To(HaveOccurred()) diff --git a/cmd/clusterctl/client/cluster/objectgraph.go b/cmd/clusterctl/client/cluster/objectgraph.go index b0934b45c7dc..18ad47b2275a 100644 --- a/cmd/clusterctl/client/cluster/objectgraph.go +++ b/cmd/clusterctl/client/cluster/objectgraph.go @@ -91,6 +91,10 @@ type node struct { // E.g. for the cluster object we capture information to see if the cluster uses a manged topology // and the cluster class used. additionalInfo map[string]interface{} + + // blockingMove is true when the object should prevent a move operation from proceeding as indicated by + // the presence of the block-move annotation. + blockingMove bool } type discoveryTypeInfo struct { @@ -319,6 +323,8 @@ func (o *objectGraph) objMetaToNode(obj *unstructured.Unstructured, n *node) { n.isGlobal = true } } + + _, n.blockingMove = obj.GetAnnotations()[clusterctlv1.BlockMoveAnnotation] } // getDiscoveryTypes returns the list of TypeMeta to be considered for the move discovery phase.