diff --git a/cli/cdsctl/queue.go b/cli/cdsctl/queue.go index eef53ef4e8..9b0c83ba37 100644 --- a/cli/cdsctl/queue.go +++ b/cli/cdsctl/queue.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "strconv" "strings" "time" @@ -28,6 +29,7 @@ var queueCmd = cli.Command{ func queue() *cobra.Command { return cli.NewListCommand(queueCmd, queueRun, []*cobra.Command{ cli.NewCommand(queueUICmd, queueUIRun, nil, withAllCommandModifiers()...), + cli.NewCommand(queueStopAllCmd, queueStopAllRun, nil, withAllCommandModifiers()...), }) } @@ -36,6 +38,90 @@ var queueUICmd = cli.Command{ Short: "Show the current queue", } +var queueStopAllCmd = cli.Command{ + Name: "stopall", + Short: "Stop all job from the queue", + Example: "cdsctl queue stopall", + OptionalArgs: []cli.Arg{ + {Name: _ProjectKey}, + {Name: _WorkflowName}, + }, + Flags: []cli.Flag{ + { + Name: "force", + Usage: "if true, do not ask user before stopping all workflows", + IsValid: func(s string) bool { + if s != "true" && s != "false" { + return false + } + return true + }, + Default: "false", + Type: cli.FlagBool, + }, + }, +} + +func queueStopAllRun(v cli.Values) error { + wantToStopAll := v.GetBool("force") || cli.AskConfirm("Are you sure to want to stop all jobs in the queue?") + if !wantToStopAll { + return nil + } + + jobs, err := client.QueueWorkflowNodeJobRun(sdk.StatusWaiting, sdk.StatusBuilding) + if err != nil { + return err + } + + var nbToStop int64 + for _, jr := range jobs { + projectKey := getVarsInPbj("cds.project", jr.Parameters) + workflowName := getVarsInPbj("cds.workflow", jr.Parameters) + + if v.GetString(_ProjectKey) != "" && projectKey != v.GetString(_ProjectKey) { + continue + } + if v.GetString(_WorkflowName) != "" && workflowName != v.GetString(_WorkflowName) { + continue + } + nbToStop++ + } + + wantToStopAllSure := v.GetBool("force") || cli.AskConfirm(fmt.Sprintf("There are %d worfklows to stop, confirm stopping workflows?", nbToStop)) + if !wantToStopAllSure { + return nil + } + + var stopped int64 + for _, jr := range jobs { + run := getVarsInPbj("cds.run.number", jr.Parameters) + projectKey := getVarsInPbj("cds.project", jr.Parameters) + workflowName := getVarsInPbj("cds.workflow", jr.Parameters) + + if v.GetString(_ProjectKey) != "" && projectKey != v.GetString(_ProjectKey) { + continue + } + if v.GetString(_WorkflowName) != "" && workflowName != v.GetString(_WorkflowName) { + continue + } + + runNumber, err := strconv.ParseInt(run, 10, 64) + if err != nil { + return fmt.Errorf("%s invalid: not a integer for a workflow run. err: %v", run, err) + } + + w, err := client.WorkflowStop(projectKey, workflowName, runNumber) + if err != nil { + fmt.Printf("ERROR while stopping Workflow %s #%d: %v\n", v.GetString(_WorkflowName), w.Number, err) + continue + } + fmt.Printf("Workflow %s #%d has been stopped\n", v.GetString(_WorkflowName), w.Number) + stopped++ + } + fmt.Printf("Nb workflows stopped: %d\n", stopped) + return nil +} + func queueRun(v cli.Values) (cli.ListResult, error) { jobList, err := getJobQueue(sdk.StatusWaiting, sdk.StatusBuilding) if err != nil { @@ -78,7 +164,7 @@ func getJobQueue(status ...string) ([]jobCLI, error) { NodeName: getVarsInPbj("cds.node", jr.Parameters), Status: jr.Status, URL: generateQueueJobURL(baseURL, jr.Parameters), - Since: fmt.Sprintf(sdk.Round(time.Since(jr.Queued), time.Second).String()), + Since: sdk.Round(time.Since(jr.Queued), time.Second).String(), Duration: time.Since(jr.Queued), BookedBy: jr.BookedBy.Name, TriggeredBy: getVarsInPbj("cds.triggered_by.username", jr.Parameters), diff --git a/tests/01_queue_stopall.yml b/tests/01_queue_stopall.yml new file mode 100644 index 0000000000..024956cae7 --- /dev/null +++ b/tests/01_queue_stopall.yml @@ -0,0 +1,6 @@ +name: Queue stop all +version: "2" +testcases: +- name: cdsctl queue stopall + steps: + - script: {{.cdsctl}} -f {{.cdsctl.config}} queue stopall --force diff --git a/tests/test.sh b/tests/test.sh index 35bab5a3ed..26548b3591 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -98,6 +98,11 @@ initialization_tests() { ${CMD} >01_signup_user.yml.output 2>&1 check_failure $? 01_signup_user.yml.output + + CMD="${VENOM} run ${VENOM_OPTS} 01_queue_stopall.yml --var cdsctl.config=${CDSCTL_CONFIG}_admin --var cdsctl=${CDSCTL} --var api.url=${CDS_API_URL}" + echo -e " ${YELLOW}01_queue_stopall.yml ${DARKGRAY}[${CMD}]${NOCOLOR}" + ${CMD} >01_queue_stopall.yml.output 2>&1 + check_failure $? 01_queue_stopall.yml.output } smoke_tests_services() { @@ -146,6 +151,12 @@ workflow_with_integration_tests() { } workflow_with_third_parties() { + echo "Stopping all jobs in queue:" + CMD="${VENOM} run ${VENOM_OPTS} 01_queue_stopall.yml --var cdsctl.config=${CDSCTL_CONFIG}_admin --var cdsctl=${CDSCTL} --var api.url=${CDS_API_URL}" + echo -e " ${YELLOW}01_queue_stopall.yml ${DARKGRAY}[${CMD}]${NOCOLOR}" + ${CMD} >01_queue_stopall.yml.output 2>&1 + check_failure $? 01_queue_stopall.yml.output + if [ -z "$CDS_MODEL_REQ" ]; then echo "missing CDS_MODEL_REQ variable"; exit 1; fi if [ -z "$CDS_REGION_REQ" ]; then echo "missing CDS_REGION_REQ variable"; exit 1; fi echo "Running Workflow with third parties:"