From f2c74335d685c11ec2f827ad2a6e35ca3e80769d Mon Sep 17 00:00:00 2001 From: dawn Date: Wed, 01 Jul 2026 10:17:42 +0000 Subject: [PATCH] spindle: categorize error messages with a more generic msg then following details Signed-off-by: dawn --- spindle/engines/microvm/agent.go | 2 +- spindle/engines/microvm/engine.go | 23 ++++++++++++++++------- spindle/engines/nixery/engine.go | 20 +++++++++++++------- 3 file(s) changed, 30 insertion(s)(+), 15 deletion(s)(-) diff --git a/spindle/engines/microvm/agent.go b/spindle/engines/microvm/agent.go --- a/spindle/engines/microvm/agent.go +++ b/spindle/engines/microvm/agent.go @@ -235,7 +235,7 @@ } } else if p := msg.ActivateConfigResult; p != nil { if p.Error != "" { - return nil, fmt.Errorf("activate config failed: %s", p.Error) + return nil, errors.New(p.Error) } if p.Toplevel == "" { return nil, fmt.Errorf("activate config returned empty toplevel") diff --git a/spindle/engines/microvm/engine.go b/spindle/engines/microvm/engine.go --- a/spindle/engines/microvm/engine.go +++ b/spindle/engines/microvm/engine.go @@ -187,12 +187,19 @@ return swf, nil } -func (e *Engine) SetupWorkflow(ctx context.Context, wid models.WorkflowId, wf *models.Workflow, wfLogger models.WorkflowLogger) error { +func (e *Engine) SetupWorkflow(ctx context.Context, wid models.WorkflowId, wf *models.Workflow, wfLogger models.WorkflowLogger) (err error) { l := e.l.With("workflow", wid) setupStep := Step{name: "microVM setup", kind: models.StepKindSystem} wfLogger.ControlWriter(-1, setupStep, models.StepStatusStart).Write([]byte{0}) defer wfLogger.ControlWriter(-1, setupStep, models.StepStatusEnd).Write([]byte{0}) + + category := "Failed to setup VM" + defer func() { + if err != nil { + err = fmt.Errorf("%s:\n%w", category, err) + } + }() state, ok := wf.Data.(*workflowState) if !ok || state == nil { @@ -276,6 +283,8 @@ } state.VM = vm + category = "Failed to connect to agent" + acceptCtx, cancelAccept := context.WithTimeout(ctx, agentAcceptTimeout) defer cancelAccept() conn, err := waitAgentConn(acceptCtx, connCh) @@ -332,7 +341,7 @@ step := w.Steps[idx] if s, ok := step.(Step); ok && s.action == activationStepAction { err := e.activateConfig(execCtx, wid, state, s, wfLogger.DataWriter(idx, "stdout")) - return e.classifyStepError(ctx, wid, step, state, stderr, vmExited, err) + return e.classifyStepError(ctx, wid, step, state, stderr, vmExited, "Failed to activate config", err) } env := []string{ "HOME=/workspace", @@ -366,19 +375,19 @@ Stderr: stderr, }) if err != nil { - return e.classifyStepError(ctx, wid, step, state, stderr, vmExited, err) + return e.classifyStepError(ctx, wid, step, state, stderr, vmExited, "User step error", err) } if exitCode != 0 { e.l.Debug("step exited non-zero", "workflow", wid, "step", step.Name(), "exitCode", exitCode) - return engine.ErrWorkflowFailed + return fmt.Errorf("User step error: exited with code %d", exitCode) } return nil } // reads the vm serial logs so we report the tail of that as an error instead of // just "guest agent connection lost: EOF" -func (e *Engine) classifyStepError(ctx context.Context, wid models.WorkflowId, step models.Step, state *workflowState, stderr io.Writer, vmExited *atomic.Bool, err error) error { +func (e *Engine) classifyStepError(ctx context.Context, wid models.WorkflowId, step models.Step, state *workflowState, stderr io.Writer, vmExited *atomic.Bool, category string, err error) error { if err == nil { return nil } @@ -397,7 +406,7 @@ fmt.Fprintln(stderr, reason) l.Error(reason, "oom", oom) } - return errors.New(reason + "; see workflow logs for serial output") + return fmt.Errorf("%s:\n%w", category, errors.New(reason+"; see workflow logs for serial output")) } if errors.Is(err, errGuestTimedOut) || ctx.Err() != nil { @@ -414,7 +423,7 @@ } else { l.Error("step failed", "error", err) } - return err + return fmt.Errorf("%s:\n%w", category, err) } func (e *Engine) activateConfig(ctx context.Context, wid models.WorkflowId, state *workflowState, step Step, out io.Writer) error { diff --git a/spindle/engines/nixery/engine.go b/spindle/engines/nixery/engine.go --- a/spindle/engines/nixery/engine.go +++ b/spindle/engines/nixery/engine.go @@ -195,7 +195,7 @@ return e.slotter.AcquireWorkflowSlot(ctx, wid, wf) } -func (e *Engine) SetupWorkflow(ctx context.Context, wid models.WorkflowId, wf *models.Workflow, wfLogger models.WorkflowLogger) error { +func (e *Engine) SetupWorkflow(ctx context.Context, wid models.WorkflowId, wf *models.Workflow, wfLogger models.WorkflowLogger) (err error) { /// -------------------------INITIAL SETUP------------------------------------------ l := e.l.With("workflow", wid) l.Info("setting up workflow") @@ -209,8 +209,14 @@ wfLogger.ControlWriter(setupStepIdx, setupStep, models.StepStatusStart).Write([]byte{0}) defer wfLogger.ControlWriter(setupStepIdx, setupStep, models.StepStatusEnd).Write([]byte{0}) + defer func() { + if err != nil { + err = fmt.Errorf("Failed to setup container:\n%w", err) + } + }() + /// -------------------------NETWORK CREATION--------------------------------------- - _, err := e.docker.NetworkCreate(ctx, networkName(wid), network.CreateOptions{ + _, err = e.docker.NetworkCreate(ctx, networkName(wid), network.CreateOptions{ Driver: "bridge", }) if err != nil { @@ -402,7 +408,7 @@ Env: envs, }) if err != nil { - return fmt.Errorf("creating exec: %w", err) + return fmt.Errorf("User step error:\ncreating exec: %w", err) } // start tailing logs in background @@ -434,21 +440,21 @@ execInspectResp, err := e.docker.ContainerExecInspect(ctx, mkExecResp.ID) if err != nil { - return err + return fmt.Errorf("User step error:\n%w", err) } if execInspectResp.ExitCode != 0 { inspectResp, err := e.docker.ContainerInspect(ctx, addl.container) if err != nil { - return err + return fmt.Errorf("User step error:\n%w", err) } e.l.Error("workflow failed!", "workflow_id", wid.String(), "exit_code", execInspectResp.ExitCode, "oom_killed", inspectResp.State.OOMKilled) if inspectResp.State.OOMKilled { - return ErrOOMKilled + return fmt.Errorf("User step error:\n%w", ErrOOMKilled) } - return engine.ErrWorkflowFailed + return fmt.Errorf("User step error: exited with code %d", execInspectResp.ExitCode) } return nil -- tangled.sh