-// 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(mode InputMode) error {
- defer c.acquireRun("input")()
-
- 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 {
- // If we only care about unset variables, then if the variable
- // is set, continue on.
- if mode&InputModeVarUnset != 0 {
- if _, ok := c.variables[n]; ok {
- continue
- }
- }
-
- var valueType config.VariableType
-
- v := m[n]
- switch valueType = v.Type(); valueType {
- case config.VariableTypeUnknown:
- continue
- case config.VariableTypeMap:
- // OK
- case config.VariableTypeList:
- // OK
- case config.VariableTypeString:
- // OK
- default:
- panic(fmt.Sprintf("Unknown variable type: %#v", v.Type()))
- }
-
- // If the variable is not already set, and the variable defines a
- // default, use that for the value.
- if _, ok := c.variables[n]; !ok {
- if v.Default != nil {
- c.variables[n] = v.Default.(string)
- continue
- }
- }
-
- // this should only happen during tests
- if c.uiInput == nil {
- log.Println("[WARN] Content.uiInput is nil")
- continue
- }
-
- // Ask the user for a value for this variable
- var value string
- retry := 0
- for {
- var err error
- value, err = c.uiInput.Input(&InputOpts{
- Id: fmt.Sprintf("var.%s", n),
- Query: fmt.Sprintf("var.%s", n),
- 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, but abort if we keep getting
- // blank entries
- if retry > 2 {
- return fmt.Errorf("missing required value for %q", n)
- }
- retry++
- continue
- }
-
- break
- }
-
- // no value provided, so don't set the variable at all
- if value == "" {
- continue
- }
-
- decoded, err := parseVariableAsHCL(n, value, valueType)
- if err != nil {
- return err
- }
-
- if decoded != nil {
- c.variables[n] = decoded
- }
- }
- }
-
- if mode&InputModeProvider != 0 {
- // Build the graph
- graph, err := c.Graph(GraphTypeInput, nil)
- if err != nil {
- return err
- }
-
- // Do the walk
- if _, err := c.walk(graph, nil, walkInput); err != nil {
- return err
- }
- }
-
- return nil