terraform: start Input
This commit is contained in:
parent
7b305d1f41
commit
f3714f1efc
|
@ -2,12 +2,30 @@ package terraform
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"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
|
||||
// NewContext.
|
||||
type ContextOpts struct {
|
||||
|
@ -36,6 +54,7 @@ type Context2 struct {
|
|||
sh *stopHook
|
||||
state *State
|
||||
stateLock sync.RWMutex
|
||||
uiInput UIInput
|
||||
variables map[string]string
|
||||
|
||||
l sync.Mutex // Lock acquired during any task
|
||||
|
@ -69,6 +88,7 @@ func NewContext2(opts *ContextOpts) *Context2 {
|
|||
provisioners: opts.Provisioners,
|
||||
sh: sh,
|
||||
state: state,
|
||||
uiInput: opts.UIInput,
|
||||
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
|
||||
// the resulting state.
|
||||
//
|
||||
|
|
|
@ -42,22 +42,6 @@ type Context struct {
|
|||
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.
|
||||
//
|
||||
// Once a context is created, the pointer values within ContextOpts should
|
||||
|
|
|
@ -2382,14 +2382,13 @@ func TestContext2Validate_varRefFilled(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func TestContextInput(t *testing.T) {
|
||||
func TestContext2Input(t *testing.T) {
|
||||
input := new(MockUIInput)
|
||||
m := testModule(t, "input-vars")
|
||||
p := testProvider("aws")
|
||||
p.ApplyFn = testApplyFn
|
||||
p.DiffFn = testDiffFn
|
||||
ctx := testContext(t, &ContextOpts{
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Module: m,
|
||||
Providers: map[string]ResourceProviderFactory{
|
||||
"aws": testProviderFuncFixed(p),
|
||||
|
@ -2425,6 +2424,7 @@ func TestContextInput(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func TestContextInput_provider(t *testing.T) {
|
||||
m := testModule(t, "input-provider")
|
||||
p := testProvider("aws")
|
||||
|
|
Loading…
Reference in New Issue