terraform: minor cleanup from EvalTree() refactor (#26429)
* Split node_resource_abstract.go into two files, putting NodeAbstractResourceInstance methods in their own file - it was getting large enough to be tricky for (my) human eyeballs. * un-exported the functions that were created as part of the EvalTree() refactor; they did not need to be public.
This commit is contained in:
parent
d76cfc8c0c
commit
90588c036b
|
@ -4,13 +4,11 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/configs"
|
||||
"github.com/hashicorp/terraform/configs/configschema"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
"github.com/hashicorp/terraform/lang"
|
||||
"github.com/hashicorp/terraform/plans"
|
||||
"github.com/hashicorp/terraform/states"
|
||||
"github.com/hashicorp/terraform/tfdiags"
|
||||
)
|
||||
|
@ -95,25 +93,6 @@ func NewNodeAbstractResource(addr addrs.ConfigResource) *NodeAbstractResource {
|
|||
}
|
||||
}
|
||||
|
||||
// NodeAbstractResourceInstance represents a resource instance with no
|
||||
// associated operations. It embeds NodeAbstractResource but additionally
|
||||
// contains an instance key, used to identify one of potentially many
|
||||
// instances that were created from a resource in configuration, e.g. using
|
||||
// the "count" or "for_each" arguments.
|
||||
type NodeAbstractResourceInstance struct {
|
||||
NodeAbstractResource
|
||||
Addr addrs.AbsResourceInstance
|
||||
|
||||
// These are set via the AttachState method.
|
||||
instanceState *states.ResourceInstance
|
||||
// storedProviderConfig is the provider address retrieved from the
|
||||
// state, but since it is only stored in the whole Resource rather than the
|
||||
// ResourceInstance, we extract it out here.
|
||||
storedProviderConfig addrs.AbsProviderConfig
|
||||
|
||||
Dependencies []addrs.ConfigResource
|
||||
}
|
||||
|
||||
var (
|
||||
_ GraphNodeModuleInstance = (*NodeAbstractResourceInstance)(nil)
|
||||
_ GraphNodeReferenceable = (*NodeAbstractResourceInstance)(nil)
|
||||
|
@ -131,33 +110,10 @@ var (
|
|||
_ dag.GraphNodeDotter = (*NodeAbstractResourceInstance)(nil)
|
||||
)
|
||||
|
||||
// NewNodeAbstractResourceInstance creates an abstract resource instance graph
|
||||
// node for the given absolute resource instance address.
|
||||
func NewNodeAbstractResourceInstance(addr addrs.AbsResourceInstance) *NodeAbstractResourceInstance {
|
||||
// Due to the fact that we embed NodeAbstractResource, the given address
|
||||
// actually ends up split between the resource address in the embedded
|
||||
// object and the InstanceKey field in our own struct. The
|
||||
// ResourceInstanceAddr method will stick these back together again on
|
||||
// request.
|
||||
r := NewNodeAbstractResource(addr.ContainingResource().Config())
|
||||
return &NodeAbstractResourceInstance{
|
||||
NodeAbstractResource: *r,
|
||||
Addr: addr,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResource) Name() string {
|
||||
return n.ResourceAddr().String()
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResourceInstance) Name() string {
|
||||
return n.ResourceInstanceAddr().String()
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResourceInstance) Path() addrs.ModuleInstance {
|
||||
return n.Addr.Module
|
||||
}
|
||||
|
||||
// GraphNodeModulePath
|
||||
func (n *NodeAbstractResource) ModulePath() addrs.Module {
|
||||
return n.Addr.Module
|
||||
|
@ -168,19 +124,6 @@ func (n *NodeAbstractResource) ReferenceableAddrs() []addrs.Referenceable {
|
|||
return []addrs.Referenceable{n.Addr.Resource}
|
||||
}
|
||||
|
||||
// GraphNodeReferenceable
|
||||
func (n *NodeAbstractResourceInstance) ReferenceableAddrs() []addrs.Referenceable {
|
||||
addr := n.ResourceInstanceAddr()
|
||||
return []addrs.Referenceable{
|
||||
addr.Resource,
|
||||
|
||||
// A resource instance can also be referenced by the address of its
|
||||
// containing resource, so that e.g. a reference to aws_instance.foo
|
||||
// would match both aws_instance.foo[0] and aws_instance.foo[1].
|
||||
addr.ContainingResource().Resource,
|
||||
}
|
||||
}
|
||||
|
||||
// GraphNodeReferencer
|
||||
func (n *NodeAbstractResource) References() []*addrs.Reference {
|
||||
// If we have a config then we prefer to use that.
|
||||
|
@ -256,52 +199,6 @@ func (n *NodeAbstractResource) DependsOn() []*addrs.Reference {
|
|||
return result
|
||||
}
|
||||
|
||||
// GraphNodeReferencer
|
||||
func (n *NodeAbstractResourceInstance) References() []*addrs.Reference {
|
||||
// If we have a configuration attached then we'll delegate to our
|
||||
// embedded abstract resource, which knows how to extract dependencies
|
||||
// from configuration. If there is no config, then the dependencies will
|
||||
// be connected during destroy from those stored in the state.
|
||||
if n.Config != nil {
|
||||
if n.Schema == nil {
|
||||
// We'll produce a log message about this out here so that
|
||||
// we can include the full instance address, since the equivalent
|
||||
// message in NodeAbstractResource.References cannot see it.
|
||||
log.Printf("[WARN] no schema is attached to %s, so config references cannot be detected", n.Name())
|
||||
return nil
|
||||
}
|
||||
return n.NodeAbstractResource.References()
|
||||
}
|
||||
|
||||
// If we have neither config nor state then we have no references.
|
||||
return nil
|
||||
}
|
||||
|
||||
// converts an instance address to the legacy dotted notation
|
||||
func dottedInstanceAddr(tr addrs.ResourceInstance) string {
|
||||
// The legacy state format uses dot-separated instance keys,
|
||||
// rather than bracketed as in our modern syntax.
|
||||
var suffix string
|
||||
switch tk := tr.Key.(type) {
|
||||
case addrs.IntKey:
|
||||
suffix = fmt.Sprintf(".%d", int(tk))
|
||||
case addrs.StringKey:
|
||||
suffix = fmt.Sprintf(".%s", string(tk))
|
||||
}
|
||||
return tr.Resource.String() + suffix
|
||||
}
|
||||
|
||||
// StateDependencies returns the dependencies saved in the state.
|
||||
func (n *NodeAbstractResourceInstance) StateDependencies() []addrs.ConfigResource {
|
||||
if s := n.instanceState; s != nil {
|
||||
if s.Current != nil {
|
||||
return s.Current.Dependencies
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResource) SetProvider(p addrs.AbsProviderConfig) {
|
||||
n.ResolvedProvider = p
|
||||
}
|
||||
|
@ -332,40 +229,6 @@ func (n *NodeAbstractResource) Provider() addrs.Provider {
|
|||
return addrs.ImpliedProviderForUnqualifiedType(n.Addr.Resource.ImpliedProvider())
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResourceInstance) ProvidedBy() (addrs.ProviderConfig, bool) {
|
||||
// If we have a config we prefer that above all else
|
||||
if n.Config != nil {
|
||||
relAddr := n.Config.ProviderConfigAddr()
|
||||
return addrs.LocalProviderConfig{
|
||||
LocalName: relAddr.LocalName,
|
||||
Alias: relAddr.Alias,
|
||||
}, false
|
||||
}
|
||||
|
||||
// See if we have a valid provider config from the state.
|
||||
if n.storedProviderConfig.Provider.Type != "" {
|
||||
// An address from the state must match exactly, since we must ensure
|
||||
// we refresh/destroy a resource with the same provider configuration
|
||||
// that created it.
|
||||
return n.storedProviderConfig, true
|
||||
}
|
||||
|
||||
// No provider configuration found; return a default address
|
||||
return addrs.AbsProviderConfig{
|
||||
Provider: n.Provider(),
|
||||
Module: n.ModulePath(),
|
||||
}, false
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResourceInstance) Provider() addrs.Provider {
|
||||
if n.Config != nil {
|
||||
return n.Config.Provider
|
||||
}
|
||||
return addrs.ImpliedProviderForUnqualifiedType(n.Addr.Resource.ContainingResource().ImpliedProvider())
|
||||
}
|
||||
|
||||
// GraphNodeProvisionerConsumer
|
||||
func (n *NodeAbstractResource) ProvisionedBy() []string {
|
||||
// If we have no configuration, then we have no provisioners
|
||||
|
@ -396,11 +259,6 @@ func (n *NodeAbstractResource) ResourceAddr() addrs.ConfigResource {
|
|||
return n.Addr
|
||||
}
|
||||
|
||||
// GraphNodeResourceInstance
|
||||
func (n *NodeAbstractResourceInstance) ResourceInstanceAddr() addrs.AbsResourceInstance {
|
||||
return n.Addr
|
||||
}
|
||||
|
||||
// GraphNodeTargetable
|
||||
func (n *NodeAbstractResource) SetTargets(targets []addrs.Targetable) {
|
||||
n.Targets = targets
|
||||
|
@ -412,16 +270,6 @@ func (n *NodeAbstractResource) AttachResourceDependencies(deps []addrs.ConfigRes
|
|||
n.forceDependsOn = force
|
||||
}
|
||||
|
||||
// GraphNodeAttachResourceState
|
||||
func (n *NodeAbstractResourceInstance) AttachResourceState(s *states.Resource) {
|
||||
if s == nil {
|
||||
log.Printf("[WARN] attaching nil state to %s", n.Addr)
|
||||
return
|
||||
}
|
||||
n.instanceState = s.Instance(n.Addr.Resource.Key)
|
||||
n.storedProviderConfig = s.ProviderConfig
|
||||
}
|
||||
|
||||
// GraphNodeAttachResourceConfig
|
||||
func (n *NodeAbstractResource) AttachResourceConfig(c *configs.Resource) {
|
||||
n.Config = c
|
||||
|
@ -449,7 +297,7 @@ func (n *NodeAbstractResource) DotNode(name string, opts *dag.DotOpts) *dag.DotN
|
|||
}
|
||||
}
|
||||
|
||||
// WriteResourceState ensures that a suitable resource-level state record is
|
||||
// writeResourceState ensures that a suitable resource-level state record is
|
||||
// present in the state, if that's required for the "each mode" of that
|
||||
// resource.
|
||||
//
|
||||
|
@ -457,7 +305,7 @@ func (n *NodeAbstractResource) DotNode(name string, opts *dag.DotOpts) *dag.DotN
|
|||
// eval is the only change we get to set the resource "each mode" to list
|
||||
// in that case, allowing expression evaluation to see it as a zero-element list
|
||||
// rather than as not set at all.
|
||||
func (n *NodeAbstractResource) WriteResourceState(ctx EvalContext, addr addrs.AbsResource) error {
|
||||
func (n *NodeAbstractResource) writeResourceState(ctx EvalContext, addr addrs.AbsResource) error {
|
||||
var diags tfdiags.Diagnostics
|
||||
state := ctx.State()
|
||||
|
||||
|
@ -542,59 +390,6 @@ func (n *NodeAbstractResource) ReadResourceInstanceState(ctx EvalContext, addr a
|
|||
return obj, nil
|
||||
}
|
||||
|
||||
// ReadDiff returns the planned change for a particular resource instance
|
||||
// object.
|
||||
func (n *NodeAbstractResourceInstance) ReadDiff(ctx EvalContext, providerSchema *ProviderSchema) (*plans.ResourceInstanceChange, error) {
|
||||
changes := ctx.Changes()
|
||||
addr := n.ResourceInstanceAddr()
|
||||
|
||||
schema, _ := providerSchema.SchemaForResourceAddr(addr.Resource.Resource)
|
||||
if schema == nil {
|
||||
// Should be caught during validation, so we don't bother with a pretty error here
|
||||
return nil, fmt.Errorf("provider does not support resource type %q", addr.Resource.Resource.Type)
|
||||
}
|
||||
|
||||
gen := states.CurrentGen
|
||||
csrc := changes.GetResourceInstanceChange(addr, gen)
|
||||
if csrc == nil {
|
||||
log.Printf("[TRACE] EvalReadDiff: No planned change recorded for %s", n.Addr)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
change, err := csrc.Decode(schema.ImpliedType())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode planned changes for %s: %s", n.Addr, err)
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] EvalReadDiff: Read %s change from plan for %s", change.Action, n.Addr)
|
||||
|
||||
return change, nil
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResourceInstance) checkPreventDestroy(change *plans.ResourceInstanceChange) error {
|
||||
if change == nil || n.Config == nil || n.Config.Managed == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
preventDestroy := n.Config.Managed.PreventDestroy
|
||||
|
||||
if (change.Action == plans.Delete || change.Action.IsReplace()) && preventDestroy {
|
||||
var diags tfdiags.Diagnostics
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Instance cannot be destroyed",
|
||||
Detail: fmt.Sprintf(
|
||||
"Resource %s has lifecycle.prevent_destroy set, but the plan calls for this resource to be destroyed. To avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan using the -target flag.",
|
||||
n.Addr.String(),
|
||||
),
|
||||
Subject: &n.Config.DeclRange,
|
||||
})
|
||||
return diags.Err()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// graphNodesAreResourceInstancesInDifferentInstancesOfSameModule is an
|
||||
// annoyingly-task-specific helper function that returns true if and only if
|
||||
// the following conditions hold:
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/plans"
|
||||
"github.com/hashicorp/terraform/states"
|
||||
"github.com/hashicorp/terraform/tfdiags"
|
||||
)
|
||||
|
||||
// NodeAbstractResourceInstance represents a resource instance with no
|
||||
// associated operations. It embeds NodeAbstractResource but additionally
|
||||
// contains an instance key, used to identify one of potentially many
|
||||
// instances that were created from a resource in configuration, e.g. using
|
||||
// the "count" or "for_each" arguments.
|
||||
type NodeAbstractResourceInstance struct {
|
||||
NodeAbstractResource
|
||||
Addr addrs.AbsResourceInstance
|
||||
|
||||
// These are set via the AttachState method.
|
||||
instanceState *states.ResourceInstance
|
||||
// storedProviderConfig is the provider address retrieved from the
|
||||
// state, but since it is only stored in the whole Resource rather than the
|
||||
// ResourceInstance, we extract it out here.
|
||||
storedProviderConfig addrs.AbsProviderConfig
|
||||
|
||||
Dependencies []addrs.ConfigResource
|
||||
}
|
||||
|
||||
// NewNodeAbstractResourceInstance creates an abstract resource instance graph
|
||||
// node for the given absolute resource instance address.
|
||||
func NewNodeAbstractResourceInstance(addr addrs.AbsResourceInstance) *NodeAbstractResourceInstance {
|
||||
// Due to the fact that we embed NodeAbstractResource, the given address
|
||||
// actually ends up split between the resource address in the embedded
|
||||
// object and the InstanceKey field in our own struct. The
|
||||
// ResourceInstanceAddr method will stick these back together again on
|
||||
// request.
|
||||
r := NewNodeAbstractResource(addr.ContainingResource().Config())
|
||||
return &NodeAbstractResourceInstance{
|
||||
NodeAbstractResource: *r,
|
||||
Addr: addr,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResourceInstance) Name() string {
|
||||
return n.ResourceInstanceAddr().String()
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResourceInstance) Path() addrs.ModuleInstance {
|
||||
return n.Addr.Module
|
||||
}
|
||||
|
||||
// GraphNodeReferenceable
|
||||
func (n *NodeAbstractResourceInstance) ReferenceableAddrs() []addrs.Referenceable {
|
||||
addr := n.ResourceInstanceAddr()
|
||||
return []addrs.Referenceable{
|
||||
addr.Resource,
|
||||
|
||||
// A resource instance can also be referenced by the address of its
|
||||
// containing resource, so that e.g. a reference to aws_instance.foo
|
||||
// would match both aws_instance.foo[0] and aws_instance.foo[1].
|
||||
addr.ContainingResource().Resource,
|
||||
}
|
||||
}
|
||||
|
||||
// GraphNodeReferencer
|
||||
func (n *NodeAbstractResourceInstance) References() []*addrs.Reference {
|
||||
// If we have a configuration attached then we'll delegate to our
|
||||
// embedded abstract resource, which knows how to extract dependencies
|
||||
// from configuration. If there is no config, then the dependencies will
|
||||
// be connected during destroy from those stored in the state.
|
||||
if n.Config != nil {
|
||||
if n.Schema == nil {
|
||||
// We'll produce a log message about this out here so that
|
||||
// we can include the full instance address, since the equivalent
|
||||
// message in NodeAbstractResource.References cannot see it.
|
||||
log.Printf("[WARN] no schema is attached to %s, so config references cannot be detected", n.Name())
|
||||
return nil
|
||||
}
|
||||
return n.NodeAbstractResource.References()
|
||||
}
|
||||
|
||||
// If we have neither config nor state then we have no references.
|
||||
return nil
|
||||
}
|
||||
|
||||
// StateDependencies returns the dependencies saved in the state.
|
||||
func (n *NodeAbstractResourceInstance) StateDependencies() []addrs.ConfigResource {
|
||||
if s := n.instanceState; s != nil {
|
||||
if s.Current != nil {
|
||||
return s.Current.Dependencies
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResourceInstance) ProvidedBy() (addrs.ProviderConfig, bool) {
|
||||
// If we have a config we prefer that above all else
|
||||
if n.Config != nil {
|
||||
relAddr := n.Config.ProviderConfigAddr()
|
||||
return addrs.LocalProviderConfig{
|
||||
LocalName: relAddr.LocalName,
|
||||
Alias: relAddr.Alias,
|
||||
}, false
|
||||
}
|
||||
|
||||
// See if we have a valid provider config from the state.
|
||||
if n.storedProviderConfig.Provider.Type != "" {
|
||||
// An address from the state must match exactly, since we must ensure
|
||||
// we refresh/destroy a resource with the same provider configuration
|
||||
// that created it.
|
||||
return n.storedProviderConfig, true
|
||||
}
|
||||
|
||||
// No provider configuration found; return a default address
|
||||
return addrs.AbsProviderConfig{
|
||||
Provider: n.Provider(),
|
||||
Module: n.ModulePath(),
|
||||
}, false
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResourceInstance) Provider() addrs.Provider {
|
||||
if n.Config != nil {
|
||||
return n.Config.Provider
|
||||
}
|
||||
return addrs.ImpliedProviderForUnqualifiedType(n.Addr.Resource.ContainingResource().ImpliedProvider())
|
||||
}
|
||||
|
||||
// GraphNodeResourceInstance
|
||||
func (n *NodeAbstractResourceInstance) ResourceInstanceAddr() addrs.AbsResourceInstance {
|
||||
return n.Addr
|
||||
}
|
||||
|
||||
// GraphNodeAttachResourceState
|
||||
func (n *NodeAbstractResourceInstance) AttachResourceState(s *states.Resource) {
|
||||
if s == nil {
|
||||
log.Printf("[WARN] attaching nil state to %s", n.Addr)
|
||||
return
|
||||
}
|
||||
n.instanceState = s.Instance(n.Addr.Resource.Key)
|
||||
n.storedProviderConfig = s.ProviderConfig
|
||||
}
|
||||
|
||||
// readDiff returns the planned change for a particular resource instance
|
||||
// object.
|
||||
func (n *NodeAbstractResourceInstance) readDiff(ctx EvalContext, providerSchema *ProviderSchema) (*plans.ResourceInstanceChange, error) {
|
||||
changes := ctx.Changes()
|
||||
addr := n.ResourceInstanceAddr()
|
||||
|
||||
schema, _ := providerSchema.SchemaForResourceAddr(addr.Resource.Resource)
|
||||
if schema == nil {
|
||||
// Should be caught during validation, so we don't bother with a pretty error here
|
||||
return nil, fmt.Errorf("provider does not support resource type %q", addr.Resource.Resource.Type)
|
||||
}
|
||||
|
||||
gen := states.CurrentGen
|
||||
csrc := changes.GetResourceInstanceChange(addr, gen)
|
||||
if csrc == nil {
|
||||
log.Printf("[TRACE] EvalReadDiff: No planned change recorded for %s", n.Addr)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
change, err := csrc.Decode(schema.ImpliedType())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode planned changes for %s: %s", n.Addr, err)
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] EvalReadDiff: Read %s change from plan for %s", change.Action, n.Addr)
|
||||
|
||||
return change, nil
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResourceInstance) checkPreventDestroy(change *plans.ResourceInstanceChange) error {
|
||||
if change == nil || n.Config == nil || n.Config.Managed == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
preventDestroy := n.Config.Managed.PreventDestroy
|
||||
|
||||
if (change.Action == plans.Delete || change.Action.IsReplace()) && preventDestroy {
|
||||
var diags tfdiags.Diagnostics
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Instance cannot be destroyed",
|
||||
Detail: fmt.Sprintf(
|
||||
"Resource %s has lifecycle.prevent_destroy set, but the plan calls for this resource to be destroyed. To avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan using the -target flag.",
|
||||
n.Addr.String(),
|
||||
),
|
||||
Subject: &n.Config.DeclRange,
|
||||
})
|
||||
return diags.Err()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/configs"
|
||||
)
|
||||
|
||||
func TestNodeAbstractResourceInstanceProvider(t *testing.T) {
|
||||
tests := []struct {
|
||||
Addr addrs.AbsResourceInstance
|
||||
Config *configs.Resource
|
||||
Want addrs.Provider
|
||||
}{
|
||||
{
|
||||
Addr: addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "null_resource",
|
||||
Name: "baz",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
Want: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "hashicorp",
|
||||
Type: "null",
|
||||
},
|
||||
},
|
||||
{
|
||||
Addr: addrs.Resource{
|
||||
Mode: addrs.DataResourceMode,
|
||||
Type: "terraform_remote_state",
|
||||
Name: "baz",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
Want: addrs.Provider{
|
||||
// As a special case, the type prefix "terraform_" maps to
|
||||
// the builtin provider, not the default one.
|
||||
Hostname: addrs.BuiltInProviderHost,
|
||||
Namespace: addrs.BuiltInProviderNamespace,
|
||||
Type: "terraform",
|
||||
},
|
||||
},
|
||||
{
|
||||
Addr: addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "null_resource",
|
||||
Name: "baz",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
Config: &configs.Resource{
|
||||
// Just enough configs.Resource for the Provider method. Not
|
||||
// actually valid for general use.
|
||||
Provider: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "awesomecorp",
|
||||
Type: "happycloud",
|
||||
},
|
||||
},
|
||||
// The config overrides the default behavior.
|
||||
Want: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "awesomecorp",
|
||||
Type: "happycloud",
|
||||
},
|
||||
},
|
||||
{
|
||||
Addr: addrs.Resource{
|
||||
Mode: addrs.DataResourceMode,
|
||||
Type: "terraform_remote_state",
|
||||
Name: "baz",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
Config: &configs.Resource{
|
||||
// Just enough configs.Resource for the Provider method. Not
|
||||
// actually valid for general use.
|
||||
Provider: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "awesomecorp",
|
||||
Type: "happycloud",
|
||||
},
|
||||
},
|
||||
// The config overrides the default behavior.
|
||||
Want: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "awesomecorp",
|
||||
Type: "happycloud",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
var name string
|
||||
if test.Config != nil {
|
||||
name = fmt.Sprintf("%s with configured %s", test.Addr, test.Config.Provider)
|
||||
} else {
|
||||
name = fmt.Sprintf("%s with no configuration", test.Addr)
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
node := &NodeAbstractResourceInstance{
|
||||
// Just enough NodeAbstractResourceInstance for the Provider
|
||||
// function. (This would not be valid for some other functions.)
|
||||
Addr: test.Addr,
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
Config: test.Config,
|
||||
},
|
||||
}
|
||||
got := node.Provider()
|
||||
if got != test.Want {
|
||||
t.Errorf("wrong result\naddr: %s\nconfig: %#v\ngot: %s\nwant: %s", test.Addr, test.Config, got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -107,105 +107,3 @@ func TestNodeAbstractResourceProvider(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeAbstractResourceInstanceProvider(t *testing.T) {
|
||||
tests := []struct {
|
||||
Addr addrs.AbsResourceInstance
|
||||
Config *configs.Resource
|
||||
Want addrs.Provider
|
||||
}{
|
||||
{
|
||||
Addr: addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "null_resource",
|
||||
Name: "baz",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
Want: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "hashicorp",
|
||||
Type: "null",
|
||||
},
|
||||
},
|
||||
{
|
||||
Addr: addrs.Resource{
|
||||
Mode: addrs.DataResourceMode,
|
||||
Type: "terraform_remote_state",
|
||||
Name: "baz",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
Want: addrs.Provider{
|
||||
// As a special case, the type prefix "terraform_" maps to
|
||||
// the builtin provider, not the default one.
|
||||
Hostname: addrs.BuiltInProviderHost,
|
||||
Namespace: addrs.BuiltInProviderNamespace,
|
||||
Type: "terraform",
|
||||
},
|
||||
},
|
||||
{
|
||||
Addr: addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "null_resource",
|
||||
Name: "baz",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
Config: &configs.Resource{
|
||||
// Just enough configs.Resource for the Provider method. Not
|
||||
// actually valid for general use.
|
||||
Provider: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "awesomecorp",
|
||||
Type: "happycloud",
|
||||
},
|
||||
},
|
||||
// The config overrides the default behavior.
|
||||
Want: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "awesomecorp",
|
||||
Type: "happycloud",
|
||||
},
|
||||
},
|
||||
{
|
||||
Addr: addrs.Resource{
|
||||
Mode: addrs.DataResourceMode,
|
||||
Type: "terraform_remote_state",
|
||||
Name: "baz",
|
||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||
Config: &configs.Resource{
|
||||
// Just enough configs.Resource for the Provider method. Not
|
||||
// actually valid for general use.
|
||||
Provider: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "awesomecorp",
|
||||
Type: "happycloud",
|
||||
},
|
||||
},
|
||||
// The config overrides the default behavior.
|
||||
Want: addrs.Provider{
|
||||
Hostname: addrs.DefaultRegistryHost,
|
||||
Namespace: "awesomecorp",
|
||||
Type: "happycloud",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
var name string
|
||||
if test.Config != nil {
|
||||
name = fmt.Sprintf("%s with configured %s", test.Addr, test.Config.Provider)
|
||||
} else {
|
||||
name = fmt.Sprintf("%s with no configuration", test.Addr)
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
node := &NodeAbstractResourceInstance{
|
||||
// Just enough NodeAbstractResourceInstance for the Provider
|
||||
// function. (This would not be valid for some other functions.)
|
||||
Addr: test.Addr,
|
||||
NodeAbstractResource: NodeAbstractResource{
|
||||
Config: test.Config,
|
||||
},
|
||||
}
|
||||
got := node.Provider()
|
||||
if got != test.Want {
|
||||
t.Errorf("wrong result\naddr: %s\nconfig: %#v\ngot: %s\nwant: %s", test.Addr, test.Config, got, test.Want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,6 @@ func (n *NodeApplyableResource) Execute(ctx EvalContext, op walkOperation) error
|
|||
return nil
|
||||
}
|
||||
|
||||
err := n.WriteResourceState(ctx, n.Addr)
|
||||
err := n.writeResourceState(ctx, n.Addr)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ func (n *NodeApplyableResourceInstance) dataResourceExecute(ctx EvalContext) err
|
|||
return err
|
||||
}
|
||||
|
||||
change, err := n.ReadDiff(ctx, providerSchema)
|
||||
change, err := n.readDiff(ctx, providerSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
|
|||
}
|
||||
|
||||
// Get the saved diff for apply
|
||||
diffApply, err := n.ReadDiff(ctx, providerSchema)
|
||||
diffApply, err := n.readDiff(ctx, providerSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
|
|||
}
|
||||
|
||||
// Get the saved diff
|
||||
diff, err := n.ReadDiff(ctx, providerSchema)
|
||||
diff, err := n.readDiff(ctx, providerSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation)
|
|||
return err
|
||||
}
|
||||
|
||||
changeApply, err = n.ReadDiff(ctx, providerSchema)
|
||||
changeApply, err = n.readDiff(ctx, providerSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ func (n *NodePlannableResource) Execute(ctx EvalContext, op walkOperation) error
|
|||
return nil
|
||||
}
|
||||
|
||||
err := n.WriteResourceState(ctx, n.Addr)
|
||||
err := n.writeResourceState(ctx, n.Addr)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue