diff --git a/internal/planner/deployment.go b/internal/planner/deployment.go index 4c6a38b..526fbfc 100644 --- a/internal/planner/deployment.go +++ b/internal/planner/deployment.go @@ -133,10 +133,6 @@ func (p *inPlaceDeploymentPlanner) BuildPlan( Namespace: ns, NodeNames: nodeNames, }}, - {task.TaskTypeMarkNodesReady, &task.MarkNodesReadyParams{ - Namespace: ns, - NodeNames: nodeNames, - }}, } tasks := make([]seiv1alpha1.PlannedTask, len(prog)) diff --git a/internal/planner/deployment_test.go b/internal/planner/deployment_test.go index 8688c9c..2cfe488 100644 --- a/internal/planner/deployment_test.go +++ b/internal/planner/deployment_test.go @@ -30,11 +30,10 @@ func TestInPlacePlan_ThreeTasks(t *testing.T) { g.Expect(err).NotTo(HaveOccurred()) g.Expect(plan.Phase).To(Equal(seiv1alpha1.TaskPlanActive)) - g.Expect(plan.Tasks).To(HaveLen(3)) + g.Expect(plan.Tasks).To(HaveLen(2)) g.Expect(plan.Tasks[0].Type).To(Equal(task.TaskTypeUpdateNodeSpecs)) g.Expect(plan.Tasks[1].Type).To(Equal(task.TaskTypeAwaitSpecUpdate)) - g.Expect(plan.Tasks[2].Type).To(Equal(task.TaskTypeMarkNodesReady)) for i, pt := range plan.Tasks { g.Expect(pt.Status).To(Equal(seiv1alpha1.TaskPending), "task[%d] should be Pending", i) @@ -52,9 +51,4 @@ func TestInPlacePlan_ThreeTasks(t *testing.T) { g.Expect(json.Unmarshal(plan.Tasks[1].Params.Raw, &awaitParams)).To(Succeed()) g.Expect(awaitParams.Namespace).To(Equal("pacific-1")) g.Expect(awaitParams.NodeNames).To(Equal([]string{"wave-group-0", "wave-group-1", "wave-group-2"})) - - var markParams task.MarkNodesReadyParams - g.Expect(json.Unmarshal(plan.Tasks[2].Params.Raw, &markParams)).To(Succeed()) - g.Expect(markParams.Namespace).To(Equal("pacific-1")) - g.Expect(markParams.NodeNames).To(Equal([]string{"wave-group-0", "wave-group-1", "wave-group-2"})) } diff --git a/internal/task/deployment.go b/internal/task/deployment.go index daf1622..2b291fd 100644 --- a/internal/task/deployment.go +++ b/internal/task/deployment.go @@ -7,7 +7,6 @@ const ( TaskTypeCreateEntrantNodes = "create-entrant-nodes" TaskTypeUpdateNodeSpecs = "update-node-specs" TaskTypeAwaitSpecUpdate = "await-spec-update" - TaskTypeMarkNodesReady = "mark-nodes-ready" TaskTypeSubmitHaltSignal = "submit-halt-signal" TaskTypeAwaitNodesAtHeight = "await-nodes-at-height" TaskTypeAwaitNodesCaughtUp = "await-nodes-caught-up" @@ -74,13 +73,6 @@ type AwaitSpecUpdateParams struct { NodeNames []string `json:"nodeNames"` } -// MarkNodesReadyParams holds parameters for submitting mark-ready to -// each node's sidecar after an InPlace rollout completes. -type MarkNodesReadyParams struct { - Namespace string `json:"namespace"` - NodeNames []string `json:"nodeNames"` -} - // TeardownNodesParams holds parameters for deleting incumbent SeiNode resources. type TeardownNodesParams struct { Namespace string `json:"namespace"` diff --git a/internal/task/deployment_update.go b/internal/task/deployment_update.go index 7ca6483..1809be2 100644 --- a/internal/task/deployment_update.go +++ b/internal/task/deployment_update.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" - sidecar "github.com/sei-protocol/seictl/sidecar/client" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/log" @@ -70,7 +69,11 @@ func (e *updateNodeSpecsExecution) Status(_ context.Context) ExecutionStatus { return e.status } -// --- AwaitSpecUpdate: waits for StatefulSet rollout to complete --- +// --- AwaitSpecUpdate: waits for each node's image update to complete --- +// This task polls status.currentImage on each SeiNode. The SeiNode +// controller's NodeUpdate plan handles the full rollout lifecycle +// (apply-statefulset, observe-image, mark-ready) and stamps currentImage +// only after the rollout is complete and the sidecar is re-initialized. type awaitSpecUpdateExecution struct { taskBase @@ -114,72 +117,3 @@ func (e *awaitSpecUpdateExecution) Status(ctx context.Context) ExecutionStatus { e.complete() return ExecutionComplete } - -// --- MarkNodesReady: submits mark-ready to each node's sidecar --- - -type markNodesReadyExecution struct { - taskBase - params MarkNodesReadyParams - cfg ExecutionConfig - marked map[string]bool -} - -func deserializeMarkNodesReady(id string, params json.RawMessage, cfg ExecutionConfig) (TaskExecution, error) { - var p MarkNodesReadyParams - if len(params) > 0 { - if err := json.Unmarshal(params, &p); err != nil { - return nil, fmt.Errorf("deserializing mark-nodes-ready params: %w", err) - } - } - return &markNodesReadyExecution{ - taskBase: taskBase{id: id, status: ExecutionRunning}, - params: p, - cfg: cfg, - marked: make(map[string]bool, len(p.NodeNames)), - }, nil -} - -func (e *markNodesReadyExecution) Execute(_ context.Context) error { return nil } - -func (e *markNodesReadyExecution) Status(ctx context.Context) ExecutionStatus { - if s, done := e.isTerminal(); done { - return s - } - logger := log.FromContext(ctx) - - allReady := true - for _, name := range e.params.NodeNames { - if e.marked[name] { - continue - } - node := &seiv1alpha1.SeiNode{} - if err := e.cfg.KubeClient.Get(ctx, types.NamespacedName{Name: name, Namespace: e.params.Namespace}, node); err != nil { - allReady = false - continue - } - sc, err := sidecarClientForNode(node) - if err != nil { - allReady = false - continue - } - resp, err := sc.Status(ctx) - if err != nil { - allReady = false - continue - } - if resp.Status == sidecar.Ready { - e.marked[name] = true - continue - } - if _, err := sc.SubmitTask(ctx, sidecar.TaskRequest{Type: sidecar.TaskTypeMarkReady}); err != nil { - logger.V(1).Info("mark-ready submission failed", "node", name, "error", err) - } - allReady = false - } - - if allReady { - e.complete() - return ExecutionComplete - } - return ExecutionRunning -} diff --git a/internal/task/deployment_update_test.go b/internal/task/deployment_update_test.go index 987766c..8442265 100644 --- a/internal/task/deployment_update_test.go +++ b/internal/task/deployment_update_test.go @@ -237,50 +237,3 @@ func TestAwaitSpecUpdate_RunningWhenNodeNotFound(t *testing.T) { t.Fatalf("expected Running for missing node, got %s", exec.Status(context.Background())) } } - -// --- MarkNodesReady --- - -func TestMarkNodesReady_Deserializes(t *testing.T) { - group := testDeploymentGroup() - cfg := testDeploymentCfg(t, group) - - params := MarkNodesReadyParams{ - Namespace: "sei", - NodeNames: []string{"wave-0", "wave-1"}, - } - raw, _ := json.Marshal(params) - exec, err := deserializeMarkNodesReady("id-3", raw, cfg) - if err != nil { - t.Fatalf("deserialize: %v", err) - } - - mnr, ok := exec.(*markNodesReadyExecution) - if !ok { - t.Fatal("expected *markNodesReadyExecution") - } - if len(mnr.params.NodeNames) != 2 { - t.Errorf("nodeNames len = %d, want 2", len(mnr.params.NodeNames)) - } - if mnr.params.Namespace != "sei" { - t.Errorf("namespace = %q, want %q", mnr.params.Namespace, "sei") - } -} - -func TestMarkNodesReady_StartsRunning(t *testing.T) { - group := testDeploymentGroup() - cfg := testDeploymentCfg(t, group) - - params := MarkNodesReadyParams{ - Namespace: "sei", - NodeNames: []string{"wave-0"}, - } - raw, _ := json.Marshal(params) - exec, err := deserializeMarkNodesReady("id-3", raw, cfg) - if err != nil { - t.Fatalf("deserialize: %v", err) - } - - if exec.Status(context.Background()) != ExecutionRunning { - t.Fatalf("expected initial status Running, got %s", exec.Status(context.Background())) - } -} diff --git a/internal/task/task.go b/internal/task/task.go index 2d5ac6a..ba168cd 100644 --- a/internal/task/task.go +++ b/internal/task/task.go @@ -213,7 +213,6 @@ var registry = map[string]taskDeserializer{ // Controller-side deployment tasks TaskTypeUpdateNodeSpecs: deserializeUpdateNodeSpecs, TaskTypeAwaitSpecUpdate: deserializeAwaitSpecUpdate, - TaskTypeMarkNodesReady: deserializeMarkNodesReady, TaskTypeCreateEntrantNodes: deserializeCreateEntrantNodes, TaskTypeSubmitHaltSignal: deserializeSubmitHaltSignal, TaskTypeAwaitNodesAtHeight: deserializeAwaitNodesAtHeight,