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