mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-20 11:48:24 -06:00
Use the new SimpleDiff method of the provider so that the diff isn't altered by ForceNew attributes. Always set an "id" as RequiresReplace so core knows an instance will be replaced, even if all ForceNew attributes are filtered out due to ignore_changes.
143 lines
3.7 KiB
Go
143 lines
3.7 KiB
Go
package resource
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
"github.com/hashicorp/terraform/config/hcl2shim"
|
|
|
|
"github.com/hashicorp/terraform/states"
|
|
"github.com/hashicorp/terraform/terraform"
|
|
)
|
|
|
|
func mustShimNewState(newState *states.State, schemas *terraform.Schemas) *terraform.State {
|
|
s, err := shimNewState(newState, schemas)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return s
|
|
}
|
|
|
|
// shimState takes a new *states.State and reverts it to a legacy state for the provider ACC tests
|
|
func shimNewState(newState *states.State, schemas *terraform.Schemas) (*terraform.State, error) {
|
|
state := terraform.NewState()
|
|
|
|
// in the odd case of a nil state, let the helper packages handle it
|
|
if newState == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
for _, newMod := range newState.Modules {
|
|
mod := state.AddModule(newMod.Addr)
|
|
|
|
for name, out := range newMod.OutputValues {
|
|
outputType := ""
|
|
val := hcl2shim.ConfigValueFromHCL2(out.Value)
|
|
ty := out.Value.Type()
|
|
switch {
|
|
case ty == cty.String:
|
|
outputType = "string"
|
|
case ty.IsTupleType() || ty.IsListType():
|
|
outputType = "list"
|
|
case ty.IsMapType():
|
|
outputType = "map"
|
|
}
|
|
|
|
mod.Outputs[name] = &terraform.OutputState{
|
|
Type: outputType,
|
|
Value: val,
|
|
Sensitive: out.Sensitive,
|
|
}
|
|
}
|
|
|
|
for _, res := range newMod.Resources {
|
|
resType := res.Addr.Type
|
|
providerType := res.ProviderConfig.ProviderConfig.Type
|
|
|
|
providerSchema := schemas.Providers[providerType]
|
|
if providerSchema == nil {
|
|
return nil, fmt.Errorf("missing schema for %q", providerType)
|
|
}
|
|
|
|
var resSchema *configschema.Block
|
|
switch res.Addr.Mode {
|
|
case addrs.ManagedResourceMode:
|
|
resSchema = providerSchema.ResourceTypes[resType]
|
|
case addrs.DataResourceMode:
|
|
resSchema = providerSchema.DataSources[resType]
|
|
}
|
|
|
|
if resSchema == nil {
|
|
return nil, fmt.Errorf("mising resource schema for %q in %q", resType, providerType)
|
|
}
|
|
|
|
for key, i := range res.Instances {
|
|
flatmap, err := shimmedAttributes(i.Current, resSchema.ImpliedType())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error decoding state for %q: %s", resType, err)
|
|
}
|
|
|
|
resState := &terraform.ResourceState{
|
|
Type: resType,
|
|
Primary: &terraform.InstanceState{
|
|
ID: flatmap["id"],
|
|
Attributes: flatmap,
|
|
Tainted: i.Current.Status == states.ObjectTainted,
|
|
},
|
|
}
|
|
|
|
for _, dep := range i.Current.Dependencies {
|
|
resState.Dependencies = append(resState.Dependencies, dep.String())
|
|
}
|
|
|
|
// convert the indexes to the old style flapmap indexes
|
|
idx := ""
|
|
switch key.(type) {
|
|
case addrs.IntKey:
|
|
idx = fmt.Sprintf(".%d", key)
|
|
case addrs.StringKey:
|
|
idx = "." + key.String()
|
|
}
|
|
|
|
mod.Resources[res.Addr.String()+idx] = resState
|
|
|
|
// ad any deposed instances
|
|
for _, dep := range i.Deposed {
|
|
flatmap, err := shimmedAttributes(dep, resSchema.ImpliedType())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error decoding deposed state for %q: %s", resType, err)
|
|
}
|
|
|
|
deposed := &terraform.InstanceState{
|
|
ID: flatmap["id"],
|
|
Attributes: flatmap,
|
|
Tainted: dep.Status == states.ObjectTainted,
|
|
}
|
|
|
|
resState.Deposed = append(resState.Deposed, deposed)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return state, nil
|
|
}
|
|
|
|
func shimmedAttributes(instance *states.ResourceInstanceObjectSrc, ty cty.Type) (map[string]string, error) {
|
|
flatmap := instance.AttrsFlat
|
|
|
|
// if we have json attrs, they need to be decoded
|
|
if flatmap == nil {
|
|
rio, err := instance.Decode(ty)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
flatmap = hcl2shim.FlatmapValueFromHCL2(rio.Value)
|
|
}
|
|
return flatmap, nil
|
|
}
|