package terraform import ( "fmt" "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/addrs" "github.com/zclconf/go-cty/cty" ) // NodePlannableResourceInstance represents a _single_ resource // instance that is plannable. This means this represents a single // count index, for example. type NodePlannableResourceInstance struct { *NodeAbstractResourceInstance ForceCreateBeforeDestroy bool } var ( _ GraphNodeSubPath = (*NodePlannableResourceInstance)(nil) _ GraphNodeReferenceable = (*NodePlannableResourceInstance)(nil) _ GraphNodeReferencer = (*NodePlannableResourceInstance)(nil) _ GraphNodeResource = (*NodePlannableResourceInstance)(nil) _ GraphNodeResourceInstance = (*NodePlannableResourceInstance)(nil) _ GraphNodeAttachResourceConfig = (*NodePlannableResourceInstance)(nil) _ GraphNodeAttachResourceState = (*NodePlannableResourceInstance)(nil) _ GraphNodeEvalable = (*NodePlannableResourceInstance)(nil) ) // GraphNodeEvalable func (n *NodePlannableResourceInstance) EvalTree() EvalNode { addr := n.ResourceInstanceAddr() // State still uses legacy-style internal ids, so we need to shim to get // a suitable key to use. stateId := NewLegacyResourceInstanceAddress(addr).stateId() // Determine the dependencies for the state. stateDeps := n.StateReferences() // Eval info is different depending on what kind of resource this is switch addr.Resource.Resource.Mode { case addrs.ManagedResourceMode: return n.evalTreeManagedResource(addr, stateId, stateDeps) case addrs.DataResourceMode: return n.evalTreeDataResource(addr, stateId, stateDeps) default: panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode)) } } func (n *NodePlannableResourceInstance) evalTreeDataResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []addrs.Referenceable) EvalNode { config := n.Config var provider providers.Interface var providerSchema *ProviderSchema var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject var configVal cty.Value return &EvalSequence{ Nodes: []EvalNode{ &EvalGetProvider{ Addr: n.ResolvedProvider, Output: &provider, Schema: &providerSchema, }, &EvalReadState{ Addr: addr.Resource, Provider: &provider, ProviderSchema: &providerSchema, Output: &state, }, &EvalValidateSelfRef{ Addr: addr.Resource, Config: config.Config, ProviderSchema: &providerSchema, }, &EvalReadDataDiff{ Addr: addr.Resource, Config: n.Config, ProviderAddr: n.ResolvedProvider, ProviderSchema: &providerSchema, Output: &change, OutputValue: &configVal, OutputState: &state, }, &EvalWriteState{ Addr: addr.Resource, ProviderAddr: n.ResolvedProvider, ProviderSchema: &providerSchema, State: &state, }, &EvalWriteDiff{ Addr: addr.Resource, ProviderSchema: &providerSchema, Change: &change, }, }, } } func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []addrs.Referenceable) EvalNode { config := n.Config 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, }, &EvalValidateSelfRef{ Addr: addr.Resource, Config: config.Config, ProviderSchema: &providerSchema, }, &EvalDiff{ Addr: addr.Resource, Config: n.Config, CreateBeforeDestroy: n.ForceCreateBeforeDestroy, Provider: &provider, ProviderAddr: n.ResolvedProvider, ProviderSchema: &providerSchema, State: &state, OutputChange: &change, OutputState: &state, }, &EvalCheckPreventDestroy{ Addr: addr.Resource, Config: n.Config, Change: &change, }, &EvalWriteState{ Addr: addr.Resource, ProviderAddr: n.ResolvedProvider, State: &state, ProviderSchema: &providerSchema, }, &EvalWriteDiff{ Addr: addr.Resource, ProviderSchema: &providerSchema, Change: &change, }, }, } }