github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/command/deployment_fail.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/hashicorp/nomad/api/contexts" 8 "github.com/posener/complete" 9 ) 10 11 type DeploymentFailCommand struct { 12 Meta 13 } 14 15 func (c *DeploymentFailCommand) Help() string { 16 helpText := ` 17 Usage: nomad deployment fail [options] <deployment id> 18 19 Fail is used to mark a deployment as failed. Failing a deployment will 20 stop the placement of new allocations as part of rolling deployment and 21 if the job is configured to auto revert, the job will attempt to roll back to a 22 stable version. 23 24 When ACLs are enabled, this command requires a token with the 'submit-job' 25 and 'read-job' capabilities for the deployment's namespace. 26 27 General Options: 28 29 ` + generalOptionsUsage(usageOptsDefault) + ` 30 31 Fail Options: 32 33 -detach 34 Return immediately instead of entering monitor mode. After deployment 35 resume, the evaluation ID will be printed to the screen, which can be used 36 to examine the evaluation using the eval-status command. 37 38 -verbose 39 Display full information. 40 ` 41 return strings.TrimSpace(helpText) 42 } 43 44 func (c *DeploymentFailCommand) Synopsis() string { 45 return "Manually fail a deployment" 46 } 47 48 func (c *DeploymentFailCommand) AutocompleteFlags() complete.Flags { 49 return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), 50 complete.Flags{ 51 "-detach": complete.PredictNothing, 52 "-verbose": complete.PredictNothing, 53 }) 54 } 55 56 func (c *DeploymentFailCommand) AutocompleteArgs() complete.Predictor { 57 return complete.PredictFunc(func(a complete.Args) []string { 58 client, err := c.Meta.Client() 59 if err != nil { 60 return nil 61 } 62 63 resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Deployments, nil) 64 if err != nil { 65 return []string{} 66 } 67 return resp.Matches[contexts.Deployments] 68 }) 69 } 70 71 func (c *DeploymentFailCommand) Name() string { return "deployment fail" } 72 73 func (c *DeploymentFailCommand) Run(args []string) int { 74 var detach, verbose bool 75 76 flags := c.Meta.FlagSet(c.Name(), FlagSetClient) 77 flags.Usage = func() { c.Ui.Output(c.Help()) } 78 flags.BoolVar(&detach, "detach", false, "") 79 flags.BoolVar(&verbose, "verbose", false, "") 80 81 if err := flags.Parse(args); err != nil { 82 return 1 83 } 84 85 // Check that we got one argument 86 args = flags.Args() 87 if l := len(args); l != 1 { 88 c.Ui.Error("This command takes one argument: <deployment id>") 89 c.Ui.Error(commandErrorText(c)) 90 return 1 91 } 92 93 dID := args[0] 94 95 // Truncate the id unless full length is requested 96 length := shortId 97 if verbose { 98 length = fullId 99 } 100 101 // Get the HTTP client 102 client, err := c.Meta.Client() 103 if err != nil { 104 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 105 return 1 106 } 107 108 // Do a prefix lookup 109 deploy, possible, err := getDeployment(client.Deployments(), dID) 110 if err != nil { 111 c.Ui.Error(fmt.Sprintf("Error retrieving deployment: %s", err)) 112 return 1 113 } 114 115 if len(possible) != 0 { 116 c.Ui.Error(fmt.Sprintf("Prefix matched multiple deployments\n\n%s", formatDeployments(possible, length))) 117 return 1 118 } 119 120 u, _, err := client.Deployments().Fail(deploy.ID, nil) 121 if err != nil { 122 c.Ui.Error(fmt.Sprintf("Error failing deployment: %s", err)) 123 return 1 124 } 125 126 if u.RevertedJobVersion == nil { 127 c.Ui.Output(fmt.Sprintf("Deployment %q failed", deploy.ID)) 128 } else { 129 c.Ui.Output(fmt.Sprintf("Deployment %q failed. Auto-reverted to job version %d.", deploy.ID, *u.RevertedJobVersion)) 130 } 131 132 evalCreated := u.EvalID != "" 133 134 // Nothing to do 135 if !evalCreated { 136 return 0 137 } 138 139 if detach { 140 c.Ui.Output("Evaluation ID: " + u.EvalID) 141 return 0 142 } 143 144 c.Ui.Output("") 145 mon := newMonitor(c.Ui, client, length) 146 return mon.monitor(u.EvalID) 147 }