github.com/blixtra/nomad@v0.7.2-0.20171221000451-da9a1d7bb050/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/flag-helpers" 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 General Options: 30 31 ` + generalOptionsUsage() + ` 32 33 Promote Options: 34 35 -group 36 Group may be specified many times and is used to promote that particular 37 group. If no specific groups are specified, all groups are promoted. 38 39 -detach 40 Return immediately instead of entering monitor mode. After deployment 41 resume, the evaluation ID will be printed to the screen, which can be used 42 to examine the evaluation using the eval-status command. 43 44 -verbose 45 Display full information. 46 ` 47 return strings.TrimSpace(helpText) 48 } 49 50 func (c *DeploymentPromoteCommand) Synopsis() string { 51 return "Promote canaries in a deployment" 52 } 53 54 func (c *DeploymentPromoteCommand) AutocompleteFlags() complete.Flags { 55 return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), 56 complete.Flags{ 57 "-group": complete.PredictAnything, 58 "-detach": complete.PredictNothing, 59 "-verbose": complete.PredictNothing, 60 }) 61 } 62 63 func (c *DeploymentPromoteCommand) AutocompleteArgs() complete.Predictor { 64 return complete.PredictFunc(func(a complete.Args) []string { 65 client, err := c.Meta.Client() 66 if err != nil { 67 return nil 68 } 69 70 resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Deployments, nil) 71 if err != nil { 72 return []string{} 73 } 74 return resp.Matches[contexts.Deployments] 75 }) 76 } 77 78 func (c *DeploymentPromoteCommand) Run(args []string) int { 79 var detach, verbose bool 80 var groups []string 81 82 flags := c.Meta.FlagSet("deployment promote", FlagSetClient) 83 flags.Usage = func() { c.Ui.Output(c.Help()) } 84 flags.BoolVar(&detach, "detach", false, "") 85 flags.BoolVar(&verbose, "verbose", false, "") 86 flags.Var((*flaghelper.StringFlag)(&groups), "group", "") 87 88 if err := flags.Parse(args); err != nil { 89 return 1 90 } 91 92 // Check that we got no arguments 93 args = flags.Args() 94 if l := len(args); l != 1 { 95 c.Ui.Error(c.Help()) 96 return 1 97 } 98 dID := args[0] 99 100 // Truncate the id unless full length is requested 101 length := shortId 102 if verbose { 103 length = fullId 104 } 105 106 // Get the HTTP client 107 client, err := c.Meta.Client() 108 if err != nil { 109 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 110 return 1 111 } 112 113 // Do a prefix lookup 114 deploy, possible, err := getDeployment(client.Deployments(), dID) 115 if err != nil { 116 c.Ui.Error(fmt.Sprintf("Error retrieving deployment: %s", err)) 117 return 1 118 } 119 120 if len(possible) != 0 { 121 c.Ui.Error(fmt.Sprintf("Prefix matched multiple deployments\n\n%s", formatDeployments(possible, length))) 122 return 1 123 } 124 125 var u *api.DeploymentUpdateResponse 126 if len(groups) == 0 { 127 u, _, err = client.Deployments().PromoteAll(deploy.ID, nil) 128 } else { 129 u, _, err = client.Deployments().PromoteGroups(deploy.ID, groups, nil) 130 } 131 132 if err != nil { 133 c.Ui.Error(fmt.Sprintf("Error promoting deployment: %s", err)) 134 return 1 135 } 136 137 // Nothing to do 138 evalCreated := u.EvalID != "" 139 if detach || !evalCreated { 140 return 0 141 } 142 143 mon := newMonitor(c.Ui, client, length) 144 return mon.monitor(u.EvalID, false) 145 }