From 906d3991890f7358ee3505b02e9371c1f1f0a69c Mon Sep 17 00:00:00 2001 From: James Bardin Date: Mon, 21 Sep 2020 21:53:55 -0400 Subject: [PATCH] remove refresh! Delete all the code associated with the Refresh walk --- terraform/context.go | 10 - terraform/context_graph_type.go | 6 +- terraform/graph_builder_refresh.go | 190 ---------- terraform/graph_builder_refresh_test.go | 79 ----- terraform/graph_walk_operation.go | 1 - terraform/graphtype_string.go | 16 +- terraform/node_data_refresh.go | 283 --------------- terraform/node_data_refresh_test.go | 178 ---------- terraform/node_module_variable.go | 2 +- terraform/node_output.go | 2 +- terraform/node_provider.go | 2 +- terraform/node_resource_destroy_deposed.go | 40 --- terraform/node_resource_refresh.go | 381 --------------------- terraform/node_resource_refresh_test.go | 159 --------- terraform/walkoperation_string.go | 13 +- 15 files changed, 17 insertions(+), 1345 deletions(-) delete mode 100644 terraform/graph_builder_refresh.go delete mode 100644 terraform/graph_builder_refresh_test.go delete mode 100644 terraform/node_data_refresh.go delete mode 100644 terraform/node_data_refresh_test.go delete mode 100644 terraform/node_resource_refresh.go delete mode 100644 terraform/node_resource_refresh_test.go diff --git a/terraform/context.go b/terraform/context.go index 56b5578b6..23db43f5a 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -311,16 +311,6 @@ func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, tfdiags. Validate: opts.Validate, }).Build(addrs.RootModuleInstance) - case GraphTypeRefresh: - return (&RefreshGraphBuilder{ - Config: c.config, - State: c.state, - Components: c.components, - Schemas: c.schemas, - Targets: c.targets, - Validate: opts.Validate, - }).Build(addrs.RootModuleInstance) - case GraphTypeEval: return (&EvalGraphBuilder{ Config: c.config, diff --git a/terraform/context_graph_type.go b/terraform/context_graph_type.go index 4448d8706..aefa17f77 100644 --- a/terraform/context_graph_type.go +++ b/terraform/context_graph_type.go @@ -8,9 +8,7 @@ package terraform type GraphType byte const ( - GraphTypeInvalid GraphType = 0 - GraphTypeLegacy GraphType = iota - GraphTypeRefresh + GraphTypeInvalid GraphType = iota GraphTypePlan GraphTypePlanDestroy GraphTypeApply @@ -25,8 +23,6 @@ var GraphTypeMap = map[string]GraphType{ "apply": GraphTypeApply, "plan": GraphTypePlan, "plan-destroy": GraphTypePlanDestroy, - "refresh": GraphTypeRefresh, - "legacy": GraphTypeLegacy, "validate": GraphTypeValidate, "eval": GraphTypeEval, } diff --git a/terraform/graph_builder_refresh.go b/terraform/graph_builder_refresh.go deleted file mode 100644 index 2721673d9..000000000 --- a/terraform/graph_builder_refresh.go +++ /dev/null @@ -1,190 +0,0 @@ -package terraform - -import ( - "log" - - "github.com/hashicorp/terraform/states" - "github.com/hashicorp/terraform/tfdiags" - - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/configs" - "github.com/hashicorp/terraform/dag" -) - -// RefreshGraphBuilder implements GraphBuilder and is responsible for building -// a graph for refreshing (updating the Terraform state). -// -// The primary difference between this graph and others: -// -// * Based on the state since it represents the only resources that -// need to be refreshed. -// -// * Ignores lifecycle options since no lifecycle events occur here. This -// simplifies the graph significantly since complex transforms such as -// create-before-destroy can be completely ignored. -// -type RefreshGraphBuilder struct { - // Config is the configuration tree. - Config *configs.Config - - // State is the prior state - State *states.State - - // Components is a factory for the plug-in components (providers and - // provisioners) available for use. - Components contextComponentFactory - - // Schemas is the repository of schemas we will draw from to analyse - // the configuration. - Schemas *Schemas - - // Targets are resources to target - Targets []addrs.Targetable - - // Validate will do structural validation of the graph. - Validate bool -} - -// See GraphBuilder -func (b *RefreshGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) { - return (&BasicGraphBuilder{ - Steps: b.Steps(), - Validate: b.Validate, - Name: "RefreshGraphBuilder", - }).Build(path) -} - -// See GraphBuilder -func (b *RefreshGraphBuilder) Steps() []GraphTransformer { - // Custom factory for creating providers. - concreteProvider := func(a *NodeAbstractProvider) dag.Vertex { - return &NodeApplyableProvider{ - NodeAbstractProvider: a, - } - } - - concreteManagedResource := func(a *NodeAbstractResource) dag.Vertex { - return &nodeExpandRefreshableManagedResource{ - NodeAbstractResource: a, - } - } - - concreteManagedResourceInstance := func(a *NodeAbstractResourceInstance) dag.Vertex { - return &NodeRefreshableManagedResourceInstance{ - NodeAbstractResourceInstance: a, - } - } - - concreteResourceInstanceDeposed := func(a *NodeAbstractResourceInstance, key states.DeposedKey) dag.Vertex { - // The "Plan" node type also handles refreshing behavior. - return &NodePlanDeposedResourceInstanceObject{ - NodeAbstractResourceInstance: a, - DeposedKey: key, - } - } - - concreteDataResource := func(a *NodeAbstractResource) dag.Vertex { - return &nodeExpandRefreshableDataResource{ - NodeAbstractResource: a, - } - } - - steps := []GraphTransformer{ - // Creates all the managed resources that aren't in the state, but only if - // we have a state already. No resources in state means there's not - // anything to refresh. - func() GraphTransformer { - if b.State.HasResources() { - return &ConfigTransformer{ - Concrete: concreteManagedResource, - Config: b.Config, - Unique: true, - ModeFilter: true, - Mode: addrs.ManagedResourceMode, - } - } - log.Println("[TRACE] No managed resources in state during refresh; skipping managed resource transformer") - return nil - }(), - - // Creates all the data resources that aren't in the state. This will also - // add any orphans from scaling in as destroy nodes. - &ConfigTransformer{ - Concrete: concreteDataResource, - Config: b.Config, - Unique: true, - ModeFilter: true, - Mode: addrs.DataResourceMode, - }, - - // Add any fully-orphaned resources from config (ones that have been - // removed completely, not ones that are just orphaned due to a scaled-in - // count. - &OrphanResourceInstanceTransformer{ - Concrete: concreteManagedResourceInstance, - State: b.State, - Config: b.Config, - }, - - // We also need nodes for any deposed instance objects present in the - // state, so we can check if they still exist. (This intentionally - // skips creating nodes for _current_ objects, since ConfigTransformer - // created nodes that will do that during DynamicExpand.) - &StateTransformer{ - ConcreteDeposed: concreteResourceInstanceDeposed, - State: b.State, - }, - - // Attach the state - &AttachStateTransformer{State: b.State}, - - // Attach the configuration to any resources - &AttachResourceConfigTransformer{Config: b.Config}, - - // Add root variables - &RootVariableTransformer{Config: b.Config}, - - // Add the local values - &LocalTransformer{Config: b.Config}, - - // Add the outputs - &OutputTransformer{Config: b.Config}, - - // Add module variables - &ModuleVariableTransformer{Config: b.Config}, - - TransformProviders(b.Components.ResourceProviders(), concreteProvider, b.Config), - - // Must attach schemas before ReferenceTransformer so that we can - // analyze the configuration to find references. - &AttachSchemaTransformer{Schemas: b.Schemas, Config: b.Config}, - - // Create expansion nodes for all of the module calls. This must - // come after all other transformers that create nodes representing - // objects that can belong to modules. - &ModuleExpansionTransformer{Config: b.Config}, - - // Connect so that the references are ready for targeting. We'll - // have to connect again later for providers and so on. - &ReferenceTransformer{}, - &AttachDependenciesTransformer{}, - &attachDataResourceDependenciesTransformer{}, - - // Target - &TargetsTransformer{ - Targets: b.Targets, - }, - - // Close opened plugin connections - &CloseProviderTransformer{}, - - // Close root module - &CloseRootModuleTransformer{}, - - // Perform the transitive reduction to make our graph a bit - // more sane if possible (it usually is possible). - &TransitiveReductionTransformer{}, - } - - return steps -} diff --git a/terraform/graph_builder_refresh_test.go b/terraform/graph_builder_refresh_test.go deleted file mode 100644 index be9a1a610..000000000 --- a/terraform/graph_builder_refresh_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package terraform - -import ( - "strings" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/states" -) - -func TestRefreshGraphBuilder_configOrphans(t *testing.T) { - - m := testModule(t, "refresh-config-orphan") - - state := states.NewState() - root := state.EnsureModule(addrs.RootModuleInstance) - deposedKey := states.DeposedKey("00000001") - testSetResourceInstanceDeposed(root, "test_object.foo[0]", `{"id":"foo"}`, `provider["registry.terraform.io/hashicorp/test"]`, deposedKey) - testSetResourceInstanceDeposed(root, "test_object.foo[1]", `{"id":"bar"}`, `provider["registry.terraform.io/hashicorp/test"]`, deposedKey) - testSetResourceInstanceDeposed(root, "test_object.foo[2]", `{"id":"baz"}`, `provider["registry.terraform.io/hashicorp/test"]`, deposedKey) - - // NOTE: Real-world data resources don't get deposed - testSetResourceInstanceDeposed(root, "data.test_object.foo[0]", `{"id":"foo"}`, `provider["registry.terraform.io/hashicorp/test"]`, deposedKey) - testSetResourceInstanceDeposed(root, "data.test_object.foo[1]", `{"id":"bar"}`, `provider["registry.terraform.io/hashicorp/test"]`, deposedKey) - testSetResourceInstanceDeposed(root, "data.test_object.foo[2]", `{"id":"baz"}`, `provider["registry.terraform.io/hashicorp/test"]`, deposedKey) - - b := &RefreshGraphBuilder{ - Config: m, - State: state, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), - } - g, err := b.Build(addrs.RootModuleInstance) - if err != nil { - t.Fatalf("Error building graph: %s", err) - } - - actual := strings.TrimSpace(g.StringWithNodeTypes()) - expected := strings.TrimSpace(` -data.test_object.foo[0] - *terraform.NodeRefreshableManagedResourceInstance - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -data.test_object.foo[0] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -data.test_object.foo[1] - *terraform.NodeRefreshableManagedResourceInstance - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -data.test_object.foo[1] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -data.test_object.foo[2] - *terraform.NodeRefreshableManagedResourceInstance - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -data.test_object.foo[2] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -provider["registry.terraform.io/hashicorp/test"] (close) - *terraform.graphNodeCloseProvider - data.test_object.foo[0] - *terraform.NodeRefreshableManagedResourceInstance - data.test_object.foo[0] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - data.test_object.foo[1] - *terraform.NodeRefreshableManagedResourceInstance - data.test_object.foo[1] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - data.test_object.foo[2] - *terraform.NodeRefreshableManagedResourceInstance - data.test_object.foo[2] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - test_object.foo (expand) - *terraform.nodeExpandRefreshableManagedResource - test_object.foo[0] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - test_object.foo[1] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - test_object.foo[2] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject -root - *terraform.nodeCloseModule - provider["registry.terraform.io/hashicorp/test"] (close) - *terraform.graphNodeCloseProvider -test_object.foo (expand) - *terraform.nodeExpandRefreshableManagedResource - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -test_object.foo[0] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -test_object.foo[1] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -test_object.foo[2] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject - provider["registry.terraform.io/hashicorp/test"] - *terraform.NodeApplyableProvider -`) - if expected != actual { - t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s\ndiff:\n%s", actual, expected, cmp.Diff(expected, actual)) - } -} diff --git a/terraform/graph_walk_operation.go b/terraform/graph_walk_operation.go index 859f6fb12..798ff20e1 100644 --- a/terraform/graph_walk_operation.go +++ b/terraform/graph_walk_operation.go @@ -10,7 +10,6 @@ const ( walkApply walkPlan walkPlanDestroy - walkRefresh walkValidate walkDestroy walkImport diff --git a/terraform/graphtype_string.go b/terraform/graphtype_string.go index b51e1a266..2d4026e46 100644 --- a/terraform/graphtype_string.go +++ b/terraform/graphtype_string.go @@ -9,18 +9,16 @@ func _() { // Re-run the stringer command to generate them again. var x [1]struct{} _ = x[GraphTypeInvalid-0] - _ = x[GraphTypeLegacy-1] - _ = x[GraphTypeRefresh-2] - _ = x[GraphTypePlan-3] - _ = x[GraphTypePlanDestroy-4] - _ = x[GraphTypeApply-5] - _ = x[GraphTypeValidate-6] - _ = x[GraphTypeEval-7] + _ = x[GraphTypePlan-1] + _ = x[GraphTypePlanDestroy-2] + _ = x[GraphTypeApply-3] + _ = x[GraphTypeValidate-4] + _ = x[GraphTypeEval-5] } -const _GraphType_name = "GraphTypeInvalidGraphTypeLegacyGraphTypeRefreshGraphTypePlanGraphTypePlanDestroyGraphTypeApplyGraphTypeValidateGraphTypeEval" +const _GraphType_name = "GraphTypeInvalidGraphTypePlanGraphTypePlanDestroyGraphTypeApplyGraphTypeValidateGraphTypeEval" -var _GraphType_index = [...]uint8{0, 16, 31, 47, 60, 80, 94, 111, 124} +var _GraphType_index = [...]uint8{0, 16, 29, 49, 63, 80, 93} func (i GraphType) String() string { if i >= GraphType(len(_GraphType_index)-1) { diff --git a/terraform/node_data_refresh.go b/terraform/node_data_refresh.go deleted file mode 100644 index 740af0fbe..000000000 --- a/terraform/node_data_refresh.go +++ /dev/null @@ -1,283 +0,0 @@ -package terraform - -import ( - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/dag" - "github.com/hashicorp/terraform/plans" - "github.com/hashicorp/terraform/states" - "github.com/hashicorp/terraform/tfdiags" -) - -type nodeExpandRefreshableDataResource struct { - *NodeAbstractResource -} - -var ( - _ GraphNodeDynamicExpandable = (*nodeExpandRefreshableDataResource)(nil) - _ GraphNodeReferenceable = (*nodeExpandRefreshableDataResource)(nil) - _ GraphNodeReferencer = (*nodeExpandRefreshableDataResource)(nil) - _ GraphNodeConfigResource = (*nodeExpandRefreshableDataResource)(nil) - _ GraphNodeAttachResourceConfig = (*nodeExpandRefreshableDataResource)(nil) -) - -func (n *nodeExpandRefreshableDataResource) Name() string { - return n.NodeAbstractResource.Name() + " (expand)" -} - -func (n *nodeExpandRefreshableDataResource) References() []*addrs.Reference { - return (&NodeRefreshableManagedResource{NodeAbstractResource: n.NodeAbstractResource}).References() -} - -func (n *nodeExpandRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, error) { - var g Graph - - expander := ctx.InstanceExpander() - for _, module := range expander.ExpandModule(n.Addr.Module) { - g.Add(&NodeRefreshableDataResource{ - NodeAbstractResource: n.NodeAbstractResource, - Addr: n.Addr.Resource.Absolute(module), - }) - } - - return &g, nil -} - -// NodeRefreshableDataResource represents a resource that is "refreshable". -type NodeRefreshableDataResource struct { - *NodeAbstractResource - - Addr addrs.AbsResource -} - -var ( - _ GraphNodeModuleInstance = (*NodeRefreshableDataResource)(nil) - _ GraphNodeDynamicExpandable = (*NodeRefreshableDataResource)(nil) - _ GraphNodeReferenceable = (*NodeRefreshableDataResource)(nil) - _ GraphNodeReferencer = (*NodeRefreshableDataResource)(nil) - _ GraphNodeConfigResource = (*NodeRefreshableDataResource)(nil) - _ GraphNodeAttachResourceConfig = (*NodeRefreshableDataResource)(nil) - _ GraphNodeAttachProviderMetaConfigs = (*NodeAbstractResource)(nil) -) - -func (n *NodeRefreshableDataResource) Path() addrs.ModuleInstance { - return n.Addr.Module -} - -// GraphNodeDynamicExpandable -func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, error) { - var diags tfdiags.Diagnostics - - expander := ctx.InstanceExpander() - - switch { - case n.Config.Count != nil: - count, countDiags := evaluateCountExpressionValue(n.Config.Count, ctx) - diags = diags.Append(countDiags) - if countDiags.HasErrors() { - return nil, diags.Err() - } - if !count.IsKnown() { - // If the count isn't known yet, we'll skip refreshing and try expansion - // again during the plan walk. - return nil, nil - } - - c, _ := count.AsBigFloat().Int64() - expander.SetResourceCount(n.Addr.Module, n.Addr.Resource, int(c)) - - case n.Config.ForEach != nil: - forEachVal, forEachDiags := evaluateForEachExpressionValue(n.Config.ForEach, ctx) - diags = diags.Append(forEachDiags) - if forEachDiags.HasErrors() { - return nil, diags.Err() - } - if !forEachVal.IsKnown() { - // If the for_each isn't known yet, we'll skip refreshing and try expansion - // again during the plan walk. - return nil, nil - } - - expander.SetResourceForEach(n.Addr.Module, n.Addr.Resource, forEachVal.AsValueMap()) - - default: - expander.SetResourceSingle(n.Addr.Module, n.Addr.Resource) - } - - // Next we need to potentially rename an instance address in the state - // if we're transitioning whether "count" is set at all. - fixResourceCountSetTransition(ctx, n.ResourceAddr(), n.Config.Count != nil) - - instanceAddrs := expander.ExpandResource(n.Addr) - - // Our graph transformers require access to the full state, so we'll - // temporarily lock it while we work on this. - state := ctx.State().Lock() - defer ctx.State().Unlock() - - // The concrete resource factory we'll use - concreteResource := func(a *NodeAbstractResourceInstance) dag.Vertex { - // Add the config and state since we don't do that via transforms - a.Config = n.Config - a.ResolvedProvider = n.ResolvedProvider - a.ProviderMetas = n.ProviderMetas - a.dependsOn = n.dependsOn - a.forceDependsOn = n.forceDependsOn - a.Targets = n.Targets - - return &NodeRefreshableDataResourceInstance{ - NodeAbstractResourceInstance: a, - } - } - - // We also need a destroyable resource for orphans that are a result of a - // scaled-in count. - concreteResourceDestroyable := func(a *NodeAbstractResourceInstance) dag.Vertex { - // Add the config and provider since we don't do that via transforms - a.Config = n.Config - a.ResolvedProvider = n.ResolvedProvider - - return &NodeDestroyableDataResourceInstance{ - NodeAbstractResourceInstance: a, - } - } - - // Start creating the steps - steps := []GraphTransformer{ - // Expand the count. - &ResourceCountTransformer{ - Concrete: concreteResource, - Schema: n.Schema, - Addr: n.ResourceAddr(), - InstanceAddrs: instanceAddrs, - }, - - // Add the count orphans. As these are orphaned refresh nodes, we add them - // directly as NodeDestroyableDataResource. - &OrphanResourceInstanceCountTransformer{ - Concrete: concreteResourceDestroyable, - Addr: n.Addr, - InstanceAddrs: instanceAddrs, - State: state, - }, - - // Attach the state - &AttachStateTransformer{State: state}, - - // Targeting - &TargetsTransformer{Targets: n.Targets}, - - // Connect references so ordering is correct - &ReferenceTransformer{}, - - // Make sure there is a single root - &RootTransformer{}, - } - - // Build the graph - b := &BasicGraphBuilder{ - Steps: steps, - Validate: true, - Name: "NodeRefreshableDataResource", - } - - graph, diags := b.Build(nil) - return graph, diags.ErrWithWarnings() -} - -// NodeRefreshableDataResourceInstance represents a single resource instance -// that is refreshable. -type NodeRefreshableDataResourceInstance struct { - *NodeAbstractResourceInstance -} - -// GraphNodeExecutable -func (n *NodeRefreshableDataResourceInstance) Execute(ctx EvalContext, op walkOperation) error { - addr := n.ResourceInstanceAddr() - - // These variables are the state for the eval sequence below, and are - // updated through pointers. - var change *plans.ResourceInstanceChange - var state *states.ResourceInstanceObject - - provider, providerSchema, err := GetProvider(ctx, n.ResolvedProvider) - if err != nil { - return err - } - - // EvalReadState - readStateReq := &EvalReadState{ - Addr: addr.Resource, - Provider: &provider, - ProviderSchema: &providerSchema, - Output: &state, - } - _, err = readStateReq.Eval(ctx) - if err != nil { - return err - } - - // EvalReadDataRefresh will _attempt_ to read the data source, but - // may generate an incomplete planned object if the configuration - // includes values that won't be known until apply. - readDataRefreshReq := &evalReadDataRefresh{ - evalReadData{ - Addr: addr.Resource, - Config: n.Config, - Provider: &provider, - ProviderAddr: n.ResolvedProvider, - ProviderMetas: n.ProviderMetas, - ProviderSchema: &providerSchema, - OutputChange: &change, - State: &state, - dependsOn: n.dependsOn, - forceDependsOn: n.forceDependsOn, - }, - } - _, err = readDataRefreshReq.Eval(ctx) - if err != nil { - return err - } - - if change == nil { - // EvalWriteState - writeStateRequest := EvalWriteState{ - Addr: addr.Resource, - ProviderAddr: n.ResolvedProvider, - State: &state, - ProviderSchema: &providerSchema, - } - _, err := writeStateRequest.Eval(ctx) - if err != nil { - return err - } - - err = UpdateStateHook(ctx) - if err != nil { - return err - } - - } else { - // EvalWriteDiff - writeDiffReq := &EvalWriteDiff{ - Addr: addr.Resource, - Change: &change, - ProviderSchema: &providerSchema, - } - _, err = writeDiffReq.Eval(ctx) - if err != nil { - return err - } - // EvalWriteState - writeStateRequest := EvalWriteState{ - Addr: addr.Resource, - ProviderAddr: n.ResolvedProvider, - State: &state, - ProviderSchema: &providerSchema, - } - _, err := writeStateRequest.Eval(ctx) - if err != nil { - return err - } - } - return err -} diff --git a/terraform/node_data_refresh_test.go b/terraform/node_data_refresh_test.go deleted file mode 100644 index ebc4044e9..000000000 --- a/terraform/node_data_refresh_test.go +++ /dev/null @@ -1,178 +0,0 @@ -package terraform - -import ( - "testing" - - "github.com/zclconf/go-cty/cty" - - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/instances" -) - -func TestNodeRefreshableDataResourceDynamicExpand_scaleOut(t *testing.T) { - m := testModule(t, "refresh-data-scale-inout") - - state := MustShimLegacyState(&State{ - Modules: []*ModuleState{ - &ModuleState{ - Path: rootModulePath, - Resources: map[string]*ResourceState{ - "data.aws_instance.foo.0": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "foo", - }, - }, - }, - "data.aws_instance.foo.1": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "bar", - }, - }, - }, - }, - }, - }, - }) - - addr := addrs.RootModule.Resource(addrs.DataResourceMode, "aws_instance", "foo") - n := &NodeRefreshableDataResource{ - NodeAbstractResource: &NodeAbstractResource{ - Addr: addr, - Config: m.Module.DataResources["data.aws_instance.foo"], - }, - Addr: addr.Absolute(addrs.RootModuleInstance), - } - - g, err := n.DynamicExpand(&MockEvalContext{ - PathPath: addrs.RootModuleInstance, - StateState: state.SyncWrapper(), - InstanceExpanderExpander: instances.NewExpander(), - - // DynamicExpand will call EvaluateExpr to evaluate the "count" - // expression, which is just a literal number 3 in the fixture config - // and so we'll just hard-code this here too. - EvaluateExprResult: cty.NumberIntVal(3), - }) - if err != nil { - t.Fatalf("error on DynamicExpand: %s", err) - } - - actual := g.StringWithNodeTypes() - expected := `data.aws_instance.foo[0] - *terraform.NodeRefreshableDataResourceInstance -data.aws_instance.foo[1] - *terraform.NodeRefreshableDataResourceInstance -data.aws_instance.foo[2] - *terraform.NodeRefreshableDataResourceInstance -root - terraform.graphNodeRoot - data.aws_instance.foo[0] - *terraform.NodeRefreshableDataResourceInstance - data.aws_instance.foo[1] - *terraform.NodeRefreshableDataResourceInstance - data.aws_instance.foo[2] - *terraform.NodeRefreshableDataResourceInstance -` - if expected != actual { - t.Fatalf("Expected:\n%s\nGot:\n%s", expected, actual) - } -} - -func TestNodeRefreshableDataResourceDynamicExpand_scaleIn(t *testing.T) { - m := testModule(t, "refresh-data-scale-inout") - - state := MustShimLegacyState(&State{ - Modules: []*ModuleState{ - &ModuleState{ - Path: rootModulePath, - Resources: map[string]*ResourceState{ - "data.aws_instance.foo.0": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "foo", - }, - }, - }, - "data.aws_instance.foo.1": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "bar", - }, - }, - }, - "data.aws_instance.foo.2": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "baz", - }, - }, - }, - "data.aws_instance.foo.3": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "qux", - }, - }, - }, - }, - }, - }, - }) - - addr := addrs.RootModule.Resource(addrs.DataResourceMode, "aws_instance", "foo") - n := &NodeRefreshableDataResource{ - NodeAbstractResource: &NodeAbstractResource{ - Addr: addr, - Config: m.Module.DataResources["data.aws_instance.foo"], - ResolvedProvider: addrs.AbsProviderConfig{ - Provider: addrs.NewDefaultProvider("aws"), - Module: addrs.RootModule, - }, - }, - Addr: addr.Absolute(addrs.RootModuleInstance), - } - - g, err := n.DynamicExpand(&MockEvalContext{ - PathPath: addrs.RootModuleInstance, - StateState: state.SyncWrapper(), - InstanceExpanderExpander: instances.NewExpander(), - - // DynamicExpand will call EvaluateExpr to evaluate the "count" - // expression, which is just a literal number 3 in the fixture config - // and so we'll just hard-code this here too. - EvaluateExprResult: cty.NumberIntVal(3), - }) - if err != nil { - t.Fatalf("error on DynamicExpand: %s", err) - } - actual := g.StringWithNodeTypes() - expected := `data.aws_instance.foo[0] - *terraform.NodeRefreshableDataResourceInstance -data.aws_instance.foo[1] - *terraform.NodeRefreshableDataResourceInstance -data.aws_instance.foo[2] - *terraform.NodeRefreshableDataResourceInstance -data.aws_instance.foo[3] - *terraform.NodeDestroyableDataResourceInstance -root - terraform.graphNodeRoot - data.aws_instance.foo[0] - *terraform.NodeRefreshableDataResourceInstance - data.aws_instance.foo[1] - *terraform.NodeRefreshableDataResourceInstance - data.aws_instance.foo[2] - *terraform.NodeRefreshableDataResourceInstance - data.aws_instance.foo[3] - *terraform.NodeDestroyableDataResourceInstance -` - if expected != actual { - t.Fatalf("Expected:\n%s\nGot:\n%s", expected, actual) - } - - var destroyableDataResource *NodeDestroyableDataResourceInstance - for _, v := range g.Vertices() { - if r, ok := v.(*NodeDestroyableDataResourceInstance); ok { - destroyableDataResource = r - } - } - - if destroyableDataResource == nil { - t.Fatal("failed to find a destroyableDataResource") - } - - if destroyableDataResource.ResolvedProvider.Provider.Type == "" { - t.Fatal("NodeDestroyableDataResourceInstance missing provider config") - } -} diff --git a/terraform/node_module_variable.go b/terraform/node_module_variable.go index 504bc9d0a..707d0986f 100644 --- a/terraform/node_module_variable.go +++ b/terraform/node_module_variable.go @@ -153,7 +153,7 @@ func (n *nodeModuleVariable) Execute(ctx EvalContext, op walkOperation) error { var err error switch op { - case walkRefresh, walkPlan, walkApply, walkDestroy, walkImport: + case walkPlan, walkApply, walkDestroy, walkImport: vals, err = n.EvalModuleCallArgument(ctx, false) if err != nil { return err diff --git a/terraform/node_output.go b/terraform/node_output.go index 8423931fd..36dff70cb 100644 --- a/terraform/node_output.go +++ b/terraform/node_output.go @@ -200,7 +200,7 @@ func (n *NodeApplyableOutput) References() []*addrs.Reference { func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) error { switch op { // Everything except walkImport - case walkEval, walkRefresh, walkPlan, walkApply, walkValidate, walkDestroy, walkPlanDestroy: + case walkEval, walkPlan, walkApply, walkValidate, walkDestroy, walkPlanDestroy: // This has to run before we have a state lock, since evaluation also // reads the state val, diags := ctx.EvaluateExpr(n.Config.Expr, cty.DynamicPseudoType, nil) diff --git a/terraform/node_provider.go b/terraform/node_provider.go index ddeeb0348..c901eb417 100644 --- a/terraform/node_provider.go +++ b/terraform/node_provider.go @@ -33,7 +33,7 @@ func (n *NodeApplyableProvider) Execute(ctx EvalContext, op walkOperation) error switch op { case walkValidate: return n.ValidateProvider(ctx, provider) - case walkRefresh, walkPlan, walkApply, walkDestroy: + case walkPlan, walkApply, walkDestroy: return n.ConfigureProvider(ctx, provider, false) case walkImport: return n.ConfigureProvider(ctx, provider, true) diff --git a/terraform/node_resource_destroy_deposed.go b/terraform/node_resource_destroy_deposed.go index 162655bf3..550cffea5 100644 --- a/terraform/node_resource_destroy_deposed.go +++ b/terraform/node_resource_destroy_deposed.go @@ -73,46 +73,6 @@ func (n *NodePlanDeposedResourceInstanceObject) EvalTree() EvalNode { seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)} - // During the refresh walk we will ensure that our record of the deposed - // object is up-to-date. If it was already deleted outside of Terraform - // then this will remove it from state and thus avoid us planning a - // destroy for it during the subsequent plan walk. - seq.Nodes = append(seq.Nodes, &EvalOpFilter{ - Ops: []walkOperation{walkRefresh}, - Node: &EvalSequence{ - Nodes: []EvalNode{ - &EvalGetProvider{ - Addr: n.ResolvedProvider, - Output: &provider, - Schema: &providerSchema, - }, - &EvalReadStateDeposed{ - Addr: addr.Resource, - Provider: &provider, - ProviderSchema: &providerSchema, - Key: n.DeposedKey, - Output: &state, - }, - &EvalRefresh{ - Addr: addr.Resource, - ProviderAddr: n.ResolvedProvider, - Provider: &provider, - ProviderMetas: n.ProviderMetas, - ProviderSchema: &providerSchema, - State: &state, - Output: &state, - }, - &EvalWriteStateDeposed{ - Addr: addr.Resource, - Key: n.DeposedKey, - ProviderAddr: n.ResolvedProvider, - ProviderSchema: &providerSchema, - State: &state, - }, - }, - }, - }) - // During the plan walk we always produce a planned destroy change, because // destroying is the only supported action for deposed objects. var change *plans.ResourceInstanceChange diff --git a/terraform/node_resource_refresh.go b/terraform/node_resource_refresh.go deleted file mode 100644 index 4d1ff74ec..000000000 --- a/terraform/node_resource_refresh.go +++ /dev/null @@ -1,381 +0,0 @@ -package terraform - -import ( - "fmt" - "log" - - "github.com/hashicorp/terraform/plans" - "github.com/hashicorp/terraform/providers" - - "github.com/hashicorp/terraform/states" - - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/dag" - "github.com/hashicorp/terraform/tfdiags" -) - -// nodeExpandRefreshableResource handles the first layer of resource -// expansion durin refresh. We need this extra layer so DynamicExpand is called -// twice for the resource, the first to expand the Resource for each module -// instance, and the second to expand each ResourceInstance for the expanded -// Resources. -type nodeExpandRefreshableManagedResource struct { - *NodeAbstractResource - - // We attach dependencies to the Resource during refresh, since the - // instances are instantiated during DynamicExpand. - Dependencies []addrs.ConfigResource -} - -var ( - _ GraphNodeDynamicExpandable = (*nodeExpandRefreshableManagedResource)(nil) - _ GraphNodeReferenceable = (*nodeExpandRefreshableManagedResource)(nil) - _ GraphNodeReferencer = (*nodeExpandRefreshableManagedResource)(nil) - _ GraphNodeConfigResource = (*nodeExpandRefreshableManagedResource)(nil) - _ GraphNodeAttachResourceConfig = (*nodeExpandRefreshableManagedResource)(nil) - _ GraphNodeAttachDependencies = (*nodeExpandRefreshableManagedResource)(nil) -) - -func (n *nodeExpandRefreshableManagedResource) Name() string { - return n.NodeAbstractResource.Name() + " (expand)" -} - -// GraphNodeAttachDependencies -func (n *nodeExpandRefreshableManagedResource) AttachDependencies(deps []addrs.ConfigResource) { - n.Dependencies = deps -} - -func (n *nodeExpandRefreshableManagedResource) References() []*addrs.Reference { - return (&NodeRefreshableManagedResource{NodeAbstractResource: n.NodeAbstractResource}).References() -} - -func (n *nodeExpandRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph, error) { - var g Graph - - expander := ctx.InstanceExpander() - for _, module := range expander.ExpandModule(n.Addr.Module) { - g.Add(&NodeRefreshableManagedResource{ - NodeAbstractResource: n.NodeAbstractResource, - Addr: n.Addr.Resource.Absolute(module), - Dependencies: n.Dependencies, - }) - } - - return &g, nil -} - -// NodeRefreshableManagedResource represents a resource that is expandable into -// NodeRefreshableManagedResourceInstance. Resource count orphans are also added. -type NodeRefreshableManagedResource struct { - *NodeAbstractResource - - Addr addrs.AbsResource - - // We attach dependencies to the Resource during refresh, since the - // instances are instantiated during DynamicExpand. - Dependencies []addrs.ConfigResource -} - -var ( - _ GraphNodeModuleInstance = (*NodeRefreshableManagedResource)(nil) - _ GraphNodeDynamicExpandable = (*NodeRefreshableManagedResource)(nil) - _ GraphNodeReferenceable = (*NodeRefreshableManagedResource)(nil) - _ GraphNodeReferencer = (*NodeRefreshableManagedResource)(nil) - _ GraphNodeConfigResource = (*NodeRefreshableManagedResource)(nil) - _ GraphNodeAttachResourceConfig = (*NodeRefreshableManagedResource)(nil) -) - -func (n *NodeRefreshableManagedResource) Path() addrs.ModuleInstance { - return n.Addr.Module -} - -// GraphNodeDynamicExpandable -func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph, error) { - var diags tfdiags.Diagnostics - - expander := ctx.InstanceExpander() - // Inform our instance expander about our expansion results, and then use - // it to calculate the instance addresses we'll expand for. - switch { - case n.Config.Count != nil: - count, countDiags := evaluateCountExpression(n.Config.Count, ctx) - diags = diags.Append(countDiags) - if countDiags.HasErrors() { - return nil, diags.Err() - } - - expander.SetResourceCount(n.Addr.Module, n.Addr.Resource, count) - - case n.Config.ForEach != nil: - forEachMap, forEachDiags := evaluateForEachExpression(n.Config.ForEach, ctx) - if forEachDiags.HasErrors() { - return nil, diags.Err() - } - - expander.SetResourceForEach(n.Addr.Module, n.Addr.Resource, forEachMap) - - default: - expander.SetResourceSingle(n.Addr.Module, n.Addr.Resource) - } - - // Next we need to potentially rename an instance address in the state - // if we're transitioning whether "count" is set at all. - fixResourceCountSetTransition(ctx, n.Addr.Config(), n.Config.Count != nil) - instanceAddrs := expander.ExpandResource(n.Addr) - - // Our graph transformers require access to the full state, so we'll - // temporarily lock it while we work on this. - state := ctx.State().Lock() - defer ctx.State().Unlock() - - // The concrete resource factory we'll use - concreteResource := func(a *NodeAbstractResourceInstance) dag.Vertex { - // Add the config and state since we don't do that via transforms - a.Config = n.Config - a.ResolvedProvider = n.ResolvedProvider - a.Dependencies = n.Dependencies - a.ProviderMetas = n.ProviderMetas - - return &NodeRefreshableManagedResourceInstance{ - NodeAbstractResourceInstance: a, - } - } - - // Start creating the steps - steps := []GraphTransformer{ - // Expand the count. - &ResourceCountTransformer{ - Concrete: concreteResource, - Schema: n.Schema, - Addr: n.Addr.Config(), - InstanceAddrs: instanceAddrs, - }, - - // Add the count orphans to make sure these resources are accounted for - // during a scale in. - &OrphanResourceInstanceCountTransformer{ - Concrete: concreteResource, - Addr: n.Addr, - InstanceAddrs: instanceAddrs, - State: state, - }, - - // Attach the state - &AttachStateTransformer{State: state}, - - // Targeting - &TargetsTransformer{Targets: n.Targets}, - - // Connect references so ordering is correct - &ReferenceTransformer{}, - - // Make sure there is a single root - &RootTransformer{}, - } - - // Build the graph - b := &BasicGraphBuilder{ - Steps: steps, - Validate: true, - Name: "NodeRefreshableManagedResource", - } - - graph, diags := b.Build(nil) - return graph, diags.ErrWithWarnings() -} - -// NodeRefreshableManagedResourceInstance represents a resource that is "applyable": -// it is ready to be applied and is represented by a diff. -type NodeRefreshableManagedResourceInstance struct { - *NodeAbstractResourceInstance -} - -var ( - _ GraphNodeModuleInstance = (*NodeRefreshableManagedResourceInstance)(nil) - _ GraphNodeReferenceable = (*NodeRefreshableManagedResourceInstance)(nil) - _ GraphNodeReferencer = (*NodeRefreshableManagedResourceInstance)(nil) - _ GraphNodeDestroyer = (*NodeRefreshableManagedResourceInstance)(nil) - _ GraphNodeConfigResource = (*NodeRefreshableManagedResourceInstance)(nil) - _ GraphNodeResourceInstance = (*NodeRefreshableManagedResourceInstance)(nil) - _ GraphNodeAttachResourceConfig = (*NodeRefreshableManagedResourceInstance)(nil) - _ GraphNodeAttachResourceState = (*NodeRefreshableManagedResourceInstance)(nil) - _ GraphNodeExecutable = (*NodeRefreshableManagedResourceInstance)(nil) -) - -// GraphNodeDestroyer -func (n *NodeRefreshableManagedResourceInstance) DestroyAddr() *addrs.AbsResourceInstance { - addr := n.ResourceInstanceAddr() - return &addr -} - -// GraphNodeEvalable -func (n *NodeRefreshableManagedResourceInstance) Execute(ctx EvalContext, op walkOperation) error { - addr := n.ResourceInstanceAddr() - - // Eval info is different depending on what kind of resource this is - switch addr.Resource.Resource.Mode { - case addrs.ManagedResourceMode: - if n.instanceState == nil { - log.Printf("[TRACE] NodeRefreshableManagedResourceInstance: %s has no existing state to refresh", addr) - _, err := n.evalTreeManagedResourceNoState().Eval(ctx) - return err - } - log.Printf("[TRACE] NodeRefreshableManagedResourceInstance: %s will be refreshed", addr) - _, err := n.evalTreeManagedResource().Eval(ctx) - return err - - case addrs.DataResourceMode: - // Get the data source node. If we don't have a configuration - // then it is an orphan so we destroy it (remove it from the state). - var dn GraphNodeExecutable - if n.Config != nil { - dn = &NodeRefreshableDataResourceInstance{ - NodeAbstractResourceInstance: n.NodeAbstractResourceInstance, - } - } else { - dn = &NodeDestroyableDataResourceInstance{ - NodeAbstractResourceInstance: n.NodeAbstractResourceInstance, - } - } - - return dn.Execute(ctx, op) - default: - panic(fmt.Errorf("unsupported resource mode %s", addr.Resource.Resource.Mode)) - } -} - -func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalNode { - addr := n.ResourceInstanceAddr() - - // Declare a bunch of variables that are used for state during - // evaluation. Most of this are written to by-address below. - var provider providers.Interface - var providerSchema *ProviderSchema - var state *states.ResourceInstanceObject - - // This happened during initial development. All known cases were - // fixed and tested but as a sanity check let's assert here. - if n.instanceState == nil { - err := fmt.Errorf( - "No resource state attached for addr: %s\n\n"+ - "This is a bug. Please report this to Terraform with your configuration\n"+ - "and state attached. Please be careful to scrub any sensitive information.", - addr) - return &EvalReturnError{Error: &err} - } - - return &EvalSequence{ - Nodes: []EvalNode{ - &EvalGetProvider{ - Addr: n.ResolvedProvider, - Output: &provider, - Schema: &providerSchema, - }, - - &EvalReadState{ - Addr: addr.Resource, - Provider: &provider, - ProviderSchema: &providerSchema, - - Output: &state, - }, - - &EvalRefreshDependencies{ - State: &state, - Dependencies: &n.Dependencies, - }, - - &EvalRefresh{ - Addr: addr.Resource, - ProviderAddr: n.ResolvedProvider, - Provider: &provider, - ProviderMetas: n.ProviderMetas, - ProviderSchema: &providerSchema, - State: &state, - Output: &state, - }, - - &EvalWriteState{ - Addr: addr.Resource, - ProviderAddr: n.ResolvedProvider, - ProviderSchema: &providerSchema, - State: &state, - Dependencies: &n.Dependencies, - }, - }, - } -} - -// evalTreeManagedResourceNoState produces an EvalSequence for refresh resource -// nodes that don't have state attached. An example of where this functionality -// is useful is when a resource that already exists in state is being scaled -// out, ie: has its resource count increased. In this case, the scaled out node -// needs to be available to other nodes (namely data sources) that may depend -// on it for proper interpolation, or confusing "index out of range" errors can -// occur. -// -// The steps in this sequence are very similar to the steps carried out in -// plan, but nothing is done with the diff after it is created - it is dropped, -// and its changes are not counted in the UI. -func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResourceNoState() EvalNode { - addr := n.ResourceInstanceAddr() - - // Declare a bunch of variables that are used for state during - // evaluation. Most of this are written to by-address below. - var provider providers.Interface - var providerSchema *ProviderSchema - var change *plans.ResourceInstanceChange - var state *states.ResourceInstanceObject - - return &EvalSequence{ - Nodes: []EvalNode{ - &EvalGetProvider{ - Addr: n.ResolvedProvider, - Output: &provider, - Schema: &providerSchema, - }, - - &EvalReadState{ - Addr: addr.Resource, - Provider: &provider, - ProviderSchema: &providerSchema, - - Output: &state, - }, - - &EvalDiff{ - Addr: addr.Resource, - Config: n.Config, - Provider: &provider, - ProviderAddr: n.ResolvedProvider, - ProviderSchema: &providerSchema, - State: &state, - OutputChange: &change, - OutputState: &state, - Stub: true, - }, - - &EvalWriteState{ - Addr: addr.Resource, - ProviderAddr: n.ResolvedProvider, - ProviderSchema: &providerSchema, - State: &state, - Dependencies: &n.Dependencies, - }, - - // We must also save the planned change, so that expressions in - // other nodes, such as provider configurations and data resources, - // can work with the planned new value. - // - // This depends on the fact that Context.Refresh creates a - // temporary new empty changeset for the duration of its graph - // walk, and so this recorded change will be discarded immediately - // after the refresh walk completes. - &EvalWriteDiff{ - Addr: addr.Resource, - Change: &change, - ProviderSchema: &providerSchema, - }, - }, - } -} diff --git a/terraform/node_resource_refresh_test.go b/terraform/node_resource_refresh_test.go deleted file mode 100644 index b318757e1..000000000 --- a/terraform/node_resource_refresh_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package terraform - -import ( - "testing" - - "github.com/zclconf/go-cty/cty" - - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/instances" -) - -func TestNodeRefreshableManagedResourceDynamicExpand_scaleOut(t *testing.T) { - m := testModule(t, "refresh-resource-scale-inout") - - state := MustShimLegacyState(&State{ - Modules: []*ModuleState{ - &ModuleState{ - Path: rootModulePath, - Resources: map[string]*ResourceState{ - "aws_instance.foo.0": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "foo", - }, - }, - }, - "aws_instance.foo.1": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "bar", - }, - }, - }, - }, - }, - }, - }).SyncWrapper() - - cfgAddr := addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo") - n := &NodeRefreshableManagedResource{ - NodeAbstractResource: &NodeAbstractResource{ - Addr: cfgAddr, - Config: m.Module.ManagedResources["aws_instance.foo"], - }, - Addr: cfgAddr.Absolute(addrs.RootModuleInstance), - } - - g, err := n.DynamicExpand(&MockEvalContext{ - PathPath: addrs.RootModuleInstance, - StateState: state, - InstanceExpanderExpander: instances.NewExpander(), - - // DynamicExpand will call EvaluateExpr to evaluate the "count" - // expression, which is just a literal number 3 in the fixture config - // and so we'll just hard-code this here too. - EvaluateExprResult: cty.NumberIntVal(3), - }) - if err != nil { - t.Fatalf("error attempting DynamicExpand: %s", err) - } - - actual := g.StringWithNodeTypes() - expected := `aws_instance.foo[0] - *terraform.NodeRefreshableManagedResourceInstance -aws_instance.foo[1] - *terraform.NodeRefreshableManagedResourceInstance -aws_instance.foo[2] - *terraform.NodeRefreshableManagedResourceInstance -root - terraform.graphNodeRoot - aws_instance.foo[0] - *terraform.NodeRefreshableManagedResourceInstance - aws_instance.foo[1] - *terraform.NodeRefreshableManagedResourceInstance - aws_instance.foo[2] - *terraform.NodeRefreshableManagedResourceInstance -` - if expected != actual { - t.Fatalf("Expected:\n%s\nGot:\n%s", expected, actual) - } -} - -func TestNodeRefreshableManagedResourceDynamicExpand_scaleIn(t *testing.T) { - m := testModule(t, "refresh-resource-scale-inout") - - state := MustShimLegacyState(&State{ - Modules: []*ModuleState{ - &ModuleState{ - Path: rootModulePath, - Resources: map[string]*ResourceState{ - "aws_instance.foo.0": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "foo", - }, - }, - }, - "aws_instance.foo.1": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "bar", - }, - }, - }, - "aws_instance.foo.2": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "baz", - }, - }, - }, - "aws_instance.foo.3": &ResourceState{ - Type: "aws_instance", - Deposed: []*InstanceState{ - &InstanceState{ - ID: "qux", - }, - }, - }, - }, - }, - }, - }).SyncWrapper() - - cfgAddr := addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo") - n := &NodeRefreshableManagedResource{ - NodeAbstractResource: &NodeAbstractResource{ - Addr: cfgAddr, - Config: m.Module.ManagedResources["aws_instance.foo"], - }, - Addr: cfgAddr.Absolute(addrs.RootModuleInstance), - } - - g, err := n.DynamicExpand(&MockEvalContext{ - PathPath: addrs.RootModuleInstance, - StateState: state, - InstanceExpanderExpander: instances.NewExpander(), - - // DynamicExpand will call EvaluateExpr to evaluate the "count" - // expression, which is just a literal number 3 in the fixture config - // and so we'll just hard-code this here too. - EvaluateExprResult: cty.NumberIntVal(3), - }) - if err != nil { - t.Fatalf("error attempting DynamicExpand: %s", err) - } - actual := g.StringWithNodeTypes() - expected := `aws_instance.foo[0] - *terraform.NodeRefreshableManagedResourceInstance -aws_instance.foo[1] - *terraform.NodeRefreshableManagedResourceInstance -aws_instance.foo[2] - *terraform.NodeRefreshableManagedResourceInstance -aws_instance.foo[3] - *terraform.NodeRefreshableManagedResourceInstance -root - terraform.graphNodeRoot - aws_instance.foo[0] - *terraform.NodeRefreshableManagedResourceInstance - aws_instance.foo[1] - *terraform.NodeRefreshableManagedResourceInstance - aws_instance.foo[2] - *terraform.NodeRefreshableManagedResourceInstance - aws_instance.foo[3] - *terraform.NodeRefreshableManagedResourceInstance -` - if expected != actual { - t.Fatalf("Expected:\n%s\nGot:\n%s", expected, actual) - } -} diff --git a/terraform/walkoperation_string.go b/terraform/walkoperation_string.go index 0666aa5f3..799d4dae2 100644 --- a/terraform/walkoperation_string.go +++ b/terraform/walkoperation_string.go @@ -12,16 +12,15 @@ func _() { _ = x[walkApply-1] _ = x[walkPlan-2] _ = x[walkPlanDestroy-3] - _ = x[walkRefresh-4] - _ = x[walkValidate-5] - _ = x[walkDestroy-6] - _ = x[walkImport-7] - _ = x[walkEval-8] + _ = x[walkValidate-4] + _ = x[walkDestroy-5] + _ = x[walkImport-6] + _ = x[walkEval-7] } -const _walkOperation_name = "walkInvalidwalkApplywalkPlanwalkPlanDestroywalkRefreshwalkValidatewalkDestroywalkImportwalkEval" +const _walkOperation_name = "walkInvalidwalkApplywalkPlanwalkPlanDestroywalkValidatewalkDestroywalkImportwalkEval" -var _walkOperation_index = [...]uint8{0, 11, 20, 28, 43, 54, 66, 77, 87, 95} +var _walkOperation_index = [...]uint8{0, 11, 20, 28, 43, 55, 66, 76, 84} func (i walkOperation) String() string { if i >= walkOperation(len(_walkOperation_index)-1) {