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.
This commit is contained in:
parent
aa07f34dbe
commit
f14369e7fb
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -7,7 +7,6 @@ type walkOperation byte
|
|||
|
||||
const (
|
||||
walkInvalid walkOperation = iota
|
||||
walkInput
|
||||
walkApply
|
||||
walkPlan
|
||||
walkPlanDestroy
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue