func (c *Context) Input(mode InputMode) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics
	defer c.acquireRun("input")()
	if c.uiInput == nil {
		log.Printf("[TRACE] Context.Input: uiInput is nil, so skipping")
		return diags
	}
	ctx := context.Background()
	if mode&InputModeVar != 0 {
		log.Printf("[TRACE] Context.Input: Prompting for variables")
		configs := c.config.Module.Variables
		names := make([]string, 0, len(configs))
		for name := range configs {
			names = append(names, name)
		}
		sort.Strings(names)
	Variables:
		for _, n := range names {
			v := configs[n]
			if mode&InputModeVarUnset != 0 {
				if _, isSet := c.variables[n]; isSet {
					continue
				}
			}
			if c.uiInput == nil {
				log.Println("[WARN] Context.uiInput is nil during input walk")
				continue
			}
			var rawValue string
			retry := 0
			for {
				var err error
				rawValue, err = c.uiInput.Input(ctx, &InputOpts{
					Id:          fmt.Sprintf("var.%s", n),
					Query:       fmt.Sprintf("var.%s", n),
					Description: v.Description,
				})
				if err != nil {
					diags = diags.Append(tfdiags.Sourceless(
						tfdiags.Error,
						"Failed to request interactive input",
						fmt.Sprintf("Terraform attempted to request a value for var.%s interactively, but encountered an error: %s.", n, err),
					))
					return diags
				}
				if rawValue == "" && v.Default == cty.NilVal {
					if retry > 2 {
						diags = diags.Append(tfdiags.Sourceless(
							tfdiags.Error,
							"Required variable not assigned",
							fmt.Sprintf("The variable %q is required, so Terraform cannot proceed without a defined value for it.", n),
						))
						continue Variables
					}
					retry++
					continue
				}
				break
			}
			val, valDiags := v.ParsingMode.Parse(n, rawValue)
			diags = diags.Append(valDiags)
			if diags.HasErrors() {
				continue
			}
			c.variables[n] = &InputValue{
				Value:      val,
				SourceType: ValueFromInput,
			}
		}
	}
	if mode&InputModeProvider != 0 {
		log.Printf("[TRACE] Context.Input: Prompting for provider arguments")
		pcs := make(map[string]*configs.Provider)
		pas := make(map[string]addrs.ProviderConfig)
		for _, pc := range c.config.Module.ProviderConfigs {
			addr := pc.Addr()
			pcs[addr.String()] = pc
			pas[addr.String()] = addr
			log.Printf("[TRACE] Context.Input: Provider %s declared at %s", addr, pc.DeclRange)
		}
		for _, rc := range c.config.Module.ManagedResources {
			pa := rc.ProviderConfigAddr()
			if pa.Alias != "" {
				continue  
			}
			if _, exists := pcs[pa.String()]; !exists {
				pcs[pa.String()] = nil
				pas[pa.String()] = pa
				log.Printf("[TRACE] Context.Input: Provider %s implied by resource block at %s", pa, rc.DeclRange)
			}
		}
		for _, rc := range c.config.Module.DataResources {
			pa := rc.ProviderConfigAddr()
			if pa.Alias != "" {
				continue  
			}
			if _, exists := pcs[pa.String()]; !exists {
				pcs[pa.String()] = nil
				pas[pa.String()] = pa
				log.Printf("[TRACE] Context.Input: Provider %s implied by data block at %s", pa, rc.DeclRange)
			}
		}
		for pk, pa := range pas {
			pc := pcs[pk]  
			input := &PrefixUIInput{
				IdPrefix:    pk,
				QueryPrefix: pk + ".",
				UIInput:     c.uiInput,
			}
			schema := c.schemas.ProviderConfig(pa.Type)
			if schema == nil {
				log.Printf("[TRACE] Context.Input: No schema available for provider type %q", pa.Type)
				continue
			}
			var attrExprs hcl.Attributes  
			if pc != nil && pc.Config != nil {
				lowLevelSchema := schemaForInputSniffing(hcldec.ImpliedSchema(schema.DecoderSpec()))
				content, _, diags := pc.Config.PartialContent(lowLevelSchema)
				if diags.HasErrors() {
					log.Printf("[TRACE] Context.Input: %s has decode error, so ignoring: %s", pa, diags.Error())
					continue
				}
				attrExprs = content.Attributes
			}
			keys := make([]string, 0, len(schema.Attributes))
			for key := range schema.Attributes {
				keys = append(keys, key)
			}
			sort.Strings(keys)
			vals := map[string]cty.Value{}
			for _, key := range keys {
				attrS := schema.Attributes[key]
				if attrS.Optional {
					continue
				}
				if attrExprs != nil {
					if _, exists := attrExprs[key]; exists {
						continue
					}
				}
				if !attrS.Type.Equals(cty.String) {
					continue
				}
				log.Printf("[TRACE] Context.Input: Prompting for %s argument %s", pa, key)
				rawVal, err := input.Input(ctx, &InputOpts{
					Id:          key,
					Query:       key,
					Description: attrS.Description,
				})
				if err != nil {
					log.Printf("[TRACE] Context.Input: Failed to prompt for %s argument %s: %s", pa, key, err)
					continue
				}
				vals[key] = cty.StringVal(rawVal)
			}
			c.providerInputConfig[pk] = vals
			log.Printf("[TRACE] Context.Input: Input for %s: %#v", pk, vals)
		}
	}
	return diags
}
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.
package terraform
import (
	"context"
	"fmt"
	"log"
	"sort"
	"github.com/hashicorp/hcl2/hcl"
	"github.com/hashicorp/hcl2/hcldec"
	"github.com/zclconf/go-cty/cty"
	"github.com/hashicorp/terraform/addrs"
	"github.com/hashicorp/terraform/configs"
	"github.com/hashicorp/terraform/tfdiags"
)