mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Implement a new provider_meta block in the terraform block of modules, allowing provider-keyed metadata to be communicated from HCL to provider binaries. Bundled in this change for minimal protocol version bumping is the addition of markdown support for attribute descriptions and the ability to indicate when an attribute is deprecated, so this information can be shown in the schema dump. Co-authored-by: Paul Tyng <paul@paultyng.net>
203 lines
5.6 KiB
Go
203 lines
5.6 KiB
Go
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()
|
|
|
|
// Eval info is different depending on what kind of resource this is
|
|
switch addr.Resource.Resource.Mode {
|
|
case addrs.ManagedResourceMode:
|
|
return n.evalTreeManagedResource(addr)
|
|
case addrs.DataResourceMode:
|
|
return n.evalTreeDataResource(addr)
|
|
default:
|
|
panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
|
|
}
|
|
}
|
|
|
|
func (n *NodePlannableResourceInstance) evalTreeDataResource(addr addrs.AbsResourceInstance) 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,
|
|
},
|
|
|
|
// If we already have a non-planned state then we already dealt
|
|
// with this during the refresh walk and so we have nothing to do
|
|
// here.
|
|
&EvalIf{
|
|
If: func(ctx EvalContext) (bool, error) {
|
|
depChanges := false
|
|
|
|
// Check and see if any of our dependencies have changes.
|
|
changes := ctx.Changes()
|
|
for _, d := range n.References() {
|
|
ri, ok := d.Subject.(addrs.ResourceInstance)
|
|
if !ok {
|
|
continue
|
|
}
|
|
change := changes.GetResourceInstanceChange(ri.Absolute(ctx.Path()), states.CurrentGen)
|
|
if change != nil && change.Action != plans.NoOp {
|
|
depChanges = true
|
|
break
|
|
}
|
|
}
|
|
|
|
refreshed := state != nil && state.Status != states.ObjectPlanned
|
|
|
|
// If there are no dependency changes, and it's not a forced
|
|
// read because we there was no Refresh, then we don't need
|
|
// to re-read. If any dependencies have changes, it means
|
|
// our config may also have changes and we need to Read the
|
|
// data source again.
|
|
if !depChanges && refreshed {
|
|
return false, EvalEarlyExitError{}
|
|
}
|
|
return true, nil
|
|
},
|
|
Then: EvalNoop{},
|
|
},
|
|
|
|
&EvalValidateSelfRef{
|
|
Addr: addr.Resource,
|
|
Config: config.Config,
|
|
ProviderSchema: &providerSchema,
|
|
},
|
|
|
|
&EvalReadData{
|
|
Addr: addr.Resource,
|
|
Config: n.Config,
|
|
Provider: &provider,
|
|
ProviderAddr: n.ResolvedProvider,
|
|
ProviderMetas: n.ProviderMetas,
|
|
ProviderSchema: &providerSchema,
|
|
ForcePlanRead: true, // _always_ produce a Read change, even if the config seems ready
|
|
OutputChange: &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) 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,
|
|
ProviderMetas: n.ProviderMetas,
|
|
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,
|
|
},
|
|
},
|
|
}
|
|
}
|