1package command
2
3import (
4	"fmt"
5	"io/ioutil"
6	"os"
7	"strings"
8
9	"github.com/posener/complete"
10)
11
12const (
13	// DefaultHclQuotaInitName is the default name we use when initializing the
14	// example quota file in HCL format
15	DefaultHclQuotaInitName = "spec.hcl"
16
17	// DefaultHclQuotaInitName is the default name we use when initializing the
18	// example quota file in JSON format
19	DefaultJsonQuotaInitName = "spec.json"
20)
21
22// QuotaInitCommand generates a new quota spec that you can customize to your
23// liking, like vagrant init
24type QuotaInitCommand struct {
25	Meta
26}
27
28func (c *QuotaInitCommand) Help() string {
29	helpText := `
30Usage: nomad quota init <filename>
31
32  Creates an example quota specification file that can be used as a starting
33  point to customize further. If no filename is given, the default of "spec.hcl"
34  or "spec.json" will be used.
35
36Init Options:
37
38  -json
39    Create an example JSON quota specification.
40`
41	return strings.TrimSpace(helpText)
42}
43
44func (c *QuotaInitCommand) Synopsis() string {
45	return "Create an example quota specification file"
46}
47
48func (c *QuotaInitCommand) AutocompleteFlags() complete.Flags {
49	return complete.Flags{
50		"-json": complete.PredictNothing,
51	}
52}
53
54func (c *QuotaInitCommand) AutocompleteArgs() complete.Predictor {
55	return complete.PredictNothing
56}
57
58func (c *QuotaInitCommand) Name() string { return "quota init" }
59
60func (c *QuotaInitCommand) Run(args []string) int {
61	var jsonOutput bool
62	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
63	flags.Usage = func() { c.Ui.Output(c.Help()) }
64	flags.BoolVar(&jsonOutput, "json", false, "")
65
66	if err := flags.Parse(args); err != nil {
67		return 1
68	}
69
70	// Check that we get no arguments
71	args = flags.Args()
72	if l := len(args); l > 1 {
73		c.Ui.Error("This command takes no arguments or one: <filename>")
74		c.Ui.Error(commandErrorText(c))
75		return 1
76	}
77
78	fileName := DefaultHclQuotaInitName
79	fileContent := defaultHclQuotaSpec
80	if jsonOutput {
81		fileName = DefaultJsonQuotaInitName
82		fileContent = defaultJsonQuotaSpec
83	}
84	if len(args) == 1 {
85		fileName = args[0]
86	}
87
88	// Check if the file already exists
89	_, err := os.Stat(fileName)
90	if err != nil && !os.IsNotExist(err) {
91		c.Ui.Error(fmt.Sprintf("Failed to stat %q: %v", fileName, err))
92		return 1
93	}
94	if !os.IsNotExist(err) {
95		c.Ui.Error(fmt.Sprintf("Quota specification %q already exists", fileName))
96		return 1
97	}
98
99	// Write out the example
100	err = ioutil.WriteFile(fileName, []byte(fileContent), 0660)
101	if err != nil {
102		c.Ui.Error(fmt.Sprintf("Failed to write %q: %v", fileName, err))
103		return 1
104	}
105
106	// Success
107	c.Ui.Output(fmt.Sprintf("Example quota specification written to %s", fileName))
108	return 0
109}
110
111var defaultHclQuotaSpec = strings.TrimSpace(`
112name        = "default-quota"
113description = "Limit the shared default namespace"
114
115# Create a limit for the global region. Additional limits may
116# be specified in-order to limit other regions.
117limit {
118  region = "global"
119  region_limit {
120    cpu        = 2500
121    memory     = 1000
122    memory_max = 1000
123  }
124}
125`)
126
127var defaultJsonQuotaSpec = strings.TrimSpace(`
128{
129	"Name": "default-quota",
130	"Description": "Limit the shared default namespace",
131	"Limits": [
132		{
133			"Region": "global",
134			"RegionLimit": {
135				"CPU": 2500,
136				"MemoryMB": 1000,
137				"MemoryMaxMB": 1000
138			}
139		}
140	]
141}
142`)
143