mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 01:41:48 -06:00
core: use correct provider config address when eval pending resources
The evaluate data source was using a guessed provider configuration address from configuration in this case, but that isn't necessarily correct since the resource might actually be associated with a config inherited from a parent module. We still need to retain that fallback to config because we are sometimes asked to evaluate when state is incomplete (like in "terraform console"), but if possible we'll take the stored provider address from the state and use that, even if the resource is otherwise "pending".
This commit is contained in:
parent
cae5c2feaa
commit
824986b698
@ -2,6 +2,7 @@ package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
)
|
||||
@ -208,6 +209,7 @@ func writeInstanceToState(
|
||||
rs.Type = resourceType
|
||||
rs.Dependencies = dependencies
|
||||
rs.Provider = provider
|
||||
log.Printf("[TRACE] Saving state for %s, managed by %s", resourceName, provider)
|
||||
|
||||
if err := writerFn(rs); err != nil {
|
||||
return nil, err
|
||||
|
@ -2,6 +2,7 @@ package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -462,10 +463,10 @@ func (d *evaluationStateData) GetResourceInstance(addr addrs.ResourceInstance, r
|
||||
// we revise the state structs to natively support the HCL type system.
|
||||
rs := ms.Resources[addrKey]
|
||||
|
||||
// If we have an exact match for the requested instance and it has non-nil
|
||||
// primary data then we'll use it directly. This is the easy path.
|
||||
if rs != nil && rs.Primary != nil {
|
||||
providerAddr, err := rs.ProviderAddr()
|
||||
var providerAddr addrs.AbsProviderConfig
|
||||
if rs != nil {
|
||||
var err error
|
||||
providerAddr, err = rs.ProviderAddr()
|
||||
if err != nil {
|
||||
// This indicates corruption of or tampering with the state file
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
@ -476,6 +477,20 @@ func (d *evaluationStateData) GetResourceInstance(addr addrs.ResourceInstance, r
|
||||
})
|
||||
return cty.DynamicVal, diags
|
||||
}
|
||||
} else {
|
||||
// Must assume a provider address from the config, then.
|
||||
// This result is usually ignored since we'll probably end up in
|
||||
// the getResourceInstancesAll path after this (if our instance
|
||||
// actually has a key). However, we can also end up here in strange
|
||||
// cases like "terraform console", which might be used before a
|
||||
// particular resource has been created in state at all.
|
||||
providerAddr = config.ProviderConfigAddr().Absolute(d.ModulePath)
|
||||
}
|
||||
|
||||
// If we have an exact match for the requested instance and it has non-nil
|
||||
// primary data then we'll use it directly. This is the easy path.
|
||||
if rs != nil && rs.Primary != nil {
|
||||
log.Printf("[TRACE] GetResourceInstance: %s is a single instance", addr)
|
||||
return d.getResourceInstanceSingle(addr, rng, rs.Primary, providerAddr)
|
||||
}
|
||||
|
||||
@ -484,10 +499,11 @@ func (d *evaluationStateData) GetResourceInstance(addr addrs.ResourceInstance, r
|
||||
// If we have a _keyed_ address then instead it's a single instance that
|
||||
// isn't evaluated yet.
|
||||
if addr.Key != addrs.NoKey {
|
||||
return d.getResourceInstancePending(addr, rng)
|
||||
log.Printf("[TRACE] GetResourceInstance: %s is pending", addr)
|
||||
return d.getResourceInstancePending(addr, rng, providerAddr)
|
||||
}
|
||||
|
||||
return d.getResourceInstancesAll(addr.ContainingResource(), config, ms)
|
||||
return d.getResourceInstancesAll(addr.ContainingResource(), config, ms, providerAddr)
|
||||
}
|
||||
|
||||
func (d *evaluationStateData) getResourceInstanceSingle(addr addrs.ResourceInstance, rng tfdiags.SourceRange, is *InstanceState, providerAddr addrs.AbsProviderConfig) (cty.Value, tfdiags.Diagnostics) {
|
||||
@ -531,7 +547,7 @@ func (d *evaluationStateData) getResourceInstanceSingle(addr addrs.ResourceInsta
|
||||
return val, diags
|
||||
}
|
||||
|
||||
func (d *evaluationStateData) getResourceInstancesAll(addr addrs.Resource, config *configs.Resource, ms *ModuleState) (cty.Value, tfdiags.Diagnostics) {
|
||||
func (d *evaluationStateData) getResourceInstancesAll(addr addrs.Resource, config *configs.Resource, ms *ModuleState, providerAddr addrs.AbsProviderConfig) (cty.Value, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
rng := tfdiags.SourceRangeFromHCL(config.DeclRange)
|
||||
hasCount := config.Count != nil
|
||||
@ -574,6 +590,8 @@ func (d *evaluationStateData) getResourceInstancesAll(addr addrs.Resource, confi
|
||||
key = addrs.StringKey(keyStr)
|
||||
}
|
||||
|
||||
// In this case we'll ignore our given providerAddr, since it was
|
||||
// for a single unkeyed ResourceState, not the keyed one we have now.
|
||||
providerAddr, err := rs.ProviderAddr()
|
||||
if err != nil {
|
||||
// This indicates corruption of or tampering with the state file
|
||||
@ -597,10 +615,14 @@ func (d *evaluationStateData) getResourceInstancesAll(addr addrs.Resource, confi
|
||||
// argument then we'll assume that we're dealing with a resource that
|
||||
// is pending creation (e.g. during the validate walk) and that it
|
||||
// will eventually have only one unkeyed instance.
|
||||
providerAddr := config.ProviderConfigAddr().Absolute(d.ModulePath)
|
||||
// In this case we _do_ use the given providerAddr, since that
|
||||
// is for the unkeyed instance we found in GetResourceInstance.
|
||||
log.Printf("[TRACE] GetResourceInstance: %s has no instances yet", addr)
|
||||
return d.getResourceInstanceSingle(addr.Instance(addrs.NoKey), rng, nil, providerAddr)
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] GetResourceInstance: %s has multiple keyed instances (%d)", addr, length)
|
||||
|
||||
// TODO: In future, when for_each is implemented, we'll need to decide here
|
||||
// whether to return a tuple value or an object value. However, by that
|
||||
// time we should've revised the state structs so we can see unambigously
|
||||
@ -628,7 +650,7 @@ func (d *evaluationStateData) getResourceInstancesAll(addr addrs.Resource, confi
|
||||
return cty.TupleVal(valsSeq), diags
|
||||
}
|
||||
|
||||
func (d *evaluationStateData) getResourceInstancePending(addr addrs.ResourceInstance, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
|
||||
func (d *evaluationStateData) getResourceInstancePending(addr addrs.ResourceInstance, rng tfdiags.SourceRange, providerAddr addrs.AbsProviderConfig) (cty.Value, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
// We'd ideally like to return a properly-typed unknown value here, in
|
||||
@ -655,7 +677,6 @@ func (d *evaluationStateData) getResourceInstancePending(addr addrs.ResourceInst
|
||||
if rc == nil {
|
||||
return cty.DynamicVal, diags
|
||||
}
|
||||
providerAddr := rc.ProviderConfigAddr().Absolute(d.ModulePath)
|
||||
schema := d.getResourceSchema(addr.ContainingResource(), providerAddr)
|
||||
if schema == nil {
|
||||
return cty.DynamicVal, diags
|
||||
@ -668,6 +689,7 @@ func (d *evaluationStateData) getResourceSchema(addr addrs.Resource, providerAdd
|
||||
d.Evaluator.ProvidersLock.Lock()
|
||||
defer d.Evaluator.ProvidersLock.Unlock()
|
||||
|
||||
log.Printf("[TRACE] Need provider schema for %s", providerAddr)
|
||||
providerSchema := d.Evaluator.ProviderSchemas[providerAddr.String()]
|
||||
if providerSchema == nil {
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user