From 9ae44977b7301beb98bb5bfa8b2bb07a1814d734 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Fri, 1 Jun 2018 10:29:55 -0700 Subject: [PATCH] core: Remove machinery for the "input" walk Provider input is now longer handled with a graph walk, so the code related to the input graph and walk are no longer needed. For now the Input method is retained on the ResourceProvider interface, but it will never be called. Subsequent work to revamp the provider API will remove this method. --- terraform/context.go | 5 --- terraform/context_graph_type.go | 2 - terraform/eval_provider.go | 27 ------------- terraform/eval_provider_test.go | 63 ------------------------------- terraform/evaltree_provider.go | 7 +--- terraform/graph_builder_input.go | 27 ------------- terraform/graph_walk_operation.go | 1 - terraform/interpolate.go | 20 +++------- terraform/node_module_variable.go | 11 ------ terraform/node_output.go | 11 ------ terraform/resource_provider.go | 11 +++--- 11 files changed, 11 insertions(+), 174 deletions(-) delete mode 100644 terraform/graph_builder_input.go diff --git a/terraform/context.go b/terraform/context.go index 351407b2fa..a91c05325a 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -270,9 +270,6 @@ func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, tfdiags. Validate: opts.Validate, }).Build(addrs.RootModuleInstance) - case GraphTypeInput: - // The input graph is just a slightly modified plan graph - fallthrough case GraphTypeValidate: // The validate graph is just a slightly modified plan graph fallthrough @@ -290,8 +287,6 @@ func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, tfdiags. // Some special cases for other graph types shared with plan currently var b GraphBuilder = p switch typ { - case GraphTypeInput: - b = InputGraphBuilder(p) case GraphTypeValidate: b = ValidateGraphBuilder(p) } diff --git a/terraform/context_graph_type.go b/terraform/context_graph_type.go index 97eefca354..0a424a01d1 100644 --- a/terraform/context_graph_type.go +++ b/terraform/context_graph_type.go @@ -14,7 +14,6 @@ const ( GraphTypePlan GraphTypePlanDestroy GraphTypeApply - GraphTypeInput GraphTypeValidate GraphTypeEval // only visits in-memory elements such as variables, locals, and outputs. ) @@ -24,7 +23,6 @@ const ( // graph types. var GraphTypeMap = map[string]GraphType{ "apply": GraphTypeApply, - "input": GraphTypeInput, "plan": GraphTypePlan, "plan-destroy": GraphTypePlanDestroy, "refresh": GraphTypeRefresh, diff --git a/terraform/eval_provider.go b/terraform/eval_provider.go index 6d5e2a82a4..be695b2f5b 100644 --- a/terraform/eval_provider.go +++ b/terraform/eval_provider.go @@ -142,30 +142,3 @@ func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) { return nil, nil } - -// EvalInputProvider is an EvalNode implementation that asks for input -// for the given provider configurations. -type EvalInputProvider struct { - Addr addrs.ProviderConfig - Provider *ResourceProvider - Config *configs.Provider -} - -func (n *EvalInputProvider) Eval(ctx EvalContext) (interface{}, error) { - // This is currently disabled. It used to interact with a provider method - // called Input, allowing the provider to capture input interactively - // itself, but once re-implemented we'll have this instead use the - // provider's configuration schema to automatically infer what we need - // to prompt for. - var diags tfdiags.Diagnostics - diag := &hcl.Diagnostic{ - Severity: hcl.DiagWarning, - Summary: "Provider input is temporarily disabled", - Detail: fmt.Sprintf("Skipped gathering input for %s because the input step is currently disabled pending a change to the provider API.", n.Addr), - } - if n.Config != nil { - diag.Subject = n.Config.DeclRange.Ptr() - } - diags = diags.Append(diag) - return nil, diags.ErrWithWarnings() -} diff --git a/terraform/eval_provider_test.go b/terraform/eval_provider_test.go index a2eaf1aba3..81e79bd1eb 100644 --- a/terraform/eval_provider_test.go +++ b/terraform/eval_provider_test.go @@ -1,14 +1,12 @@ package terraform import ( - "reflect" "testing" "github.com/hashicorp/hcl2/hcldec" "github.com/zclconf/go-cty/cty" "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/config/configschema" "github.com/hashicorp/terraform/configs" ) @@ -159,64 +157,3 @@ func TestEvalGetProvider(t *testing.T) { t.Fatalf("wrong provider address %s", ctx.ProviderAddr) } } - -func TestEvalInputProvider(t *testing.T) { - var provider ResourceProvider = &MockResourceProvider{ - InputFn: func(ui UIInput, c *ResourceConfig) (*ResourceConfig, error) { - if c.Config["mock_config"] != "mock" { - t.Fatalf("original config not passed to provider.Input") - } - - rawConfig, err := config.NewRawConfig(map[string]interface{}{ - "set_by_input": "input", - }) - if err != nil { - return nil, err - } - config := NewResourceConfig(rawConfig) - config.ComputedKeys = []string{"computed"} // fake computed key - - return config, nil - }, - } - ctx := &MockEvalContext{ProviderProvider: provider} - config := &configs.Provider{ - Name: "foo", - Config: configs.SynthBody("synth", map[string]cty.Value{ - "mock_config": cty.StringVal("mock"), - "set_in_config": cty.StringVal("input"), - }), - } - - n := &EvalInputProvider{ - Addr: addrs.ProviderConfig{Type: "foo"}, - Provider: &provider, - Config: config, - } - - result, err := n.Eval(ctx) - if err != nil { - t.Fatalf("Eval failed: %s", err) - } - if result != nil { - t.Fatalf("Eval returned non-nil result %#v", result) - } - - if !ctx.SetProviderInputCalled { - t.Fatalf("ctx.SetProviderInput wasn't called") - } - - if got, want := ctx.SetProviderInputAddr.String(), "provider.mock"; got != want { - t.Errorf("wrong provider name %q; want %q", got, want) - } - - inputCfg := ctx.SetProviderInputValues - - // we should only have the value that was set during Input - want := map[string]cty.Value{ - "set_by_input": cty.StringVal("input"), - } - if !reflect.DeepEqual(inputCfg, want) { - t.Errorf("got incorrect input config:\n%#v\nwant:\n%#v", inputCfg, want) - } -} diff --git a/terraform/evaltree_provider.go b/terraform/evaltree_provider.go index f4c2bc03df..f8ad7a9445 100644 --- a/terraform/evaltree_provider.go +++ b/terraform/evaltree_provider.go @@ -21,18 +21,13 @@ func ProviderEvalTree(n *NodeApplyableProvider, config *configs.Provider) EvalNo // Input stuff seq = append(seq, &EvalOpFilter{ - Ops: []walkOperation{walkInput, walkImport}, + Ops: []walkOperation{walkImport}, Node: &EvalSequence{ Nodes: []EvalNode{ &EvalGetProvider{ Addr: addr, Output: &provider, }, - &EvalInputProvider{ - Addr: relAddr, - Provider: &provider, - Config: config, - }, }, }, }) diff --git a/terraform/graph_builder_input.go b/terraform/graph_builder_input.go deleted file mode 100644 index 0df48cdb87..0000000000 --- a/terraform/graph_builder_input.go +++ /dev/null @@ -1,27 +0,0 @@ -package terraform - -import ( - "github.com/hashicorp/terraform/dag" -) - -// InputGraphBuilder creates the graph for the input operation. -// -// Unlike other graph builders, this is a function since it currently modifies -// and is based on the PlanGraphBuilder. The PlanGraphBuilder passed in will be -// modified and should not be used for any other operations. -func InputGraphBuilder(p *PlanGraphBuilder) GraphBuilder { - // We're going to customize the concrete functions - p.CustomConcrete = true - - // Set the provider to the normal provider. This will ask for input. - p.ConcreteProvider = func(a *NodeAbstractProvider) dag.Vertex { - return &NodeApplyableProvider{ - NodeAbstractProvider: a, - } - } - - // We purposely don't set any more concrete fields since the remainder - // should be no-ops. - - return p -} diff --git a/terraform/graph_walk_operation.go b/terraform/graph_walk_operation.go index d2605d8c75..a3756e764d 100644 --- a/terraform/graph_walk_operation.go +++ b/terraform/graph_walk_operation.go @@ -7,7 +7,6 @@ type walkOperation byte const ( walkInvalid walkOperation = iota - walkInput walkApply walkPlan walkPlanDestroy diff --git a/terraform/interpolate.go b/terraform/interpolate.go index 6b9dbb6e82..26c185751a 100644 --- a/terraform/interpolate.go +++ b/terraform/interpolate.go @@ -199,13 +199,13 @@ func (i *Interpolater) valueResourceVar( } if variable == nil { - // During the input walk we tolerate missing variables because + // During the refresh walk we tolerate missing variables because // we haven't yet had a chance to refresh state, so dynamic data may // not yet be complete. // If it truly is missing, we'll catch it on a later walk. // This applies only to graph nodes that interpolate during the - // config walk, e.g. providers. - if i.Operation == walkInput || i.Operation == walkRefresh { + // refresh walk, e.g. providers. + if i.Operation == walkRefresh { result[n] = unknownVariable() return nil } @@ -526,10 +526,7 @@ MISSING: // // For a Destroy, we're also fine with computed values, since our goal is // only to get destroy nodes for existing resources. - // - // For an input walk, computed values are okay to return because we're only - // looking for missing variables to prompt the user for. - if i.Operation == walkRefresh || i.Operation == walkPlanDestroy || i.Operation == walkInput { + if i.Operation == walkRefresh || i.Operation == walkPlanDestroy { return &unknownVariable, nil } @@ -549,13 +546,6 @@ func (i *Interpolater) computeResourceMultiVariable( unknownVariable := unknownVariable() - // If we're only looking for input, we don't need to expand a - // multi-variable. This prevents us from encountering things that should be - // known but aren't because the state has yet to be refreshed. - if i.Operation == walkInput { - return &unknownVariable, nil - } - // Get the information about this resource variable, and verify // that it exists and such. module, cr, err := i.resourceVariableInfo(scope, v) @@ -637,7 +627,7 @@ func (i *Interpolater) computeResourceMultiVariable( // // For an input walk, computed values are okay to return because we're only // looking for missing variables to prompt the user for. - if i.Operation == walkRefresh || i.Operation == walkPlanDestroy || i.Operation == walkDestroy || i.Operation == walkInput { + if i.Operation == walkRefresh || i.Operation == walkPlanDestroy || i.Operation == walkDestroy { return &unknownVariable, nil } diff --git a/terraform/node_module_variable.go b/terraform/node_module_variable.go index 02983d6a8c..aca5a6a3fd 100644 --- a/terraform/node_module_variable.go +++ b/terraform/node_module_variable.go @@ -121,17 +121,6 @@ func (n *NodeApplyableModuleVariable) EvalTree() EvalNode { IgnoreDiagnostics: false, }, }, - &EvalOpFilter{ - Ops: []walkOperation{walkInput}, - Node: &EvalModuleCallArgument{ - Addr: n.Addr.Variable, - Config: n.Config, - Expr: n.Expr, - Values: vals, - - IgnoreDiagnostics: true, - }, - }, &EvalSetModuleCallArguments{ Module: call, diff --git a/terraform/node_output.go b/terraform/node_output.go index c42dd4860f..bb3d065311 100644 --- a/terraform/node_output.go +++ b/terraform/node_output.go @@ -115,17 +115,6 @@ func (n *NodeApplyableOutput) References() []*addrs.Reference { func (n *NodeApplyableOutput) EvalTree() EvalNode { return &EvalSequence{ Nodes: []EvalNode{ - &EvalOpFilter{ - // Don't let interpolation errors stop Input, since it happens - // before Refresh. - Ops: []walkOperation{walkInput}, - Node: &EvalWriteOutput{ - Addr: n.Addr.OutputValue, - Sensitive: n.Config.Sensitive, - Expr: n.Config.Expr, - ContinueOnErr: true, - }, - }, &EvalOpFilter{ Ops: []walkOperation{walkRefresh, walkPlan, walkApply, walkValidate, walkDestroy, walkPlanDestroy}, Node: &EvalWriteOutput{ diff --git a/terraform/resource_provider.go b/terraform/resource_provider.go index 93fd14fc80..7c978d220e 100644 --- a/terraform/resource_provider.go +++ b/terraform/resource_provider.go @@ -30,13 +30,12 @@ type ResourceProvider interface { // resource or data source has the SchemaAvailable flag set. GetSchema(*ProviderSchemaRequest) (*ProviderSchema, error) - // Input is called to ask the provider to ask the user for input - // for completing the configuration if necesarry. + // Input was used prior to v0.12 to ask the provider to prompt the user + // for input to complete the configuration. // - // This may or may not be called, so resource provider writers shouldn't - // rely on this being available to set some default values for validate - // later. Example of a situation where this wouldn't be called is if - // the user is not using a TTY. + // From v0.12 onwards this method is never called because Terraform Core + // is able to handle the necessary input logic itself based on the + // schema returned from GetSchema. Input(UIInput, *ResourceConfig) (*ResourceConfig, error) // Validate is called once at the beginning with the raw configuration