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 {
|
if inst == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return inst.GetGeneration(gen)
|
return inst.GetGeneration(gen).DeepCopy()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetResourceMeta updates the resource-level metadata for the resource at
|
// 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())
|
absAddr := n.Addr.Absolute(ctx.Path())
|
||||||
state := ctx.State()
|
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
|
obj := *n.State
|
||||||
if obj == nil || obj.Value.IsNull() {
|
if obj == nil || obj.Value.IsNull() {
|
||||||
// No need to encode anything: we'll just write it directly.
|
// No need to encode anything: we'll just write it directly.
|
||||||
|
|
|
@ -1,23 +1,40 @@
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hashicorp/terraform/providers"
|
||||||
"github.com/hashicorp/terraform/states"
|
"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.
|
// it is ready to be destroyed.
|
||||||
type NodeDestroyableDataResource struct {
|
type NodeDestroyableDataResourceInstance struct {
|
||||||
*NodeAbstractResourceInstance
|
*NodeAbstractResourceInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeEvalable
|
// GraphNodeEvalable
|
||||||
func (n *NodeDestroyableDataResource) EvalTree() EvalNode {
|
func (n *NodeDestroyableDataResourceInstance) EvalTree() EvalNode {
|
||||||
addr := n.ResourceInstanceAddr()
|
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.
|
// Just destroy it.
|
||||||
var state *states.ResourceInstanceObject
|
var state *states.ResourceInstanceObject
|
||||||
return &EvalWriteState{
|
return &EvalSequence{
|
||||||
Addr: addr.Resource,
|
Nodes: []EvalNode{
|
||||||
State: &state, // state is nil here
|
&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
|
// We also need a destroyable resource for orphans that are a result of a
|
||||||
// scaled-in count.
|
// scaled-in count.
|
||||||
concreteResourceDestroyable := func(a *NodeAbstractResourceInstance) dag.Vertex {
|
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.Config = n.Config
|
||||||
|
a.ResolvedProvider = n.ResolvedProvider
|
||||||
|
|
||||||
return &NodeDestroyableDataResource{
|
return &NodeDestroyableDataResourceInstance{
|
||||||
NodeAbstractResourceInstance: a,
|
NodeAbstractResourceInstance: a,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,11 @@ func TestNodeRefreshableDataResourceDynamicExpand_scaleIn(t *testing.T) {
|
||||||
"foo",
|
"foo",
|
||||||
),
|
),
|
||||||
Config: m.Module.DataResources["data.aws_instance.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
|
expected := `data.aws_instance.foo[0] - *terraform.NodeRefreshableDataResourceInstance
|
||||||
data.aws_instance.foo[1] - *terraform.NodeRefreshableDataResourceInstance
|
data.aws_instance.foo[1] - *terraform.NodeRefreshableDataResourceInstance
|
||||||
data.aws_instance.foo[2] - *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
|
root - terraform.graphNodeRoot
|
||||||
data.aws_instance.foo[0] - *terraform.NodeRefreshableDataResourceInstance
|
data.aws_instance.foo[0] - *terraform.NodeRefreshableDataResourceInstance
|
||||||
data.aws_instance.foo[1] - *terraform.NodeRefreshableDataResourceInstance
|
data.aws_instance.foo[1] - *terraform.NodeRefreshableDataResourceInstance
|
||||||
data.aws_instance.foo[2] - *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 {
|
if expected != actual {
|
||||||
t.Fatalf("Expected:\n%s\nGot:\n%s", 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,
|
NodeAbstractResourceInstance: n.NodeAbstractResourceInstance,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dn = &NodeDestroyableDataResource{
|
dn = &NodeDestroyableDataResourceInstance{
|
||||||
NodeAbstractResourceInstance: n.NodeAbstractResourceInstance,
|
NodeAbstractResourceInstance: n.NodeAbstractResourceInstance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,9 @@ func (t *AttachStateTransformer) Transform(g *Graph) error {
|
||||||
continue
|
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
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue