github.com/mattyr/nomad@v0.3.3-0.20160919021406-3485a065154a/command/stop.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 type StopCommand struct { 9 Meta 10 } 11 12 func (c *StopCommand) Help() string { 13 helpText := ` 14 Usage: nomad stop [options] <job> 15 16 Stop an existing job. This command is used to signal allocations 17 to shut down for the given job ID. Upon successful deregistraion, 18 an interactive monitor session will start to display log lines as 19 the job unwinds its allocations and completes shutting down. It 20 is safe to exit the monitor early using ctrl+c. 21 22 General Options: 23 24 ` + generalOptionsUsage() + ` 25 26 Stop Options: 27 28 -detach 29 Return immediately instead of entering monitor mode. After the 30 deregister command is submitted, a new evaluation ID is printed to the 31 screen, which can be used to examine the evaluation using the eval-status 32 command. 33 34 -yes 35 Automatic yes to prompts. 36 37 -verbose 38 Display full information. 39 ` 40 return strings.TrimSpace(helpText) 41 } 42 43 func (c *StopCommand) Synopsis() string { 44 return "Stop a running job" 45 } 46 47 func (c *StopCommand) Run(args []string) int { 48 var detach, verbose, autoYes bool 49 50 flags := c.Meta.FlagSet("stop", FlagSetClient) 51 flags.Usage = func() { c.Ui.Output(c.Help()) } 52 flags.BoolVar(&detach, "detach", false, "") 53 flags.BoolVar(&verbose, "verbose", false, "") 54 flags.BoolVar(&autoYes, "yes", false, "") 55 56 if err := flags.Parse(args); err != nil { 57 return 1 58 } 59 60 // Truncate the id unless full length is requested 61 length := shortId 62 if verbose { 63 length = fullId 64 } 65 66 // Check that we got exactly one job 67 args = flags.Args() 68 if len(args) != 1 { 69 c.Ui.Error(c.Help()) 70 return 1 71 } 72 jobID := args[0] 73 74 // Get the HTTP client 75 client, err := c.Meta.Client() 76 if err != nil { 77 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 78 return 1 79 } 80 81 // Check if the job exists 82 jobs, _, err := client.Jobs().PrefixList(jobID) 83 if err != nil { 84 c.Ui.Error(fmt.Sprintf("Error deregistering job: %s", err)) 85 return 1 86 } 87 if len(jobs) == 0 { 88 c.Ui.Error(fmt.Sprintf("No job(s) with prefix or id %q found", jobID)) 89 return 1 90 } 91 if len(jobs) > 1 && strings.TrimSpace(jobID) != jobs[0].ID { 92 out := make([]string, len(jobs)+1) 93 out[0] = "ID|Type|Priority|Status" 94 for i, job := range jobs { 95 out[i+1] = fmt.Sprintf("%s|%s|%d|%s", 96 job.ID, 97 job.Type, 98 job.Priority, 99 job.Status) 100 } 101 c.Ui.Output(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", formatList(out))) 102 return 0 103 } 104 // Prefix lookup matched a single job 105 job, _, err := client.Jobs().Info(jobs[0].ID, nil) 106 if err != nil { 107 c.Ui.Error(fmt.Sprintf("Error deregistering job: %s", err)) 108 return 1 109 } 110 111 // Confirm the stop if the job was a prefix match. 112 if jobID != job.ID && !autoYes { 113 question := fmt.Sprintf("Are you sure you want to stop job %q? [y/N]", job.ID) 114 answer, err := c.Ui.Ask(question) 115 if err != nil { 116 c.Ui.Error(fmt.Sprintf("Failed to parse answer: %v", err)) 117 return 1 118 } 119 120 if answer == "" || strings.ToLower(answer)[0] == 'n' { 121 // No case 122 c.Ui.Output("Cancelling job stop") 123 return 0 124 } else if strings.ToLower(answer)[0] == 'y' && len(answer) > 1 { 125 // Non exact match yes 126 c.Ui.Output("For confirmation, an exact ‘y’ is required.") 127 return 0 128 } else if answer != "y" { 129 c.Ui.Output("No confirmation detected. For confirmation, an exact 'y' is required.") 130 return 1 131 } 132 } 133 134 // Invoke the stop 135 evalID, _, err := client.Jobs().Deregister(job.ID, nil) 136 if err != nil { 137 c.Ui.Error(fmt.Sprintf("Error deregistering job: %s", err)) 138 return 1 139 } 140 141 // If we are stopping a periodic job there won't be an evalID. 142 if evalID == "" { 143 return 0 144 } 145 146 if detach { 147 c.Ui.Output(evalID) 148 return 0 149 } 150 151 // Start monitoring the stop eval 152 mon := newMonitor(c.Ui, client, length) 153 return mon.monitor(evalID, false) 154 }