github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/command/deployment_promote.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/hashicorp/nomad/api" 8 "github.com/hashicorp/nomad/api/contexts" 9 flaghelper "github.com/hashicorp/nomad/helper/flags" 10 "github.com/posener/complete" 11 ) 12 13 type DeploymentPromoteCommand struct { 14 Meta 15 } 16 17 func (c *DeploymentPromoteCommand) Help() string { 18 helpText := ` 19 Usage: nomad deployment promote [options] <deployment id> 20 21 Promote is used to promote task groups in a deployment. Promotion should occur 22 when the deployment has placed canaries for a task group and those canaries have 23 been deemed healthy. When a task group is promoted, the rolling upgrade of the 24 remaining allocations is unblocked. If the canaries are found to be unhealthy, 25 the deployment may either be failed using the "nomad deployment fail" command, 26 the job can be failed forward by submitting a new version or failed backwards by 27 reverting to an older version using the "nomad job revert" command. 28 29 When ACLs are enabled, this command requires a token with the 'submit-job' 30 and 'read-job' capabilities for the deployment's namespace. 31 32 General Options: 33 34 ` + generalOptionsUsage(usageOptsDefault) + ` 35 36 Promote Options: 37 38 -group 39 Group may be specified many times and is used to promote that particular 40 group. If no specific groups are specified, all groups are promoted. 41 42 -detach 43 Return immediately instead of entering monitor mode. After deployment 44 resume, the evaluation ID will be printed to the screen, which can be used 45 to examine the evaluation using the eval-status command. 46 47 -verbose 48 Display full information. 49 ` 50 return strings.TrimSpace(helpText) 51 } 52 53 func (c *DeploymentPromoteCommand) Synopsis() string { 54 return "Promote canaries in a deployment" 55 } 56 57 func (c *DeploymentPromoteCommand) AutocompleteFlags() complete.Flags { 58 return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), 59 complete.Flags{ 60 "-group": complete.PredictAnything, 61 "-detach": complete.PredictNothing, 62 "-verbose": complete.PredictNothing, 63 }) 64 } 65 66 func (c *DeploymentPromoteCommand) AutocompleteArgs() complete.Predictor { 67 return complete.PredictFunc(func(a complete.Args) []string { 68 client, err := c.Meta.Client() 69 if err != nil { 70 return nil 71 } 72 73 resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Deployments, nil) 74 if err != nil { 75 return []string{} 76 } 77 return resp.Matches[contexts.Deployments] 78 }) 79 } 80 81 func (c *DeploymentPromoteCommand) Name() string { return "deployment promote" } 82 83 func (c *DeploymentPromoteCommand) Run(args []string) int { 84 var detach, verbose bool 85 var groups []string 86 87 flags := c.Meta.FlagSet(c.Name(), FlagSetClient) 88 flags.Usage = func() { c.Ui.Output(c.Help()) } 89 flags.BoolVar(&detach, "detach", false, "") 90 flags.BoolVar(&verbose, "verbose", false, "") 91 flags.Var((*flaghelper.StringFlag)(&groups), "group", "") 92 93 if err := flags.Parse(args); err != nil { 94 return 1 95 } 96 97 // Check that we got exactly one argument 98 args = flags.Args() 99 if l := len(args); l != 1 { 100 c.Ui.Error("This command takes one argument: <deployment id>") 101 c.Ui.Error(commandErrorText(c)) 102 return 1 103 } 104 dID := args[0] 105 106 // Truncate the id unless full length is requested 107 length := shortId 108 if verbose { 109 length = fullId 110 } 111 112 // Get the HTTP client 113 client, err := c.Meta.Client() 114 if err != nil { 115 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 116 return 1 117 } 118 119 // Do a prefix lookup 120 deploy, possible, err := getDeployment(client.Deployments(), dID) 121 if err != nil { 122 c.Ui.Error(fmt.Sprintf("Error retrieving deployment: %s", err)) 123 return 1 124 } 125 126 if len(possible) != 0 { 127 c.Ui.Error(fmt.Sprintf("Prefix matched multiple deployments\n\n%s", formatDeployments(possible, length))) 128 return 1 129 } 130 131 var u *api.DeploymentUpdateResponse 132 if len(groups) == 0 { 133 u, _, err = client.Deployments().PromoteAll(deploy.ID, nil) 134 } else { 135 u, _, err = client.Deployments().PromoteGroups(deploy.ID, groups, nil) 136 } 137 138 if err != nil { 139 c.Ui.Error(fmt.Sprintf("Error promoting deployment: %s", err)) 140 return 1 141 } 142 143 evalCreated := u.EvalID != "" 144 145 // Nothing to do 146 if !evalCreated { 147 return 0 148 } 149 150 if detach { 151 c.Ui.Output("Evaluation ID: " + u.EvalID) 152 return 0 153 } 154 155 mon := newMonitor(c.Ui, client, length) 156 return mon.monitor(u.EvalID) 157 }