github.com/blixtra/nomad@v0.7.2-0.20171221000451-da9a1d7bb050/command/job_dispatch.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "strings" 8 9 "github.com/hashicorp/nomad/api/contexts" 10 flaghelper "github.com/hashicorp/nomad/helper/flag-helpers" 11 "github.com/posener/complete" 12 ) 13 14 type JobDispatchCommand struct { 15 Meta 16 } 17 18 func (c *JobDispatchCommand) Help() string { 19 helpText := ` 20 Usage: nomad job dispatch [options] <parameterized job> [input source] 21 22 Dispatch creates an instance of a parameterized job. A data payload to the 23 dispatched instance can be provided via stdin by using "-" or by specifying a 24 path to a file. Metadata can be supplied by using the meta flag one or more 25 times. 26 27 Upon successful creation, the dispatched job ID will be printed and the 28 triggered evaluation will be monitored. This can be disabled by supplying the 29 detach flag. 30 31 General Options: 32 33 ` + generalOptionsUsage() + ` 34 35 Dispatch Options: 36 37 -meta <key>=<value> 38 Meta takes a key/value pair separated by "=". The metadata key will be 39 merged into the job's metadata. The job may define a default value for the 40 key which is overridden when dispatching. The flag can be provided more than 41 once to inject multiple metadata key/value pairs. Arbitrary keys are not 42 allowed. The parameterized job must allow the key to be merged. 43 44 -detach 45 Return immediately instead of entering monitor mode. After job dispatch, 46 the evaluation ID will be printed to the screen, which can be used to 47 examine the evaluation using the eval-status command. 48 49 -verbose 50 Display full information. 51 ` 52 return strings.TrimSpace(helpText) 53 } 54 55 func (c *JobDispatchCommand) Synopsis() string { 56 return "Dispatch an instance of a parameterized job" 57 } 58 59 func (c *JobDispatchCommand) AutocompleteFlags() complete.Flags { 60 return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), 61 complete.Flags{ 62 "-meta": complete.PredictAnything, 63 "-detach": complete.PredictNothing, 64 "-verbose": complete.PredictNothing, 65 }) 66 } 67 68 func (c *JobDispatchCommand) AutocompleteArgs() complete.Predictor { 69 return complete.PredictFunc(func(a complete.Args) []string { 70 client, err := c.Meta.Client() 71 if err != nil { 72 return nil 73 } 74 75 resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Jobs, nil) 76 if err != nil { 77 return []string{} 78 } 79 return resp.Matches[contexts.Jobs] 80 }) 81 } 82 83 func (c *JobDispatchCommand) Run(args []string) int { 84 var detach, verbose bool 85 var meta []string 86 87 flags := c.Meta.FlagSet("job dispatch", 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)(&meta), "meta", "") 92 93 if err := flags.Parse(args); err != nil { 94 return 1 95 } 96 97 // Truncate the id unless full length is requested 98 length := shortId 99 if verbose { 100 length = fullId 101 } 102 103 // Check that we got exactly one node 104 args = flags.Args() 105 if l := len(args); l < 1 || l > 2 { 106 c.Ui.Error(c.Help()) 107 return 1 108 } 109 110 job := args[0] 111 var payload []byte 112 var readErr error 113 114 // Read the input 115 if len(args) == 2 { 116 switch args[1] { 117 case "-": 118 payload, readErr = ioutil.ReadAll(os.Stdin) 119 default: 120 payload, readErr = ioutil.ReadFile(args[1]) 121 } 122 if readErr != nil { 123 c.Ui.Error(fmt.Sprintf("Error reading input data: %v", readErr)) 124 return 1 125 } 126 } 127 128 // Build the meta 129 metaMap := make(map[string]string, len(meta)) 130 for _, m := range meta { 131 split := strings.SplitN(m, "=", 2) 132 if len(split) != 2 { 133 c.Ui.Error(fmt.Sprintf("Error parsing meta value: %v", m)) 134 return 1 135 } 136 137 metaMap[split[0]] = split[1] 138 } 139 140 // Get the HTTP client 141 client, err := c.Meta.Client() 142 if err != nil { 143 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 144 return 1 145 } 146 147 // Dispatch the job 148 resp, _, err := client.Jobs().Dispatch(job, metaMap, payload, nil) 149 if err != nil { 150 c.Ui.Error(fmt.Sprintf("Failed to dispatch job: %s", err)) 151 return 1 152 } 153 154 // See if an evaluation was created. If the job is periodic there will be no 155 // eval. 156 evalCreated := resp.EvalID != "" 157 158 basic := []string{ 159 fmt.Sprintf("Dispatched Job ID|%s", resp.DispatchedJobID), 160 } 161 if evalCreated { 162 basic = append(basic, fmt.Sprintf("Evaluation ID|%s", limit(resp.EvalID, length))) 163 } 164 c.Ui.Output(formatKV(basic)) 165 166 // Nothing to do 167 if detach || !evalCreated { 168 return 0 169 } 170 171 c.Ui.Output("") 172 mon := newMonitor(c.Ui, client, length) 173 return mon.monitor(resp.EvalID, false) 174 }