-
Notifications
You must be signed in to change notification settings - Fork 88
/
stop.go
164 lines (137 loc) · 3.97 KB
/
stop.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package job
import (
"fmt"
"io"
"github.com/bacalhau-project/bacalhau/pkg/publicapi/apimodels"
"github.com/spf13/cobra"
"k8s.io/kubectl/pkg/util/i18n"
"github.com/bacalhau-project/bacalhau/cmd/util"
"github.com/bacalhau-project/bacalhau/cmd/util/printer"
"github.com/bacalhau-project/bacalhau/pkg/bacerrors"
"github.com/bacalhau-project/bacalhau/pkg/util/templates"
)
var (
stopLong = templates.LongDesc(i18n.T(`
Stop a previously submitted job.
`))
//nolint:lll // Documentation
stopExample = templates.Examples(i18n.T(`
# Stop a previously submitted job
bacalhau job stop j-51225160-807e-48b8-88c9-28311c7899e1
# Stop a job, with a short ID.
bacalhau job stop j-51225160
`))
)
var (
checkingJobStatusMessage = i18n.T("Checking job status")
connectingMessage = i18n.T("Connecting to network")
gettingJobMessage = i18n.T("Verifying job state")
stoppingJobMessage = i18n.T("Stopping job")
jobAlreadyCompleteMessage = i18n.T(`Job is already in a terminal state.
The current state is: %s
`)
)
type StopOptions struct {
Quiet bool
}
func NewStopOptions() *StopOptions {
return &StopOptions{
Quiet: false,
}
}
func NewStopCmd() *cobra.Command {
o := NewStopOptions()
stopCmd := &cobra.Command{
Use: "stop [id]",
Short: "Stop a previously submitted job",
Long: stopLong,
Example: stopExample,
Args: cobra.ExactArgs(1),
RunE: o.run,
}
stopCmd.PersistentFlags().BoolVar(&o.Quiet, "quiet", o.Quiet,
`Do not print anything to stdout or stderr`,
)
return stopCmd
}
func (o *StopOptions) run(cmd *cobra.Command, cmdArgs []string) error {
ctx := cmd.Context()
if o.Quiet {
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
}
cmd.Printf("%s\n\n", checkingJobStatusMessage)
widestString := findWidestString(
checkingJobStatusMessage,
connectingMessage,
gettingJobMessage,
stoppingJobMessage,
)
writer := cmd.OutOrStdout()
if o.Quiet {
writer = io.Discard
}
// Create a spinner that will exit if/when it sees ctrl-c
spinner, err := printer.NewSpinner(ctx, writer, widestString, true)
if err != nil {
return err
}
spinner.Run()
requestedJobID := cmdArgs[0]
if requestedJobID == "" {
var byteResult []byte
byteResult, err = util.ReadFromStdinIfAvailable(cmd)
if err != nil {
return fmt.Errorf("unknown error reading from file: %s", err)
}
requestedJobID = string(byteResult)
}
// Let the user know we are initiating the request
spinner.NextStep(connectingMessage)
apiClient := util.GetAPIClientV2(ctx)
// Fetch the job information so we can check whether the task is already
// terminal or not. We will not send requests if it is.
spinner.NextStep(gettingJobMessage)
response, err := apiClient.Jobs().Get(&apimodels.GetJobRequest{
JobID: requestedJobID,
})
if err != nil {
spinner.Done(printer.StopFailed)
return err
}
// Check status to make sure there is something to be stopped. If it is currently
// in a terminal state, then we'll exit immediately
job := response.Job
if job.IsTerminal() {
spinner.Done(printer.StopFailed)
errorMessage := fmt.Errorf(jobAlreadyCompleteMessage, job.State.StateType.String())
return errorMessage
}
// Submit a request to stop the specified job. It is the responsibility of the
// requester to decide if we are allowed to do that or not.
spinner.NextStep(stoppingJobMessage)
stopResponse, err := apiClient.Jobs().Stop(&apimodels.StopJobRequest{
JobID: requestedJobID,
Reason: "Stopped at user request",
})
if err != nil {
spinner.Done(printer.StopFailed)
if errResp, ok := err.(*bacerrors.ErrorResponse); ok {
return errResp
}
return fmt.Errorf("unknown error trying to stop job (ID: %s): %w", requestedJobID, err)
}
spinner.Done(printer.StopSuccess)
cmd.Printf("\nJob stop successfully submitted with evaluation ID: %s\n", stopResponse.EvaluationID)
return nil
}
func findWidestString(messages ...string) int {
widest := 0
for _, msg := range messages {
msgLen := len(msg)
if msgLen > widest {
widest = msgLen
}
}
return widest
}