CLI: Return non-zero exit code when deployment fails in `nomad run` (#11550)
* Exit non-zero from run command if deployment fails * Fix typo in deployment monitor introduced in 0edda11
This commit is contained in:
parent
92eccda949
commit
0e5958d671
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
cli: Return non-zero exit code from monitor if deployment fails
|
||||
```
|
|
@ -181,11 +181,11 @@ func (c *DeploymentStatusCommand) Run(args []string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (c *DeploymentStatusCommand) monitor(client *api.Client, deployID string, index uint64, verbose bool) {
|
||||
func (c *DeploymentStatusCommand) monitor(client *api.Client, deployID string, index uint64, verbose bool) (status string, err error) {
|
||||
if isStdoutTerminal() {
|
||||
c.ttyMonitor(client, deployID, index, verbose)
|
||||
return c.ttyMonitor(client, deployID, index, verbose)
|
||||
} else {
|
||||
c.defaultMonitor(client, deployID, index, verbose)
|
||||
return c.defaultMonitor(client, deployID, index, verbose)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ func isStdoutTerminal() bool {
|
|||
// but only used for tty and non-Windows machines since glint doesn't work with
|
||||
// cmd/PowerShell and non-interactive interfaces
|
||||
// Margins are used to match the text alignment from job run
|
||||
func (c *DeploymentStatusCommand) ttyMonitor(client *api.Client, deployID string, index uint64, verbose bool) {
|
||||
func (c *DeploymentStatusCommand) ttyMonitor(client *api.Client, deployID string, index uint64, verbose bool) (status string, err error) {
|
||||
var length int
|
||||
if verbose {
|
||||
length = fullId
|
||||
|
@ -242,7 +242,9 @@ func (c *DeploymentStatusCommand) ttyMonitor(client *api.Client, deployID string
|
|||
|
||||
UPDATE:
|
||||
for {
|
||||
deploy, meta, err := client.Deployments().Info(deployID, &q)
|
||||
var deploy *api.Deployment
|
||||
var meta *api.QueryMeta
|
||||
deploy, meta, err = client.Deployments().Info(deployID, &q)
|
||||
if err != nil {
|
||||
d.Append(glint.Layout(glint.Style(
|
||||
glint.Text(fmt.Sprintf("%s: Error fetching deployment", formatTime(time.Now()))),
|
||||
|
@ -252,7 +254,7 @@ UPDATE:
|
|||
return
|
||||
}
|
||||
|
||||
status := deploy.Status
|
||||
status = deploy.Status
|
||||
statusComponent = glint.Layout(
|
||||
glint.Text(""),
|
||||
glint.Text(formatTime(time.Now())),
|
||||
|
@ -309,7 +311,8 @@ UPDATE:
|
|||
|
||||
// Wait for rollback to launch
|
||||
time.Sleep(1 * time.Second)
|
||||
rollback, _, err := client.Jobs().LatestDeployment(deploy.JobID, nil)
|
||||
var rollback *api.Deployment
|
||||
rollback, _, err = client.Jobs().LatestDeployment(deploy.JobID, nil)
|
||||
|
||||
if err != nil {
|
||||
d.Append(glint.Layout(glint.Style(
|
||||
|
@ -342,7 +345,7 @@ UPDATE:
|
|||
glint.Text(fmt.Sprintf("✓ Deployment %q %s", limit(deployID, length), status)),
|
||||
).Row().MarginLeft(2)
|
||||
break UPDATE
|
||||
case structs.DeploymentStatusCancelled, structs.DeploymentStatusDescriptionBlocked:
|
||||
case structs.DeploymentStatusCancelled, structs.DeploymentStatusBlocked:
|
||||
endSpinner = glint.Layout(
|
||||
glint.Text(fmt.Sprintf("! Deployment %q %s", limit(deployID, length), status)),
|
||||
).Row().MarginLeft(2)
|
||||
|
@ -355,10 +358,11 @@ UPDATE:
|
|||
// Render one final time with completion message
|
||||
d.Set(endSpinner, statusComponent, glint.Text(""))
|
||||
d.RenderFrame()
|
||||
return
|
||||
}
|
||||
|
||||
// Used for Windows and non-tty
|
||||
func (c *DeploymentStatusCommand) defaultMonitor(client *api.Client, deployID string, index uint64, verbose bool) {
|
||||
func (c *DeploymentStatusCommand) defaultMonitor(client *api.Client, deployID string, index uint64, verbose bool) (status string, err error) {
|
||||
writer := uilive.New()
|
||||
writer.Start()
|
||||
defer writer.Stop()
|
||||
|
@ -377,13 +381,15 @@ func (c *DeploymentStatusCommand) defaultMonitor(client *api.Client, deployID st
|
|||
}
|
||||
|
||||
for {
|
||||
deploy, meta, err := client.Deployments().Info(deployID, &q)
|
||||
var deploy *api.Deployment
|
||||
var meta *api.QueryMeta
|
||||
deploy, meta, err = client.Deployments().Info(deployID, &q)
|
||||
if err != nil {
|
||||
c.Ui.Error(c.Colorize().Color(fmt.Sprintf("%s: Error fetching deployment", formatTime(time.Now()))))
|
||||
return
|
||||
}
|
||||
|
||||
status := deploy.Status
|
||||
status = deploy.Status
|
||||
info := formatTime(time.Now())
|
||||
info += fmt.Sprintf("\n%s", formatDeployment(client, deploy, length))
|
||||
|
||||
|
@ -413,7 +419,8 @@ func (c *DeploymentStatusCommand) defaultMonitor(client *api.Client, deployID st
|
|||
if hasAutoRevert(deploy) {
|
||||
// Wait for rollback to launch
|
||||
time.Sleep(1 * time.Second)
|
||||
rollback, _, err := client.Jobs().LatestDeployment(deploy.JobID, nil)
|
||||
var rollback *api.Deployment
|
||||
rollback, _, err = client.Jobs().LatestDeployment(deploy.JobID, nil)
|
||||
|
||||
// Separate rollback monitoring from failed deployment
|
||||
// Needs to be after time.Sleep or it messes up the formatting
|
||||
|
@ -436,7 +443,7 @@ func (c *DeploymentStatusCommand) defaultMonitor(client *api.Client, deployID st
|
|||
}
|
||||
return
|
||||
|
||||
case structs.DeploymentStatusSuccessful, structs.DeploymentStatusCancelled, structs.DeploymentStatusDescriptionBlocked:
|
||||
case structs.DeploymentStatusSuccessful, structs.DeploymentStatusCancelled, structs.DeploymentStatusBlocked:
|
||||
return
|
||||
default:
|
||||
q.WaitIndex = meta.LastIndex
|
||||
|
|
|
@ -300,7 +300,10 @@ func (m *monitor) monitor(evalID string) int {
|
|||
meta := new(Meta)
|
||||
meta.Ui = m.ui
|
||||
cmd := &DeploymentStatusCommand{Meta: *meta}
|
||||
cmd.monitor(m.client, dID, 0, verbose)
|
||||
status, err := cmd.monitor(m.client, dID, 0, verbose)
|
||||
if err != nil || status != structs.DeploymentStatusSuccessful {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
// Treat scheduling failures specially using a dedicated exit code.
|
||||
|
|
|
@ -34,7 +34,8 @@ exit after scheduling and deployment have finished or failed.
|
|||
On successful job submission and scheduling, exit code 0 will be returned. If
|
||||
there are job placement issues encountered (unsatisfiable constraints, resource
|
||||
exhaustion, etc), then the exit code will be 2. Any other errors, including
|
||||
client connection issues or internal errors, are indicated by exit code 1.
|
||||
deployment failures, client connection issues, or internal errors, are indicated
|
||||
by exit code 1.
|
||||
|
||||
If the job has specified the region, the `-region` flag and `$NOMAD_REGION`
|
||||
environment variable are overridden and the job's region is used.
|
||||
|
|
Loading…
Reference in New Issue