diff --git a/cmd/playbook.go b/cmd/playbook.go index c46de861e..fb75807d2 100644 --- a/cmd/playbook.go +++ b/cmd/playbook.go @@ -148,13 +148,13 @@ var Run = &cobra.Command{ logger.Fatalf(err.Error()) return } + if action == nil { logger.Errorf("No actions to run") return } for action != nil { - if delayed, err := runner.CheckDelay(ctx, *p, *run, action, step); err != nil { ctx.Errorf("Error running action %s: %v", action.Name, err) break @@ -163,7 +163,6 @@ var Run = &cobra.Command{ } runAction, err := run.StartAction(ctx.DB(), action.Name) - if err != nil { ctx.Errorf("Error starting action %s: %v", action.Name, err) break @@ -175,11 +174,11 @@ var Run = &cobra.Command{ } action, _, err = runner.GetNextActionToRun(ctx, *p, *run) - if action != nil && action.Name == runAction.Name { ctx.Errorf("%v", ctx.Oops().Errorf("Action cycle detected for: %s", action.Name)) shutdown.ShutdownAndExit(1, "") } + if err != nil { ctx.Errorf("Error getting next action %s: %v", action.Name, err) break @@ -197,7 +196,6 @@ var Run = &cobra.Command{ if summary.Run.Status != models.PlaybookRunStatusCompleted { shutdown.ShutdownAndExit(1, fmt.Sprintf("Playbook run status: %s ", summary.Run.Status)) } - }, } diff --git a/playbook/runner/runner.go b/playbook/runner/runner.go index aaefdf2cf..3ea8fd040 100644 --- a/playbook/runner/runner.go +++ b/playbook/runner/runner.go @@ -142,12 +142,22 @@ func CheckDelay(ctx context.Context, playbook models.Playbook, run models.Playbo return false, nil } +func getEligibleAgents(spec v1.PlaybookSpec, action *v1.PlaybookAction) []string { + if len(action.RunsOn) != 0 { + return action.RunsOn + } + + if len(spec.RunsOn) != 0 { + return spec.RunsOn + } + + return []string{Main} +} + // ScheduleRun finds the next action step that needs to run and // creates the PlaybookActionRun in a scheduled status, with an optional agentId func ScheduleRun(ctx context.Context, run models.PlaybookRun) error { - var playbook models.Playbook - if err := ctx.DB().First(&playbook, run.PlaybookID).Error; err != nil { return ctx.Oops("db").Wrap(err) } @@ -179,24 +189,34 @@ func ScheduleRun(ctx context.Context, run models.PlaybookRun) error { }, action.Name)) } - if run.AgentID == nil && (len(action.RunsOn) == 0 || lo.Contains(action.RunsOn, Main)) { + var playbookSpec v1.PlaybookSpec + if err := json.Unmarshal(playbook.Spec, &playbookSpec); err != nil { + return ctx.Oops().Wrap(err) + } + + eligibleAgents := getEligibleAgents(playbookSpec, action) + + agent, err := db.FindFirstAgent(ctx, eligibleAgents...) + if err != nil { + return ctx.Oops("db").Wrap(err) + } else if agent == nil { + return ctx.Oops("db").Wrapf(err, "failed to find any agent (%s)", strings.Join(eligibleAgents, ",")) + } + + if agent.Name == Main { if runAction, err := run.StartAction(ctx.DB(), action.Name); err != nil { return ctx.Oops("db").Wrap(err) } else { ctx.Tracef("started %s (%v) on local", action.Name, runAction.ID) } - } - - if agent, err := db.FindFirstAgent(ctx, action.RunsOn...); err != nil { - return ctx.Oops("db").Wrap(err) - } else if agent == nil { - return ctx.Oops("db").Wrapf(err, "failed to find any agent (%s)", strings.Join(action.RunsOn, ",")) } else { // Assign the action to an agent and step the status to Waiting // When the agent polls for new actions to run, we return and then set the status to Running ctx.Tracef("assigning %s to agent %s", action.Name, agent.Name) return ctx.Oops("db").Wrap(run.Assign(ctx.DB(), agent, action.Name)) } + + return nil } func ExecuteAndSaveAction(ctx context.Context, playbookID any, action *models.PlaybookRunAction, actionSpec v1.PlaybookAction) error { diff --git a/playbook/testdata/agent-runner.yaml b/playbook/testdata/agent-runner.yaml index 269e545ed..5c91e4fb6 100644 --- a/playbook/testdata/agent-runner.yaml +++ b/playbook/testdata/agent-runner.yaml @@ -18,7 +18,7 @@ spec: echo "{{.config.config_class}}" - name: Echo class on agent aws runsOn: - - "aws" + - 'aws' templatesOn: agent exec: script: |