terraform: start Input
This commit is contained in:
parent
7b305d1f41
commit
f3714f1efc
|
@ -2,12 +2,30 @@ package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
|
"github.com/hashicorp/terraform/config"
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
)
|
||||||
|
|
||||||
// ContextOpts are the user-configurable options to create a context with
|
// ContextOpts are the user-configurable options to create a context with
|
||||||
// NewContext.
|
// NewContext.
|
||||||
type ContextOpts struct {
|
type ContextOpts struct {
|
||||||
|
@ -36,6 +54,7 @@ type Context2 struct {
|
||||||
sh *stopHook
|
sh *stopHook
|
||||||
state *State
|
state *State
|
||||||
stateLock sync.RWMutex
|
stateLock sync.RWMutex
|
||||||
|
uiInput UIInput
|
||||||
variables map[string]string
|
variables map[string]string
|
||||||
|
|
||||||
l sync.Mutex // Lock acquired during any task
|
l sync.Mutex // Lock acquired during any task
|
||||||
|
@ -69,6 +88,7 @@ func NewContext2(opts *ContextOpts) *Context2 {
|
||||||
provisioners: opts.Provisioners,
|
provisioners: opts.Provisioners,
|
||||||
sh: sh,
|
sh: sh,
|
||||||
state: state,
|
state: state,
|
||||||
|
uiInput: opts.UIInput,
|
||||||
variables: opts.Variables,
|
variables: opts.Variables,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +116,88 @@ func (c *Context2) GraphBuilder() GraphBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 *Context2) 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()
|
||||||
|
names := make([]string, len(rootConf.Variables))
|
||||||
|
m := make(map[string]*config.Variable)
|
||||||
|
for i, v := range rootConf.Variables {
|
||||||
|
names[i] = v.Name
|
||||||
|
m[v.Name] = v
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
for _, n := range names {
|
||||||
|
v := m[n]
|
||||||
|
switch v.Type() {
|
||||||
|
case config.VariableTypeMap:
|
||||||
|
continue
|
||||||
|
case config.VariableTypeString:
|
||||||
|
// Good!
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Unknown variable type: %#v", v.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultString string
|
||||||
|
if v.Default != nil {
|
||||||
|
defaultString = v.Default.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask the user for a value for this variable
|
||||||
|
var value string
|
||||||
|
for {
|
||||||
|
var err error
|
||||||
|
value, err = c.uiInput.Input(&InputOpts{
|
||||||
|
Id: fmt.Sprintf("var.%s", n),
|
||||||
|
Query: fmt.Sprintf("var.%s", n),
|
||||||
|
Default: defaultString,
|
||||||
|
Description: v.Description,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error asking for %s: %s", n, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value == "" && v.Required() {
|
||||||
|
// Redo if it is required.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if value == "" {
|
||||||
|
// No value, just exit the loop. With no value, we just
|
||||||
|
// use whatever is currently set in variables.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if value != "" {
|
||||||
|
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)
|
||||||
|
wc.Meta = new(walkInputMeta)
|
||||||
|
return wc.Walk()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Apply applies the changes represented by this context and returns
|
// Apply applies the changes represented by this context and returns
|
||||||
// the resulting state.
|
// the resulting state.
|
||||||
//
|
//
|
||||||
|
|
|
@ -42,22 +42,6 @@ type Context struct {
|
||||||
sh *stopHook
|
sh *stopHook
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// NewContext creates a new context.
|
||||||
//
|
//
|
||||||
// Once a context is created, the pointer values within ContextOpts should
|
// Once a context is created, the pointer values within ContextOpts should
|
||||||
|
|
|
@ -2382,14 +2382,13 @@ func TestContext2Validate_varRefFilled(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func TestContext2Input(t *testing.T) {
|
||||||
func TestContextInput(t *testing.T) {
|
|
||||||
input := new(MockUIInput)
|
input := new(MockUIInput)
|
||||||
m := testModule(t, "input-vars")
|
m := testModule(t, "input-vars")
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
p.ApplyFn = testApplyFn
|
p.ApplyFn = testApplyFn
|
||||||
p.DiffFn = testDiffFn
|
p.DiffFn = testDiffFn
|
||||||
ctx := testContext(t, &ContextOpts{
|
ctx := testContext2(t, &ContextOpts{
|
||||||
Module: m,
|
Module: m,
|
||||||
Providers: map[string]ResourceProviderFactory{
|
Providers: map[string]ResourceProviderFactory{
|
||||||
"aws": testProviderFuncFixed(p),
|
"aws": testProviderFuncFixed(p),
|
||||||
|
@ -2425,6 +2424,7 @@ func TestContextInput(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func TestContextInput_provider(t *testing.T) {
|
func TestContextInput_provider(t *testing.T) {
|
||||||
m := testModule(t, "input-provider")
|
m := testModule(t, "input-provider")
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
|
|
Loading…
Reference in New Issue