command: -var flag works
This commit is contained in:
parent
272632ced0
commit
3534470ca3
|
@ -2,7 +2,6 @@ package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -25,7 +24,7 @@ func (c *ApplyCommand) Run(args []string) int {
|
||||||
|
|
||||||
args = c.Meta.process(args)
|
args = c.Meta.process(args)
|
||||||
|
|
||||||
cmdFlags := flag.NewFlagSet("apply", flag.ContinueOnError)
|
cmdFlags := c.Meta.flagSet("apply")
|
||||||
cmdFlags.BoolVar(&init, "init", false, "init")
|
cmdFlags.BoolVar(&init, "init", false, "init")
|
||||||
cmdFlags.StringVar(&statePath, "state", DefaultStateFilename, "path")
|
cmdFlags.StringVar(&statePath, "state", DefaultStateFilename, "path")
|
||||||
cmdFlags.StringVar(&stateOutPath, "state-out", "", "path")
|
cmdFlags.StringVar(&stateOutPath, "state-out", "", "path")
|
||||||
|
@ -207,6 +206,14 @@ Options:
|
||||||
"-state". This can be used to preserve the old
|
"-state". This can be used to preserve the old
|
||||||
state.
|
state.
|
||||||
|
|
||||||
|
-var 'foo=bar' Set a variable in the Terraform configuration. This
|
||||||
|
flag can be set multiple times.
|
||||||
|
|
||||||
|
-var-file=foo Set variables in the Terraform configuration from
|
||||||
|
a file. If "terraform.tfvars" is present, it will be
|
||||||
|
automatically loaded if this flag is not specified.
|
||||||
|
|
||||||
|
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
|
@ -466,3 +466,41 @@ func TestApply_stateNoExist(t *testing.T) {
|
||||||
t.Fatalf("bad: \n%s", ui.OutputWriter.String())
|
t.Fatalf("bad: \n%s", ui.OutputWriter.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApply_vars(t *testing.T) {
|
||||||
|
statePath := testTempFile(t)
|
||||||
|
|
||||||
|
p := testProvider()
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &ApplyCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
ContextOpts: testCtxConfig(p),
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := ""
|
||||||
|
p.DiffFn = func(
|
||||||
|
s *terraform.ResourceState,
|
||||||
|
c *terraform.ResourceConfig) (*terraform.ResourceDiff, error) {
|
||||||
|
if v, ok := c.Config["value"]; ok {
|
||||||
|
actual = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-init",
|
||||||
|
"-var", "foo=bar",
|
||||||
|
"-state", statePath,
|
||||||
|
testFixturePath("apply-vars"),
|
||||||
|
}
|
||||||
|
if code := c.Run(args); code != 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual != "bar" {
|
||||||
|
t.Fatal("didn't work")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FlagVar is a flag.Value implementation for parsing user variables
|
||||||
|
// from the command-line in the format of '-var key=value'.
|
||||||
|
type FlagVar map[string]string
|
||||||
|
|
||||||
|
func (v *FlagVar) String() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *FlagVar) Set(raw string) error {
|
||||||
|
idx := strings.Index(raw, "=")
|
||||||
|
if idx == -1 {
|
||||||
|
return fmt.Errorf("No '=' value in arg: %s", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *v == nil {
|
||||||
|
*v = make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
key, value := raw[0:idx], raw[idx+1:]
|
||||||
|
(*v)[key] = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlagVarFile is a flag.Value implementation for parsing user variables
|
||||||
|
// from the command line in the form of files. i.e. '-var-file=foo'
|
||||||
|
type FlagVarFile map[string]string
|
||||||
|
|
||||||
|
func (v *FlagVarFile) String() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *FlagVarFile) Set(raw string) error {
|
||||||
|
// TODO
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFlagVar_impl(t *testing.T) {
|
||||||
|
var _ flag.Value = new(FlagVar)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFlagVar(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Input string
|
||||||
|
Output map[string]string
|
||||||
|
Error bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"key=value",
|
||||||
|
map[string]string{"key": "value"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"key=",
|
||||||
|
map[string]string{"key": ""},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"key=foo=bar",
|
||||||
|
map[string]string{"key": "foo=bar"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"key",
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
f := new(FlagVar)
|
||||||
|
err := f.Set(tc.Input)
|
||||||
|
if (err != nil) != tc.Error {
|
||||||
|
t.Fatalf("bad error. Input: %#v", tc.Input)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := map[string]string(*f)
|
||||||
|
if !reflect.DeepEqual(actual, tc.Output) {
|
||||||
|
t.Fatalf("bad: %#v", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
@ -19,6 +20,9 @@ type Meta struct {
|
||||||
// This can be set by the command itself to provide extra hooks.
|
// This can be set by the command itself to provide extra hooks.
|
||||||
extraHooks []terraform.Hook
|
extraHooks []terraform.Hook
|
||||||
|
|
||||||
|
// Variables for the context (private)
|
||||||
|
variables map[string]string
|
||||||
|
|
||||||
color bool
|
color bool
|
||||||
oldUi cli.Ui
|
oldUi cli.Ui
|
||||||
}
|
}
|
||||||
|
@ -109,9 +113,29 @@ func (m *Meta) contextOpts() *terraform.ContextOpts {
|
||||||
copy(opts.Hooks[1:], m.ContextOpts.Hooks)
|
copy(opts.Hooks[1:], m.ContextOpts.Hooks)
|
||||||
copy(opts.Hooks[len(m.ContextOpts.Hooks)+1:], m.extraHooks)
|
copy(opts.Hooks[len(m.ContextOpts.Hooks)+1:], m.extraHooks)
|
||||||
println(fmt.Sprintf("%#v", opts.Hooks))
|
println(fmt.Sprintf("%#v", opts.Hooks))
|
||||||
|
|
||||||
|
if len(m.variables) > 0 {
|
||||||
|
vs := make(map[string]string)
|
||||||
|
for k, v := range opts.Variables {
|
||||||
|
vs[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range m.variables {
|
||||||
|
vs[k] = v
|
||||||
|
}
|
||||||
|
opts.Variables = vs
|
||||||
|
}
|
||||||
|
|
||||||
return &opts
|
return &opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// flags adds the meta flags to the given FlagSet.
|
||||||
|
func (m *Meta) flagSet(n string) *flag.FlagSet {
|
||||||
|
f := flag.NewFlagSet(n, flag.ContinueOnError)
|
||||||
|
f.Var((*FlagVar)(&m.variables), "var", "variables")
|
||||||
|
f.Var((*FlagVarFile)(&m.variables), "var-file", "variable file")
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
// process will process the meta-parameters out of the arguments. This
|
// process will process the meta-parameters out of the arguments. This
|
||||||
// will potentially modify the args in-place. It will return the resulting
|
// will potentially modify the args in-place. It will return the resulting
|
||||||
// slice.
|
// slice.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
@ -22,7 +21,7 @@ func (c *PlanCommand) Run(args []string) int {
|
||||||
|
|
||||||
args = c.Meta.process(args)
|
args = c.Meta.process(args)
|
||||||
|
|
||||||
cmdFlags := flag.NewFlagSet("plan", flag.ContinueOnError)
|
cmdFlags := c.Meta.flagSet("plan")
|
||||||
cmdFlags.BoolVar(&destroy, "destroy", false, "destroy")
|
cmdFlags.BoolVar(&destroy, "destroy", false, "destroy")
|
||||||
cmdFlags.BoolVar(&refresh, "refresh", true, "refresh")
|
cmdFlags.BoolVar(&refresh, "refresh", true, "refresh")
|
||||||
cmdFlags.StringVar(&outPath, "out", "", "path")
|
cmdFlags.StringVar(&outPath, "out", "", "path")
|
||||||
|
@ -145,6 +144,13 @@ Options:
|
||||||
up Terraform-managed resources. By default it will
|
up Terraform-managed resources. By default it will
|
||||||
use the state "terraform.tfstate" if it exists.
|
use the state "terraform.tfstate" if it exists.
|
||||||
|
|
||||||
|
-var 'foo=bar' Set a variable in the Terraform configuration. This
|
||||||
|
flag can be set multiple times.
|
||||||
|
|
||||||
|
-var-file=foo Set variables in the Terraform configuration from
|
||||||
|
a file. If "terraform.tfvars" is present, it will be
|
||||||
|
automatically loaded if this flag is not specified.
|
||||||
|
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,3 +281,37 @@ func TestPlan_stateDefault(t *testing.T) {
|
||||||
t.Fatalf("bad: %#v", p.DiffState)
|
t.Fatalf("bad: %#v", p.DiffState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPlan_vars(t *testing.T) {
|
||||||
|
p := testProvider()
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &PlanCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
ContextOpts: testCtxConfig(p),
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := ""
|
||||||
|
p.DiffFn = func(
|
||||||
|
s *terraform.ResourceState,
|
||||||
|
c *terraform.ResourceConfig) (*terraform.ResourceDiff, error) {
|
||||||
|
if v, ok := c.Config["value"]; ok {
|
||||||
|
actual = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-var", "foo=bar",
|
||||||
|
testFixturePath("plan-vars"),
|
||||||
|
}
|
||||||
|
if code := c.Run(args); code != 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual != "bar" {
|
||||||
|
t.Fatal("didn't work")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
@ -21,7 +20,7 @@ func (c *RefreshCommand) Run(args []string) int {
|
||||||
|
|
||||||
args = c.Meta.process(args)
|
args = c.Meta.process(args)
|
||||||
|
|
||||||
cmdFlags := flag.NewFlagSet("refresh", flag.ContinueOnError)
|
cmdFlags := c.Meta.flagSet("refresh")
|
||||||
cmdFlags.StringVar(&statePath, "state", DefaultStateFilename, "path")
|
cmdFlags.StringVar(&statePath, "state", DefaultStateFilename, "path")
|
||||||
cmdFlags.StringVar(&stateOutPath, "state-out", "", "path")
|
cmdFlags.StringVar(&stateOutPath, "state-out", "", "path")
|
||||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
|
@ -128,6 +127,13 @@ Options:
|
||||||
-state-out=path Path to write updated state file. By default, the
|
-state-out=path Path to write updated state file. By default, the
|
||||||
"-state" path will be used.
|
"-state" path will be used.
|
||||||
|
|
||||||
|
-var 'foo=bar' Set a variable in the Terraform configuration. This
|
||||||
|
flag can be set multiple times.
|
||||||
|
|
||||||
|
-var-file=foo Set variables in the Terraform configuration from
|
||||||
|
a file. If "terraform.tfvars" is present, it will be
|
||||||
|
automatically loaded if this flag is not specified.
|
||||||
|
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,3 +296,40 @@ func TestRefresh_outPath(t *testing.T) {
|
||||||
t.Fatalf("bad: %#v", actual)
|
t.Fatalf("bad: %#v", actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRefresh_var(t *testing.T) {
|
||||||
|
state := &terraform.State{
|
||||||
|
Resources: map[string]*terraform.ResourceState{
|
||||||
|
"test_instance.foo": &terraform.ResourceState{
|
||||||
|
ID: "bar",
|
||||||
|
Type: "test_instance",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
statePath := testStateFile(t, state)
|
||||||
|
|
||||||
|
p := testProvider()
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &RefreshCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
ContextOpts: testCtxConfig(p),
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-var", "foo=bar",
|
||||||
|
"-state", statePath,
|
||||||
|
testFixturePath("refresh-var"),
|
||||||
|
}
|
||||||
|
if code := c.Run(args); code != 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !p.ConfigureCalled {
|
||||||
|
t.Fatal("configure should be called")
|
||||||
|
}
|
||||||
|
if p.ConfigureConfig.Config["value"].(string) != "bar" {
|
||||||
|
t.Fatalf("bad: %#v", p.ConfigureConfig.Config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
variable "foo" {}
|
||||||
|
|
||||||
|
resource "test_instance" "foo" {
|
||||||
|
value = "${var.foo}"
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
variable "foo" {}
|
||||||
|
|
||||||
|
resource "test_instance" "foo" {
|
||||||
|
value = "${var.foo}"
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
variable "foo" {}
|
||||||
|
|
||||||
|
provider "test" {
|
||||||
|
value = "${var.foo}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "test_instance" "foo" {}
|
Loading…
Reference in New Issue