mirror of
https://github.com/FlipsideCrypto/convox.git
synced 2026-02-06 10:56:56 +00:00
cli: allow terraform options on rack install/update (#85)
This commit is contained in:
parent
9dbc425d88
commit
5192c09625
@ -404,7 +404,6 @@ func switchRack(c *stdcli.Context, name string) error {
|
||||
func tag(name, value string) string {
|
||||
return fmt.Sprintf("<%s>%s</%s>", name, value, name)
|
||||
}
|
||||
|
||||
func terraform(c *stdcli.Context, dir string, env map[string]string, args ...string) error {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
@ -439,7 +438,45 @@ func terraformEnv(provider string) (map[string]string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func terraformVars(provider string) (map[string]string, error) {
|
||||
func terraformOptionVars(dir string, args []string) (map[string]string, error) {
|
||||
vars := map[string]string{}
|
||||
|
||||
vf := filepath.Join(dir, "vars.json")
|
||||
|
||||
if _, err := os.Stat(vf); !os.IsNotExist(err) {
|
||||
data, err := ioutil.ReadFile(vf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &vars); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, arg := range args {
|
||||
parts := strings.Split(arg, "=")
|
||||
k := strings.TrimSpace(parts[0])
|
||||
if v := strings.TrimSpace(parts[1]); v != "" {
|
||||
vars[k] = v
|
||||
} else {
|
||||
delete(vars, k)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(vars, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(vf, data, 0600); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vars, nil
|
||||
}
|
||||
|
||||
func terraformProviderVars(provider string) (map[string]string, error) {
|
||||
switch provider {
|
||||
case "do":
|
||||
env, err := requireEnv("DIGITALOCEAN_ACCESS_ID", "DIGITALOCEAN_SECRET_KEY", "DIGITALOCEAN_TOKEN")
|
||||
@ -449,11 +486,28 @@ func terraformVars(provider string) (map[string]string, error) {
|
||||
vars := map[string]string{
|
||||
"access_id": env["DIGITALOCEAN_ACCESS_ID"],
|
||||
"secret_key": env["DIGITALOCEAN_SECRET_KEY"],
|
||||
"release": "",
|
||||
"token": env["DIGITALOCEAN_TOKEN"],
|
||||
}
|
||||
return vars, nil
|
||||
default:
|
||||
return map[string]string{}, nil
|
||||
vars := map[string]string{
|
||||
"release": "",
|
||||
}
|
||||
return vars, nil
|
||||
}
|
||||
}
|
||||
|
||||
func terraformTemplateHelpers() template.FuncMap {
|
||||
return template.FuncMap{
|
||||
"keys": func(h map[string]string) []string {
|
||||
ks := []string{}
|
||||
for k := range h {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
return ks
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,14 +518,14 @@ func terraformWriteTemplate(filename string, params map[string]interface{}) erro
|
||||
params["Source"] = fmt.Sprintf("github.com/convox/convox//terraform/system/%s", params["Provider"])
|
||||
}
|
||||
|
||||
t, err := template.New("main").Parse(`
|
||||
t, err := template.New("main").Funcs(terraformTemplateHelpers()).Parse(`
|
||||
module "system" {
|
||||
source = "{{.Source}}"
|
||||
|
||||
name = "{{.Name}}"
|
||||
release = "{{.Release}}"
|
||||
{{- range $k, $v := .Vars }}
|
||||
{{$k}} = "{{$v}}"
|
||||
name = "{{.Name}}"
|
||||
|
||||
{{- range (keys .Vars) }}
|
||||
{{.}} = "{{index $.Vars .}}"
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
|
||||
@ -22,8 +22,8 @@ func init() {
|
||||
})
|
||||
|
||||
registerWithoutProvider("rack install", "install a new rack", RackInstall, stdcli.CommandOptions{
|
||||
Usage: "<provider> <name>",
|
||||
Validate: stdcli.Args(2),
|
||||
Usage: "<provider> <name> [option=value]...",
|
||||
Validate: stdcli.ArgsMin(2),
|
||||
})
|
||||
|
||||
register("rack logs", "get logs for the rack", RackLogs, stdcli.CommandOptions{
|
||||
@ -67,8 +67,8 @@ func init() {
|
||||
})
|
||||
|
||||
registerWithoutProvider("rack update", "update a rack", RackUpdate, stdcli.CommandOptions{
|
||||
Usage: "<name>",
|
||||
Validate: stdcli.Args(1),
|
||||
Usage: "<name> [option=value]...",
|
||||
Validate: stdcli.ArgsMin(1),
|
||||
})
|
||||
}
|
||||
|
||||
@ -110,11 +110,6 @@ func RackInstall(rack sdk.Interface, c *stdcli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
vars, err := terraformVars(provider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dir, err := c.SettingDirectory(fmt.Sprintf("racks/%s", name))
|
||||
if err != nil {
|
||||
return err
|
||||
@ -124,6 +119,20 @@ func RackInstall(rack sdk.Interface, c *stdcli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
vars, err := terraformProviderVars(provider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ov, err := terraformOptionVars(dir, c.Args[2:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for k, v := range ov {
|
||||
vars[k] = v
|
||||
}
|
||||
|
||||
tf := filepath.Join(dir, "main.tf")
|
||||
|
||||
if _, err := os.Stat(tf); !os.IsNotExist(err) {
|
||||
@ -133,7 +142,6 @@ func RackInstall(rack sdk.Interface, c *stdcli.Context) error {
|
||||
params := map[string]interface{}{
|
||||
"Name": name,
|
||||
"Provider": provider,
|
||||
"Release": "",
|
||||
"Vars": vars,
|
||||
}
|
||||
|
||||
@ -367,27 +375,35 @@ func RackUpdate(rack sdk.Interface, c *stdcli.Context) error {
|
||||
return rackUpdateRemote(c, name)
|
||||
}
|
||||
|
||||
dir, err := c.SettingDirectory(fmt.Sprintf("racks/%s", name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
env, err := terraformEnv(r.Provider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vars, err := terraformVars(r.Provider)
|
||||
vars, err := terraformProviderVars(r.Provider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dir, err := c.SettingDirectory(fmt.Sprintf("racks/%s", name))
|
||||
ov, err := terraformOptionVars(dir, c.Args[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for k, v := range ov {
|
||||
vars[k] = v
|
||||
}
|
||||
|
||||
tf := filepath.Join(dir, "main.tf")
|
||||
|
||||
params := map[string]interface{}{
|
||||
"Name": name,
|
||||
"Provider": r.Provider,
|
||||
"Release": "",
|
||||
"Vars": vars,
|
||||
}
|
||||
|
||||
@ -403,7 +419,7 @@ func RackUpdate(rack sdk.Interface, c *stdcli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.OK()
|
||||
return nil
|
||||
}
|
||||
|
||||
func rackUninstallRemote(c *stdcli.Context, name string) error {
|
||||
|
||||
@ -73,7 +73,46 @@ func TestRackInstall(t *testing.T) {
|
||||
tfdata, err := ioutil.ReadFile(tf)
|
||||
require.NoError(t, err)
|
||||
|
||||
testdata, err := ioutil.ReadFile("testdata/terraform.local.tf")
|
||||
testdata, err := ioutil.ReadFile("testdata/terraform/dev1.tf")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, strings.Trim(string(tfdata), "\n"), strings.Trim(string(testdata), "\n"))
|
||||
|
||||
res, err = testExecute(e, "switch", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, res.Code)
|
||||
res.RequireStderr(t, []string{""})
|
||||
res.RequireStdout(t, []string{"dev1"})
|
||||
|
||||
me.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRackInstallArgs(t *testing.T) {
|
||||
testClientWait(t, 50*time.Millisecond, func(e *cli.Engine, i *mocksdk.Interface) {
|
||||
me := &mockstdcli.Executor{}
|
||||
me.On("Terminal", "terraform", "init").Return(nil)
|
||||
me.On("Terminal", "terraform", "apply", "-auto-approve").Return(nil)
|
||||
e.Executor = me
|
||||
|
||||
res, err := testExecute(e, "rack install local dev1 foo=bar baz=qux", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, res.Code)
|
||||
res.RequireStderr(t, []string{""})
|
||||
res.RequireStdout(t, []string{""})
|
||||
|
||||
dir := filepath.Join(e.Settings, "racks", "dev1")
|
||||
tf := filepath.Join(dir, "main.tf")
|
||||
|
||||
_, err = os.Stat(dir)
|
||||
require.NoError(t, err)
|
||||
_, err = os.Stat(tf)
|
||||
require.NoError(t, err)
|
||||
|
||||
tfdata, err := ioutil.ReadFile(tf)
|
||||
require.NoError(t, err)
|
||||
|
||||
testdata, err := ioutil.ReadFile("testdata/terraform/dev1.args.tf")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, strings.Trim(string(tfdata), "\n"), strings.Trim(string(testdata), "\n"))
|
||||
@ -417,9 +456,71 @@ func TestRackUpdate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, res.Code)
|
||||
res.RequireStderr(t, []string{""})
|
||||
res.RequireStdout(t, []string{
|
||||
"OK",
|
||||
})
|
||||
res.RequireStdout(t, []string{""})
|
||||
|
||||
dir := filepath.Join(e.Settings, "racks", "dev1")
|
||||
tf := filepath.Join(dir, "main.tf")
|
||||
|
||||
_, err = os.Stat(dir)
|
||||
require.NoError(t, err)
|
||||
_, err = os.Stat(tf)
|
||||
require.NoError(t, err)
|
||||
|
||||
tfdata, err := ioutil.ReadFile(tf)
|
||||
require.NoError(t, err)
|
||||
|
||||
testdata, err := ioutil.ReadFile("testdata/terraform/dev1.tf")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, strings.Trim(string(tfdata), "\n"), strings.Trim(string(testdata), "\n"))
|
||||
|
||||
me.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRackUpdateArgs(t *testing.T) {
|
||||
testClientWait(t, 50*time.Millisecond, func(e *cli.Engine, i *mocksdk.Interface) {
|
||||
require.NoError(t, testLocalRack(e, "dev1", "local", "https://host1"))
|
||||
|
||||
me := e.Executor.(*mockstdcli.Executor)
|
||||
|
||||
me.On("Terminal", "terraform", "init").Return(nil).Once()
|
||||
me.On("Terminal", "terraform", "apply", "-auto-approve").Return(nil).Once()
|
||||
|
||||
res, err := testExecute(e, "rack install local dev2 foo=bar baz=qux", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, res.Code)
|
||||
res.RequireStderr(t, []string{""})
|
||||
res.RequireStdout(t, []string{""})
|
||||
|
||||
tf := filepath.Join(e.Settings, "racks", "dev2", "main.tf")
|
||||
|
||||
fmt.Printf("tf: %+v\n", tf)
|
||||
|
||||
tfdata, err := ioutil.ReadFile(tf)
|
||||
require.NoError(t, err)
|
||||
|
||||
testdata, err := ioutil.ReadFile("testdata/terraform/dev2.args.tf")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, strings.Trim(string(testdata), "\n"), strings.Trim(string(tfdata), "\n"))
|
||||
|
||||
me.On("Terminal", "terraform", "init", "-upgrade").Return(nil).Once()
|
||||
me.On("Terminal", "terraform", "apply", "-auto-approve").Return(nil).Once()
|
||||
|
||||
res, err = testExecute(e, "rack update dev2 foo= other=side", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, res.Code)
|
||||
res.RequireStderr(t, []string{""})
|
||||
res.RequireStdout(t, []string{""})
|
||||
|
||||
tfdata2, err := ioutil.ReadFile(tf)
|
||||
require.NoError(t, err)
|
||||
|
||||
testdata2, err := ioutil.ReadFile("testdata/terraform/dev2.update.tf")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, strings.Trim(string(tfdata2), "\n"), strings.Trim(string(testdata2), "\n"))
|
||||
|
||||
me.AssertExpectations(t)
|
||||
})
|
||||
|
||||
16
pkg/cli/testdata/terraform/dev1.args.tf
vendored
Normal file
16
pkg/cli/testdata/terraform/dev1.args.tf
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
module "system" {
|
||||
source = "github.com/convox/convox//terraform/system/local"
|
||||
|
||||
name = "dev1"
|
||||
baz = "qux"
|
||||
foo = "bar"
|
||||
release = ""
|
||||
}
|
||||
|
||||
output "api" {
|
||||
value = module.system.api
|
||||
}
|
||||
|
||||
output "provider" {
|
||||
value = "local"
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
module "system" {
|
||||
source = "github.com/convox/convox//terraform/system/local"
|
||||
|
||||
name = "dev1"
|
||||
name = "dev1"
|
||||
release = ""
|
||||
}
|
||||
|
||||
16
pkg/cli/testdata/terraform/dev2.args.tf
vendored
Normal file
16
pkg/cli/testdata/terraform/dev2.args.tf
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
module "system" {
|
||||
source = "github.com/convox/convox//terraform/system/local"
|
||||
|
||||
name = "dev2"
|
||||
baz = "qux"
|
||||
foo = "bar"
|
||||
release = ""
|
||||
}
|
||||
|
||||
output "api" {
|
||||
value = module.system.api
|
||||
}
|
||||
|
||||
output "provider" {
|
||||
value = "local"
|
||||
}
|
||||
16
pkg/cli/testdata/terraform/dev2.update.tf
vendored
Normal file
16
pkg/cli/testdata/terraform/dev2.update.tf
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
module "system" {
|
||||
source = "github.com/convox/convox//terraform/system/local"
|
||||
|
||||
name = "dev2"
|
||||
baz = "qux"
|
||||
other = "side"
|
||||
release = ""
|
||||
}
|
||||
|
||||
output "api" {
|
||||
value = module.system.api
|
||||
}
|
||||
|
||||
output "provider" {
|
||||
value = "local"
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user