forked from mergermarket/cdflow2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
241 lines (187 loc) · 5.91 KB
/
main.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
package main
import (
"fmt"
"os"
"github.com/mergermarket/cdflow2/command"
"github.com/mergermarket/cdflow2/deploy"
"github.com/mergermarket/cdflow2/destroy"
release "github.com/mergermarket/cdflow2/release/command"
"github.com/mergermarket/cdflow2/setup"
"github.com/mergermarket/cdflow2/shell"
"github.com/mergermarket/cdflow2/util"
)
var version = "undefined"
const globalOptions string = `Global options:
--component COMPONENT_NAME - override component name (inferred from git by default).
--commit GIT_COMMIT - override the git commit (inferred from git by default).
--no-pull-config - don't pull the config container (must exist).
--no-pull-release - don't pull the release container (must exist).
--no-pull-terraform - don't pull the terraform container (must exist).
--quiet | -q - hide verbose description of what's going on.
--version - print the version number and exit.
--help - print the help message and exit.
`
const help string = `
Usage:
cdflow2 [ GLOBALOPTS ] COMMAND [ ARGS ]
Commands:
setup - configure your pipeline
release VERSION - build and publish a new software artefact
deploy ENV VERSION - create & update infrastructure using software artefact
shell ENV VERSION - access terraform for debugging and tf state manipulation
destroy ENV [ VERSION ] - destroy all Terraform managed infrastructure in ENV
help [ COMMAND ] - display detailed help and usage information for a command
` + globalOptions
const releaseHelp string = `
Usage:
cdflow2 [ GLOBALOPTS ] release [ OPTS ] VERSION
Args:
VERSION - the version being released. We recommend using evergreen version numbers (i.e. simple incrementing integers,
probably from your CI service), combined with something to identify the commit - e.g. "34-a5dbc4a7".
Options:
--release-data | -r - add key/value to release metadata (i.e. --release-data foo=bar).
` + globalOptions
const deployHelp string = `
Usage:
cdflow2 [ GLOBALOPTS ] deploy [ OPTS ] ENV VERSION
Args:
ENV - the environment being deployed to.
VERSION - the version being deployed (must match what was released).
Options:
--plan-only | -p - create the terraform plan only, don't apply.
` + globalOptions
const setupHelp string = `
Usage:
cdflow2 [ GLOBALARGS ] setup
` + globalOptions
const shellHelp string = `
Usage:
cdflow2 [ GLOBALOPTS ] shell ENV [ OPTS ] [ SHELLARGS ]
Args:
ENV - the environment containing the deployment.
Options:
-v, --version - the version to interract with (must match a pre-existing release).
Shell Arguments:
The shell arguments are passed to shell
ex: (cdflow2 shell aslive test.sh)
(cdflow2 shell aslive -v v1.0 -- -c "echo test") or
`
const destroyHelp string = `
Usage:
cdflow2 [ GLOBALOPTS ] destroy [ OPTS ] ENV [ VERSION ]
Args:
ENV - the environment containing the infrastructure being destroyed.
VERSION - the version to destroy (must match a pre-existing release).
Options:
--plan-only | -p - generate an execution plan only, don't destroy.
` + globalOptions
func usage(subcommand string) {
if subcommand == "release" {
fmt.Println(releaseHelp)
} else if subcommand == "deploy" {
fmt.Println(deployHelp)
} else if subcommand == "shell" {
fmt.Println(shellHelp)
} else if subcommand == "setup" {
fmt.Println(setupHelp)
} else if subcommand == "destroy" {
fmt.Println(destroyHelp)
} else {
fmt.Println(help)
}
os.Exit(1)
}
var globalOptionErrorFormat = `
Error in global options:
%v
For usage run:
cdflow --help
`
func main() {
globalArgs, remainingArgs, err := command.ParseArgs(os.Args[1:])
if err != nil {
fmt.Fprintf(os.Stderr, globalOptionErrorFormat, err)
os.Exit(1)
}
if globalArgs.Command == "" {
usage("")
} else if globalArgs.Command == "help" {
subcommand := ""
if len(remainingArgs) > 0 {
subcommand = remainingArgs[0]
}
usage(subcommand)
} else if globalArgs.Command == "version" {
fmt.Println(version)
os.Exit(0)
}
state, err := command.GetGlobalState(globalArgs)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
env := util.GetEnv(os.Environ())
if globalArgs.Command == "release" {
releaseArgs, ok := release.ParseArgs(remainingArgs)
if ok != nil {
fmt.Fprintln(os.Stderr, fmt.Sprintf("Error: %s", ok))
usage("release")
}
if err := release.RunCommand(state, *releaseArgs, env); err != nil {
if status, ok := err.(command.Failure); ok {
os.Exit(int(status))
}
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
} else if globalArgs.Command == "deploy" {
deployArgs, ok := deploy.ParseArgs(remainingArgs)
if !ok {
usage("deploy")
}
if err := deploy.RunCommand(state, deployArgs, env); err != nil {
if status, ok := err.(command.Failure); ok {
os.Exit(int(status))
}
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
} else if globalArgs.Command == "shell" {
shellArgs, ok := shell.ParseArgs(remainingArgs)
if ok != nil {
usage("shell")
}
if err := shell.RunCommand(state, shellArgs, env); err != nil {
if status, ok := err.(command.Failure); ok {
os.Exit(int(status))
}
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
} else if globalArgs.Command == "setup" {
if len(remainingArgs) != 0 {
usage("setup")
}
if err := setup.RunCommand(state, env); err != nil {
if status, ok := err.(command.Failure); ok {
os.Exit(int(status))
}
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
} else if globalArgs.Command == "destroy" {
destroyArgs, ok := destroy.ParseArgs(remainingArgs)
if !ok {
usage("destroy")
}
if err := destroy.RunCommand(state, destroyArgs, env); err != nil {
if status, ok := err.(command.Failure); ok {
os.Exit(int(status))
}
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
} else {
usage("")
}
}