Merge pull request #19676 from hashicorp/jbardin/ResourceInstanceObject
Ensure we have providers when scaling in counted data sources
This commit is contained in:
commit
7ce03b5a7e
|
@ -179,7 +179,7 @@ func (s *SyncState) ResourceInstanceObject(addr addrs.AbsResourceInstance, gen G
|
|||
if inst == nil {
|
||||
return nil
|
||||
}
|
||||
return inst.GetGeneration(gen)
|
||||
return inst.GetGeneration(gen).DeepCopy()
|
||||
}
|
||||
|
||||
// SetResourceMeta updates the resource-level metadata for the resource at
|
||||
|
|
|
@ -212,6 +212,10 @@ func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) {
|
|||
absAddr := n.Addr.Absolute(ctx.Path())
|
||||
state := ctx.State()
|
||||
|
||||
if n.ProviderAddr.ProviderConfig.Type == "" {
|
||||
return nil, fmt.Errorf("failed to write state for %s, missing provider type", absAddr)
|
||||
}
|
||||
|
||||
obj := *n.State
|
||||
if obj == nil || obj.Value.IsNull() {
|
||||
// No need to encode anything: we'll just write it directly.
|
||||
|
|
|
@ -1,23 +1,40 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/providers"
|
||||
"github.com/hashicorp/terraform/states"
|
||||
)
|
||||
|
||||
// NodeDestroyableDataResource represents a resource that is "destroyable":
|
||||
// NodeDestroyableDataResourceInstance represents a resource that is "destroyable":
|
||||
// it is ready to be destroyed.
|
||||
type NodeDestroyableDataResource struct {
|
||||
type NodeDestroyableDataResourceInstance struct {
|
||||
*NodeAbstractResourceInstance
|
||||
}
|
||||
|
||||
// GraphNodeEvalable
|
||||
func (n *NodeDestroyableDataResource) EvalTree() EvalNode {
|
||||
func (n *NodeDestroyableDataResourceInstance) EvalTree() EvalNode {
|
||||
addr := n.ResourceInstanceAddr()
|
||||
|
||||
var providerSchema *ProviderSchema
|
||||
// We don't need the provider, but we're calling EvalGetProvider to load the
|
||||
// schema.
|
||||
var provider providers.Interface
|
||||
|
||||
// Just destroy it.
|
||||
var state *states.ResourceInstanceObject
|
||||
return &EvalWriteState{
|
||||
Addr: addr.Resource,
|
||||
State: &state, // state is nil here
|
||||
return &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Addr: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
Schema: &providerSchema,
|
||||
},
|
||||
&EvalWriteState{
|
||||
Addr: addr.Resource,
|
||||
State: &state,
|
||||
ProviderAddr: n.ResolvedProvider,
|
||||
ProviderSchema: &providerSchema,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,10 +56,11 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er
|
|||
// 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 since we don't do that via transforms
|
||||
// Add the config and provider since we don't do that via transforms
|
||||
a.Config = n.Config
|
||||
a.ResolvedProvider = n.ResolvedProvider
|
||||
|
||||
return &NodeDestroyableDataResource{
|
||||
return &NodeDestroyableDataResourceInstance{
|
||||
NodeAbstractResourceInstance: a,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,6 +128,11 @@ func TestNodeRefreshableDataResourceDynamicExpand_scaleIn(t *testing.T) {
|
|||
"foo",
|
||||
),
|
||||
Config: m.Module.DataResources["data.aws_instance.foo"],
|
||||
ResolvedProvider: addrs.AbsProviderConfig{
|
||||
ProviderConfig: addrs.ProviderConfig{
|
||||
Type: "aws",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -147,14 +152,29 @@ func TestNodeRefreshableDataResourceDynamicExpand_scaleIn(t *testing.T) {
|
|||
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.NodeDestroyableDataResource
|
||||
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.NodeDestroyableDataResource
|
||||
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.ProviderConfig.Type == "" {
|
||||
t.Fatal("NodeDestroyableDataResourceInstance missing provider config")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ func (n *NodeRefreshableManagedResourceInstance) EvalTree() EvalNode {
|
|||
NodeAbstractResourceInstance: n.NodeAbstractResourceInstance,
|
||||
}
|
||||
} else {
|
||||
dn = &NodeDestroyableDataResource{
|
||||
dn = &NodeDestroyableDataResourceInstance{
|
||||
NodeAbstractResourceInstance: n.NodeAbstractResourceInstance,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,9 @@ func (t *AttachStateTransformer) Transform(g *Graph) error {
|
|||
continue
|
||||
}
|
||||
|
||||
an.AttachResourceState(rs)
|
||||
// make sure to attach a copy of the state, so instances can modify the
|
||||
// same ResourceState.
|
||||
an.AttachResourceState(rs.DeepCopy())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
Loading…
Reference in New Issue