terraform: add InputMode to determine what is asked for

This commit is contained in:
Mitchell Hashimoto 2014-10-08 10:18:45 -07:00
parent 014bde64c4
commit 8b5c120ecf
4 changed files with 210 additions and 59 deletions

View File

@ -58,6 +58,22 @@ type ContextOpts struct {
UIInput UIInput
}
// InputMode defines what sort of input will be asked for when Input
// is called on Context.
type InputMode byte
const (
// InputModeVar asks for variables
InputModeVar InputMode = 1 << iota
// InputModeProvider asks for provider variables
InputModeProvider
// InputModeStd is the standard operating mode and asks for both variables
// and providers.
InputModeStd = InputModeVar | InputModeProvider
)
// NewContext creates a new context.
//
// Once a context is created, the pointer values within ContextOpts should
@ -137,10 +153,11 @@ func (c *Context) Graph() (*depgraph.Graph, error) {
// Input asks for input to fill variables and provider configurations.
// This modifies the configuration in-place, so asking for Input twice
// may result in different UI output showing different current values.
func (c *Context) Input() error {
func (c *Context) Input(mode InputMode) error {
v := c.acquireRun()
defer c.releaseRun(v)
if mode&InputModeVar != 0 {
// Walk the variables first for the root module. We walk them in
// alphabetical order for UX reasons.
rootConf := c.module.Config()
@ -200,7 +217,9 @@ func (c *Context) Input() error {
c.variables[n] = value
}
}
}
if mode&InputModeProvider != 0 {
// Create the walk context and walk the inputs, which will gather the
// inputs for any resource providers.
wc := c.walkContext(walkInput, rootModulePath)
@ -208,6 +227,9 @@ func (c *Context) Input() error {
return wc.Walk()
}
return nil
}
// Plan generates an execution plan for the given context.
//
// The execution plan encapsulates the context and can be stored

View File

@ -460,7 +460,7 @@ func TestContextInput(t *testing.T) {
"var.foo": "us-east-1",
}
if err := ctx.Input(); err != nil {
if err := ctx.Input(InputModeStd); err != nil {
t.Fatalf("err: %s", err)
}
@ -502,7 +502,7 @@ func TestContextInput_provider(t *testing.T) {
return nil
}
if err := ctx.Input(); err != nil {
if err := ctx.Input(InputModeStd); err != nil {
t.Fatalf("err: %s", err)
}
@ -552,7 +552,7 @@ func TestContextInput_providerId(t *testing.T) {
"provider.aws.foo": "bar",
}
if err := ctx.Input(); err != nil {
if err := ctx.Input(InputModeStd); err != nil {
t.Fatalf("err: %s", err)
}
@ -569,6 +569,116 @@ func TestContextInput_providerId(t *testing.T) {
}
}
func TestContextInput_providerOnly(t *testing.T) {
input := new(MockUIInput)
m := testModule(t, "input-provider-vars")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
ctx := testContext(t, &ContextOpts{
Module: m,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
Variables: map[string]string{
"foo": "us-west-2",
},
UIInput: input,
})
input.InputReturnMap = map[string]string{
"var.foo": "us-east-1",
}
var actual interface{}
p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
c.Raw["foo"] = "bar"
return c, nil
}
p.ConfigureFn = func(c *ResourceConfig) error {
actual = c.Raw["foo"]
return nil
}
if err := ctx.Input(InputModeProvider); err != nil {
t.Fatalf("err: %s", err)
}
if _, err := ctx.Plan(nil); err != nil {
t.Fatalf("err: %s", err)
}
state, err := ctx.Apply()
if err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(actual, "bar") {
t.Fatalf("bad: %#v", actual)
}
actualStr := strings.TrimSpace(state.String())
expectedStr := strings.TrimSpace(testTerraformInputProviderOnlyStr)
if actualStr != expectedStr {
t.Fatalf("bad: \n%s", actualStr)
}
}
func TestContextInput_varOnly(t *testing.T) {
input := new(MockUIInput)
m := testModule(t, "input-provider-vars")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
ctx := testContext(t, &ContextOpts{
Module: m,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
Variables: map[string]string{
"foo": "us-west-2",
},
UIInput: input,
})
input.InputReturnMap = map[string]string{
"var.foo": "us-east-1",
}
var actual interface{}
p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) {
c.Raw["foo"] = "bar"
return c, nil
}
p.ConfigureFn = func(c *ResourceConfig) error {
actual = c.Raw["foo"]
return nil
}
if err := ctx.Input(InputModeVar); err != nil {
t.Fatalf("err: %s", err)
}
if _, err := ctx.Plan(nil); err != nil {
t.Fatalf("err: %s", err)
}
state, err := ctx.Apply()
if err != nil {
t.Fatalf("err: %s", err)
}
if reflect.DeepEqual(actual, "bar") {
t.Fatalf("bad: %#v", actual)
}
actualStr := strings.TrimSpace(state.String())
expectedStr := strings.TrimSpace(testTerraformInputVarOnlyStr)
if actualStr != expectedStr {
t.Fatalf("bad: \n%s", actualStr)
}
}
func TestContextApply(t *testing.T) {
m := testModule(t, "apply-good")
p := testProvider("aws")

View File

@ -126,6 +126,20 @@ aws_instance.foo:
type = aws_instance
`
const testTerraformInputProviderOnlyStr = `
aws_instance.foo:
ID = foo
foo = us-west-2
type = aws_instance
`
const testTerraformInputVarOnlyStr = `
aws_instance.foo:
ID = foo
foo = us-east-1
type = aws_instance
`
const testTerraformInputVarsStr = `
aws_instance.bar:
ID = foo

View File

@ -0,0 +1,5 @@
variable "foo" {}
resource "aws_instance" "foo" {
foo = "${var.foo}"
}