don't store an entire Resource in each Instance
The AbstractResourceInstance type was storing the entire Resource from the state, when it only needs the actual instance state. This would cause resources to consume memory on the order of n^2, where n in the number of instances of the resource. Rather than attaching the entire resource state, which includes copying each individual instance, only attach the ResourceInstance state, and extract out the provider address from the Resource.
This commit is contained in:
parent
1c7a8c3e43
commit
ee8cc627a0
|
@ -101,11 +101,14 @@ type NodeAbstractResourceInstance struct {
|
||||||
NodeAbstractResource
|
NodeAbstractResource
|
||||||
Addr addrs.AbsResourceInstance
|
Addr addrs.AbsResourceInstance
|
||||||
|
|
||||||
// The fields below will be automatically set using the Attach
|
// These are set via the AttachState method.
|
||||||
// interfaces if you're running those transforms, but also be explicitly
|
instanceState *states.ResourceInstance
|
||||||
// set if you already have that information.
|
// storedProviderConfig is the provider address retrieved from the
|
||||||
ResourceState *states.Resource
|
// state, but since it is only stored in the whole Resource rather than the
|
||||||
Dependencies []addrs.ConfigResource
|
// ResourceInstance, we extract it out here.
|
||||||
|
storedProviderConfig addrs.AbsProviderConfig
|
||||||
|
|
||||||
|
Dependencies []addrs.ConfigResource
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -287,11 +290,9 @@ func dottedInstanceAddr(tr addrs.ResourceInstance) string {
|
||||||
|
|
||||||
// StateDependencies returns the dependencies saved in the state.
|
// StateDependencies returns the dependencies saved in the state.
|
||||||
func (n *NodeAbstractResourceInstance) StateDependencies() []addrs.ConfigResource {
|
func (n *NodeAbstractResourceInstance) StateDependencies() []addrs.ConfigResource {
|
||||||
if rs := n.ResourceState; rs != nil {
|
if s := n.instanceState; s != nil {
|
||||||
if s := rs.Instance(n.Addr.Resource.Key); s != nil {
|
if s.Current != nil {
|
||||||
if s.Current != nil {
|
return s.Current.Dependencies
|
||||||
return s.Current.Dependencies
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,12 +340,12 @@ func (n *NodeAbstractResourceInstance) ProvidedBy() (addrs.ProviderConfig, bool)
|
||||||
}, false
|
}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have state, then we will use the provider from there
|
// See if we have a valid provider config from the state.
|
||||||
if n.ResourceState != nil {
|
if n.storedProviderConfig.Provider.Type != "" {
|
||||||
// An address from the state must match exactly, since we must ensure
|
// An address from the state must match exactly, since we must ensure
|
||||||
// we refresh/destroy a resource with the same provider configuration
|
// we refresh/destroy a resource with the same provider configuration
|
||||||
// that created it.
|
// that created it.
|
||||||
return n.ResourceState.ProviderConfig, true
|
return n.storedProviderConfig, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// No provider configuration found; return a default address
|
// No provider configuration found; return a default address
|
||||||
|
@ -410,7 +411,12 @@ func (n *NodeAbstractResource) AttachResourceDependencies(deps []addrs.ConfigRes
|
||||||
|
|
||||||
// GraphNodeAttachResourceState
|
// GraphNodeAttachResourceState
|
||||||
func (n *NodeAbstractResourceInstance) AttachResourceState(s *states.Resource) {
|
func (n *NodeAbstractResourceInstance) AttachResourceState(s *states.Resource) {
|
||||||
n.ResourceState = s
|
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
|
// GraphNodeAttachResourceConfig
|
||||||
|
|
|
@ -63,11 +63,9 @@ func (n *NodeDestroyResourceInstance) CreateBeforeDestroy() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise check the state for a stored destroy order
|
// Otherwise check the state for a stored destroy order
|
||||||
if rs := n.ResourceState; rs != nil {
|
if s := n.instanceState; s != nil {
|
||||||
if s := rs.Instance(n.Addr.Resource.Key); s != nil {
|
if s.Current != nil {
|
||||||
if s.Current != nil {
|
return s.Current.CreateBeforeDestroy
|
||||||
return s.Current.CreateBeforeDestroy
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,11 +132,7 @@ func (n *NodeDestroyResourceInstance) EvalTree() EvalNode {
|
||||||
addr := n.ResourceInstanceAddr()
|
addr := n.ResourceInstanceAddr()
|
||||||
|
|
||||||
// Get our state
|
// Get our state
|
||||||
rs := n.ResourceState
|
is := n.instanceState
|
||||||
var is *states.ResourceInstance
|
|
||||||
if rs != nil {
|
|
||||||
is = rs.Instance(n.Addr.Resource.Key)
|
|
||||||
}
|
|
||||||
if is == nil {
|
if is == nil {
|
||||||
log.Printf("[WARN] NodeDestroyResourceInstance for %s with no state", addr)
|
log.Printf("[WARN] NodeDestroyResourceInstance for %s with no state", addr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,7 +215,7 @@ func (n *NodeRefreshableManagedResourceInstance) EvalTree() EvalNode {
|
||||||
// Eval info is different depending on what kind of resource this is
|
// Eval info is different depending on what kind of resource this is
|
||||||
switch addr.Resource.Resource.Mode {
|
switch addr.Resource.Resource.Mode {
|
||||||
case addrs.ManagedResourceMode:
|
case addrs.ManagedResourceMode:
|
||||||
if n.ResourceState == nil {
|
if n.instanceState == nil {
|
||||||
log.Printf("[TRACE] NodeRefreshableManagedResourceInstance: %s has no existing state to refresh", addr)
|
log.Printf("[TRACE] NodeRefreshableManagedResourceInstance: %s has no existing state to refresh", addr)
|
||||||
return n.evalTreeManagedResourceNoState()
|
return n.evalTreeManagedResourceNoState()
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalN
|
||||||
|
|
||||||
// This happened during initial development. All known cases were
|
// This happened during initial development. All known cases were
|
||||||
// fixed and tested but as a sanity check let's assert here.
|
// fixed and tested but as a sanity check let's assert here.
|
||||||
if n.ResourceState == nil {
|
if n.instanceState == nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"No resource state attached for addr: %s\n\n"+
|
"No resource state attached for addr: %s\n\n"+
|
||||||
"This is a bug. Please report this to Terraform with your configuration\n"+
|
"This is a bug. Please report this to Terraform with your configuration\n"+
|
||||||
|
|
Loading…
Reference in New Issue