1package command
2
3import (
4	"fmt"
5	"io/ioutil"
6	"os"
7	"strings"
8
9	"github.com/posener/complete"
10)
11
12const (
13	// DefaultInitName is the default name we use when
14	// initializing the example file
15	DefaultInitName = "example.nomad"
16)
17
18// JobInitCommand generates a new job template that you can customize to your
19// liking, like vagrant init
20type JobInitCommand struct {
21	Meta
22}
23
24func (c *JobInitCommand) Help() string {
25	helpText := `
26Usage: nomad job init <filename>
27Alias: nomad init <filename>
28
29  Creates an example job file that can be used as a starting point to customize
30  further. If no filename is given, the default of "example.nomad" will be used.
31
32Init Options:
33
34  -short
35    If the short flag is set, a minimal jobspec without comments is emitted.
36
37  -connect
38    If the connect flag is set, the jobspec includes Consul Connect integration.
39`
40	return strings.TrimSpace(helpText)
41}
42
43func (c *JobInitCommand) Synopsis() string {
44	return "Create an example job file"
45}
46
47func (c *JobInitCommand) AutocompleteFlags() complete.Flags {
48	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
49		complete.Flags{
50			"-short": complete.PredictNothing,
51		})
52}
53
54func (c *JobInitCommand) AutocompleteArgs() complete.Predictor {
55	return complete.PredictNothing
56}
57
58func (c *JobInitCommand) Name() string { return "job init" }
59
60func (c *JobInitCommand) Run(args []string) int {
61	var short bool
62	var connect bool
63
64	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
65	flags.Usage = func() { c.Ui.Output(c.Help()) }
66	flags.BoolVar(&short, "short", false, "")
67	flags.BoolVar(&connect, "connect", false, "")
68
69	if err := flags.Parse(args); err != nil {
70		return 1
71	}
72
73	// Check for misuse
74	// Check that we either got no filename or exactly one.
75	args = flags.Args()
76	if len(args) > 1 {
77		c.Ui.Error("This command takes either no arguments or one: <filename>")
78		c.Ui.Error(commandErrorText(c))
79		return 1
80	}
81
82	filename := DefaultInitName
83	if len(args) == 1 {
84		filename = args[0]
85	}
86
87	// Check if the file already exists
88	_, err := os.Stat(filename)
89	if err != nil && !os.IsNotExist(err) {
90		c.Ui.Error(fmt.Sprintf("Failed to stat '%s': %v", filename, err))
91		return 1
92	}
93	if !os.IsNotExist(err) {
94		c.Ui.Error(fmt.Sprintf("Job '%s' already exists", filename))
95		return 1
96	}
97
98	var jobSpec []byte
99	switch {
100	case connect && !short:
101		jobSpec, err = Asset("command/assets/connect.nomad")
102	case connect && short:
103		jobSpec, err = Asset("command/assets/connect-short.nomad")
104	case !connect && short:
105		jobSpec, err = Asset("command/assets/example-short.nomad")
106	default:
107		jobSpec, err = Asset("command/assets/example.nomad")
108	}
109	if err != nil {
110		// should never see this because we've precompiled the assets
111		// as part of `make generate-examples`
112		c.Ui.Error(fmt.Sprintf("Accessed non-existent asset: %s", err))
113		return 1
114	}
115
116	// Write out the example
117	err = ioutil.WriteFile(filename, jobSpec, 0660)
118	if err != nil {
119		c.Ui.Error(fmt.Sprintf("Failed to write '%s': %v", filename, err))
120		return 1
121	}
122
123	// Success
124	c.Ui.Output(fmt.Sprintf("Example job file written to %s", filename))
125	return 0
126}
127