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