forked from hashicorp/levant
-
Notifications
You must be signed in to change notification settings - Fork 0
/
plan.go
142 lines (113 loc) · 4.21 KB
/
plan.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package command
import (
"fmt"
"strings"
"github.com/hashicorp/levant/helper"
"github.com/hashicorp/levant/levant"
"github.com/hashicorp/levant/levant/structs"
"github.com/hashicorp/levant/logging"
"github.com/hashicorp/levant/template"
)
// PlanCommand is the command implementation that allows users to plan a
// Nomad job based on passed templates and variables.
type PlanCommand struct {
Meta
}
// Help provides the help information for the plan command.
func (c *PlanCommand) Help() string {
helpText := `
Usage: levant plan [options] [TEMPLATE]
Perform a Nomad plan based on input templates and variable files. The plan
command supports passing variables individually on the command line. Multiple
commands can be passed in the format of -var 'key=value'. Variables passed
via the command line take precedence over the same variable declared within
a passed variable file.
Arguments:
TEMPLATE nomad job template
If no argument is given we look for a single *.nomad file
General Options:
-address=<http_address>
The Nomad HTTP API address including port which Levant will use to make
calls.
-allow-stale
Allow stale consistency mode for requests into nomad.
-consul-address=<addr>
The Consul host and port to use when making Consul KeyValue lookups for
template rendering.
-force-count
Use the taskgroup count from the Nomad jobfile instead of the count that
is currently set in a running job.
-ignore-no-changes
By default if no changes are detected when running a plan Levant will
exit with a status 1 to indicate there are no changes. This behaviour
can be changed using this flag so that Levant will exit cleanly ensuring CD
pipelines don't fail when no changes are detected.
-log-level=<level>
Specify the verbosity level of Levant's logs. Valid values include DEBUG,
INFO, and WARN, in decreasing order of verbosity. The default is INFO.
-log-format=<format>
Specify the format of Levant's logs. Valid values are HUMAN or JSON. The
default is HUMAN.
-var-file=<file>
Used in conjunction with the -job-file will plan a templated job against your
Nomad cluster. You can repeat this flag multiple times to supply multiple var-files.
[default: levant.(json|yaml|yml|tf)]
`
return strings.TrimSpace(helpText)
}
// Synopsis is provides a brief summary of the plan command.
func (c *PlanCommand) Synopsis() string {
return "Render and perform a Nomad job plan from a template"
}
// Run triggers a run of the Levant template and plan functions.
func (c *PlanCommand) Run(args []string) int {
var err error
var level, format string
config := &levant.PlanConfig{
Client: &structs.ClientConfig{},
Plan: &structs.PlanConfig{},
Template: &structs.TemplateConfig{},
}
flags := c.Meta.FlagSet("plan", FlagSetVars)
flags.Usage = func() { c.UI.Output(c.Help()) }
flags.StringVar(&config.Client.Addr, "address", "", "")
flags.BoolVar(&config.Client.AllowStale, "allow-stale", false, "")
flags.StringVar(&config.Client.ConsulAddr, "consul-address", "", "")
flags.BoolVar(&config.Plan.IgnoreNoChanges, "ignore-no-changes", false, "")
flags.StringVar(&level, "log-level", "INFO", "")
flags.StringVar(&format, "log-format", "HUMAN", "")
flags.Var((*helper.FlagStringSlice)(&config.Template.VariableFiles), "var-file", "")
if err = flags.Parse(args); err != nil {
return 1
}
args = flags.Args()
if err = logging.SetupLogger(level, format); err != nil {
c.UI.Error(err.Error())
return 1
}
if len(args) == 1 {
config.Template.TemplateFile = args[0]
} else if len(args) == 0 {
if config.Template.TemplateFile = helper.GetDefaultTmplFile(); config.Template.TemplateFile == "" {
c.UI.Error(c.Help())
c.UI.Error("\nERROR: Template arg missing and no default template found")
return 1
}
} else {
c.UI.Error(c.Help())
return 1
}
config.Template.Job, err = template.RenderJob(config.Template.TemplateFile,
config.Template.VariableFiles, config.Client.ConsulAddr, &c.Meta.flagVars)
if err != nil {
c.UI.Error(fmt.Sprintf("[ERROR] levant/command: %v", err))
return 1
}
success, changes := levant.TriggerPlan(config)
if !success {
return 1
} else if !changes && config.Plan.IgnoreNoChanges {
return 0
}
return 0
}