Merge pull request #24807 from hashicorp/jbardin/remove-each-mode
Remove EachMode from state
This commit is contained in:
commit
9debd341bc
|
@ -259,6 +259,7 @@ func marshalResources(resources map[string]*states.Resource, module addrs.Module
|
||||||
|
|
||||||
current := resource{
|
current := resource{
|
||||||
Address: r.Addr.Instance(k).String(),
|
Address: r.Addr.Instance(k).String(),
|
||||||
|
Index: k,
|
||||||
Type: resAddr.Type,
|
Type: resAddr.Type,
|
||||||
Name: resAddr.Name,
|
Name: resAddr.Name,
|
||||||
ProviderName: r.ProviderConfig.Provider.String(),
|
ProviderName: r.ProviderConfig.Provider.String(),
|
||||||
|
@ -276,10 +277,6 @@ func marshalResources(resources map[string]*states.Resource, module addrs.Module
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.EachMode != states.NoEach {
|
|
||||||
current.Index = k
|
|
||||||
}
|
|
||||||
|
|
||||||
schema, _ := schemas.ResourceTypeConfig(
|
schema, _ := schemas.ResourceTypeConfig(
|
||||||
r.ProviderConfig.Provider,
|
r.ProviderConfig.Provider,
|
||||||
resAddr.Mode,
|
resAddr.Mode,
|
||||||
|
|
|
@ -193,7 +193,6 @@ func TestMarshalResources(t *testing.T) {
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EachMode: states.NoEach,
|
|
||||||
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
||||||
addrs.NoKey: {
|
addrs.NoKey: {
|
||||||
Current: &states.ResourceInstanceObjectSrc{
|
Current: &states.ResourceInstanceObjectSrc{
|
||||||
|
@ -237,7 +236,6 @@ func TestMarshalResources(t *testing.T) {
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EachMode: states.EachList,
|
|
||||||
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
||||||
addrs.IntKey(0): {
|
addrs.IntKey(0): {
|
||||||
Current: &states.ResourceInstanceObjectSrc{
|
Current: &states.ResourceInstanceObjectSrc{
|
||||||
|
@ -281,7 +279,6 @@ func TestMarshalResources(t *testing.T) {
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EachMode: states.EachMap,
|
|
||||||
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
||||||
addrs.StringKey("rockhopper"): {
|
addrs.StringKey("rockhopper"): {
|
||||||
Current: &states.ResourceInstanceObjectSrc{
|
Current: &states.ResourceInstanceObjectSrc{
|
||||||
|
@ -325,7 +322,6 @@ func TestMarshalResources(t *testing.T) {
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EachMode: states.NoEach,
|
|
||||||
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
||||||
addrs.NoKey: {
|
addrs.NoKey: {
|
||||||
Deposed: map[states.DeposedKey]*states.ResourceInstanceObjectSrc{
|
Deposed: map[states.DeposedKey]*states.ResourceInstanceObjectSrc{
|
||||||
|
@ -371,7 +367,6 @@ func TestMarshalResources(t *testing.T) {
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EachMode: states.NoEach,
|
|
||||||
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
||||||
addrs.NoKey: {
|
addrs.NoKey: {
|
||||||
Deposed: map[states.DeposedKey]*states.ResourceInstanceObjectSrc{
|
Deposed: map[states.DeposedKey]*states.ResourceInstanceObjectSrc{
|
||||||
|
|
|
@ -279,10 +279,6 @@ func (c *StateMvCommand) Run(args []string) int {
|
||||||
ssFrom.ForgetResourceInstanceAll(addrFrom)
|
ssFrom.ForgetResourceInstanceAll(addrFrom)
|
||||||
ssFrom.RemoveResourceIfEmpty(fromResourceAddr)
|
ssFrom.RemoveResourceIfEmpty(fromResourceAddr)
|
||||||
|
|
||||||
// since this is moving an instance, we can infer the target
|
|
||||||
// mode from the address.
|
|
||||||
toEachMode := eachModeForInstanceKey(addrTo.Resource.Key)
|
|
||||||
|
|
||||||
rs := stateTo.Resource(addrTo.ContainingResource())
|
rs := stateTo.Resource(addrTo.ContainingResource())
|
||||||
if rs == nil {
|
if rs == nil {
|
||||||
// If we're moving to an address without an index then that
|
// If we're moving to an address without an index then that
|
||||||
|
@ -291,15 +287,13 @@ func (c *StateMvCommand) Run(args []string) int {
|
||||||
// address covers both). If there's an index in the
|
// address covers both). If there's an index in the
|
||||||
// target then allow creating the new instance here.
|
// target then allow creating the new instance here.
|
||||||
resourceAddr := addrTo.ContainingResource()
|
resourceAddr := addrTo.ContainingResource()
|
||||||
stateTo.SyncWrapper().SetResourceMeta(
|
stateTo.SyncWrapper().SetResourceProvider(
|
||||||
resourceAddr,
|
resourceAddr,
|
||||||
toEachMode,
|
|
||||||
fromProviderAddr, // in this case, we bring the provider along as if we were moving the whole resource
|
fromProviderAddr, // in this case, we bring the provider along as if we were moving the whole resource
|
||||||
)
|
)
|
||||||
rs = stateTo.Resource(resourceAddr)
|
rs = stateTo.Resource(resourceAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
rs.EachMode = toEachMode
|
|
||||||
rs.Instances[addrTo.Resource.Key] = is
|
rs.Instances[addrTo.Resource.Key] = is
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -372,20 +366,6 @@ func (c *StateMvCommand) Run(args []string) int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func eachModeForInstanceKey(key addrs.InstanceKey) states.EachMode {
|
|
||||||
switch key.(type) {
|
|
||||||
case addrs.IntKey:
|
|
||||||
return states.EachList
|
|
||||||
case addrs.StringKey:
|
|
||||||
return states.EachMap
|
|
||||||
default:
|
|
||||||
if key == addrs.NoKey {
|
|
||||||
return states.NoEach
|
|
||||||
}
|
|
||||||
panic(fmt.Sprintf("don't know an each mode for instance key %#v", key))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sourceObjectAddrs takes a single source object address and expands it to
|
// sourceObjectAddrs takes a single source object address and expands it to
|
||||||
// potentially multiple objects that need to be handled within it.
|
// potentially multiple objects that need to be handled within it.
|
||||||
//
|
//
|
||||||
|
@ -415,11 +395,13 @@ func (c *StateMvCommand) sourceObjectAddrs(state *states.State, matched addrs.Ta
|
||||||
// terraform state mv aws_instance.foo aws_instance.bar[1]
|
// terraform state mv aws_instance.foo aws_instance.bar[1]
|
||||||
// That wouldn't be allowed if aws_instance.foo had multiple instances
|
// That wouldn't be allowed if aws_instance.foo had multiple instances
|
||||||
// since we can't move multiple instances into one.
|
// since we can't move multiple instances into one.
|
||||||
if rs := state.Resource(addr); rs != nil && rs.EachMode == states.NoEach {
|
if rs := state.Resource(addr); rs != nil {
|
||||||
|
if _, ok := rs.Instances[addrs.NoKey]; ok {
|
||||||
ret = append(ret, addr.Instance(addrs.NoKey))
|
ret = append(ret, addr.Instance(addrs.NoKey))
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, addr)
|
ret = append(ret, addr)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ret = append(ret, matched)
|
ret = append(ret, matched)
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,9 +97,10 @@ func TestStateMv(t *testing.T) {
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
t.Fatal(diags.Err())
|
t.Fatal(diags.Err())
|
||||||
}
|
}
|
||||||
i := s.Resource(addr)
|
for key := range s.Resource(addr).Instances {
|
||||||
if i.EachMode != states.EachList {
|
if _, ok := key.(addrs.IntKey); !ok {
|
||||||
t.Fatalf("expected each mode List, got %s", i.EachMode)
|
t.Fatalf("expected each mode List, got key %q", key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// change from list to map
|
// change from list to map
|
||||||
|
@ -118,9 +119,10 @@ func TestStateMv(t *testing.T) {
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
t.Fatal(diags.Err())
|
t.Fatal(diags.Err())
|
||||||
}
|
}
|
||||||
i = s.Resource(addr)
|
for key := range s.Resource(addr).Instances {
|
||||||
if i.EachMode != states.EachMap {
|
if _, ok := key.(addrs.StringKey); !ok {
|
||||||
t.Fatalf("expected each mode Map, got %s", i.EachMode)
|
t.Fatalf("expected each mode map, found key %q", key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// change from from map back to single
|
// change from from map back to single
|
||||||
|
@ -139,9 +141,10 @@ func TestStateMv(t *testing.T) {
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
t.Fatal(diags.Err())
|
t.Fatal(diags.Err())
|
||||||
}
|
}
|
||||||
i = s.Resource(addr)
|
for key := range s.Resource(addr).Instances {
|
||||||
if i.EachMode != states.NoEach {
|
if key != addrs.NoKey {
|
||||||
t.Fatalf("expected each mode NoEach, got %s", i.EachMode)
|
t.Fatalf("expected no each mode, found key %q", key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -179,13 +182,12 @@ func TestStateMv_resourceToInstance(t *testing.T) {
|
||||||
Module: addrs.RootModule,
|
Module: addrs.RootModule,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
s.SetResourceMeta(
|
s.SetResourceProvider(
|
||||||
addrs.Resource{
|
addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "test_instance",
|
Type: "test_instance",
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
}.Absolute(addrs.RootModuleInstance),
|
}.Absolute(addrs.RootModuleInstance),
|
||||||
states.EachList,
|
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
Provider: addrs.NewLegacyProvider("test"),
|
Provider: addrs.NewLegacyProvider("test"),
|
||||||
Module: addrs.RootModule,
|
Module: addrs.RootModule,
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
// Code generated by "stringer -type EachMode"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package states
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
func _() {
|
|
||||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
|
||||||
// Re-run the stringer command to generate them again.
|
|
||||||
var x [1]struct{}
|
|
||||||
_ = x[NoEach-0]
|
|
||||||
_ = x[EachList-76]
|
|
||||||
_ = x[EachMap-77]
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
_EachMode_name_0 = "NoEach"
|
|
||||||
_EachMode_name_1 = "EachListEachMap"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_EachMode_index_1 = [...]uint8{0, 8, 15}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (i EachMode) String() string {
|
|
||||||
switch {
|
|
||||||
case i == 0:
|
|
||||||
return _EachMode_name_0
|
|
||||||
case 76 <= i && i <= 77:
|
|
||||||
i -= 76
|
|
||||||
return _EachMode_name_1[_EachMode_index_1[i]:_EachMode_index_1[i+1]]
|
|
||||||
default:
|
|
||||||
return "EachMode(" + strconv.FormatInt(int64(i), 10) + ")"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -51,10 +51,10 @@ func (ms *Module) ResourceInstance(addr addrs.ResourceInstance) *ResourceInstanc
|
||||||
return rs.Instance(addr.Key)
|
return rs.Instance(addr.Key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetResourceMeta updates the resource-level metadata for the resource
|
// SetResourceProvider updates the resource-level metadata for the resource
|
||||||
// with the given address, creating the resource state for it if it doesn't
|
// with the given address, creating the resource state for it if it doesn't
|
||||||
// already exist.
|
// already exist.
|
||||||
func (ms *Module) SetResourceMeta(addr addrs.Resource, eachMode EachMode, provider addrs.AbsProviderConfig) {
|
func (ms *Module) SetResourceProvider(addr addrs.Resource, provider addrs.AbsProviderConfig) {
|
||||||
rs := ms.Resource(addr)
|
rs := ms.Resource(addr)
|
||||||
if rs == nil {
|
if rs == nil {
|
||||||
rs = &Resource{
|
rs = &Resource{
|
||||||
|
@ -64,7 +64,6 @@ func (ms *Module) SetResourceMeta(addr addrs.Resource, eachMode EachMode, provid
|
||||||
ms.Resources[addr.String()] = rs
|
ms.Resources[addr.String()] = rs
|
||||||
}
|
}
|
||||||
|
|
||||||
rs.EachMode = eachMode
|
|
||||||
rs.ProviderConfig = provider
|
rs.ProviderConfig = provider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,9 +96,7 @@ func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *R
|
||||||
if obj == nil && rs != nil {
|
if obj == nil && rs != nil {
|
||||||
// does the resource have any other objects?
|
// does the resource have any other objects?
|
||||||
// if not then delete the whole resource
|
// if not then delete the whole resource
|
||||||
// When deleting the resource, ensure that its EachMode is NoEach,
|
if len(rs.Instances) == 0 {
|
||||||
// as a resource with EachList or EachMap can have 0 instances and be valid
|
|
||||||
if rs.EachMode == NoEach && len(rs.Instances) == 0 {
|
|
||||||
delete(ms.Resources, addr.Resource.String())
|
delete(ms.Resources, addr.Resource.String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -115,7 +112,7 @@ func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *R
|
||||||
// If we have no objects at all then we'll clean up.
|
// If we have no objects at all then we'll clean up.
|
||||||
delete(rs.Instances, addr.Key)
|
delete(rs.Instances, addr.Key)
|
||||||
// Delete the resource if it has no instances, but only if NoEach
|
// Delete the resource if it has no instances, but only if NoEach
|
||||||
if rs.EachMode == NoEach && len(rs.Instances) == 0 {
|
if len(rs.Instances) == 0 {
|
||||||
delete(ms.Resources, addr.Resource.String())
|
delete(ms.Resources, addr.Resource.String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -125,7 +122,7 @@ func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *R
|
||||||
}
|
}
|
||||||
if rs == nil && obj != nil {
|
if rs == nil && obj != nil {
|
||||||
// We don't have have a resource so make one, which is a side effect of setResourceMeta
|
// We don't have have a resource so make one, which is a side effect of setResourceMeta
|
||||||
ms.SetResourceMeta(addr.Resource, eachModeForInstanceKey(addr.Key), provider)
|
ms.SetResourceProvider(addr.Resource, provider)
|
||||||
// now we have a resource! so update the rs value to point to it
|
// now we have a resource! so update the rs value to point to it
|
||||||
rs = ms.Resource(addr.Resource)
|
rs = ms.Resource(addr.Resource)
|
||||||
}
|
}
|
||||||
|
@ -134,8 +131,8 @@ func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *R
|
||||||
if is == nil {
|
if is == nil {
|
||||||
// if we don't have a resource, create one and add to the instances
|
// if we don't have a resource, create one and add to the instances
|
||||||
is = rs.CreateInstance(addr.Key)
|
is = rs.CreateInstance(addr.Key)
|
||||||
// update the resource meta because we have a new instance, so EachMode may have changed
|
// update the resource meta because we have a new
|
||||||
ms.SetResourceMeta(addr.Resource, eachModeForInstanceKey(addr.Key), provider)
|
ms.SetResourceProvider(addr.Resource, provider)
|
||||||
}
|
}
|
||||||
// Update the resource's ProviderConfig, in case the provider has updated
|
// Update the resource's ProviderConfig, in case the provider has updated
|
||||||
rs.ProviderConfig = provider
|
rs.ProviderConfig = provider
|
||||||
|
@ -159,7 +156,7 @@ func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *R
|
||||||
// the instance is left with no objects after this operation then it will
|
// the instance is left with no objects after this operation then it will
|
||||||
// be removed from its containing resource altogether.
|
// be removed from its containing resource altogether.
|
||||||
func (ms *Module) SetResourceInstanceDeposed(addr addrs.ResourceInstance, key DeposedKey, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig) {
|
func (ms *Module) SetResourceInstanceDeposed(addr addrs.ResourceInstance, key DeposedKey, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig) {
|
||||||
ms.SetResourceMeta(addr.Resource, eachModeForInstanceKey(addr.Key), provider)
|
ms.SetResourceProvider(addr.Resource, provider)
|
||||||
|
|
||||||
rs := ms.Resource(addr.Resource)
|
rs := ms.Resource(addr.Resource)
|
||||||
is := rs.EnsureInstance(addr.Key)
|
is := rs.EnsureInstance(addr.Key)
|
||||||
|
@ -173,7 +170,7 @@ func (ms *Module) SetResourceInstanceDeposed(addr addrs.ResourceInstance, key De
|
||||||
// If we have no objects at all then we'll clean up.
|
// If we have no objects at all then we'll clean up.
|
||||||
delete(rs.Instances, addr.Key)
|
delete(rs.Instances, addr.Key)
|
||||||
}
|
}
|
||||||
if rs.EachMode == NoEach && len(rs.Instances) == 0 {
|
if len(rs.Instances) == 0 {
|
||||||
// Also clean up if we only expect to have one instance anyway
|
// Also clean up if we only expect to have one instance anyway
|
||||||
// and there are none. We leave the resource behind if an each mode
|
// and there are none. We leave the resource behind if an each mode
|
||||||
// is active because an empty list or map of instances is a valid state.
|
// is active because an empty list or map of instances is a valid state.
|
||||||
|
@ -190,7 +187,7 @@ func (ms *Module) ForgetResourceInstanceAll(addr addrs.ResourceInstance) {
|
||||||
}
|
}
|
||||||
delete(rs.Instances, addr.Key)
|
delete(rs.Instances, addr.Key)
|
||||||
|
|
||||||
if rs.EachMode == NoEach && len(rs.Instances) == 0 {
|
if len(rs.Instances) == 0 {
|
||||||
// Also clean up if we only expect to have one instance anyway
|
// Also clean up if we only expect to have one instance anyway
|
||||||
// and there are none. We leave the resource behind if an each mode
|
// and there are none. We leave the resource behind if an each mode
|
||||||
// is active because an empty list or map of instances is a valid state.
|
// is active because an empty list or map of instances is a valid state.
|
||||||
|
@ -215,7 +212,7 @@ func (ms *Module) ForgetResourceInstanceDeposed(addr addrs.ResourceInstance, key
|
||||||
// If we have no objects at all then we'll clean up.
|
// If we have no objects at all then we'll clean up.
|
||||||
delete(rs.Instances, addr.Key)
|
delete(rs.Instances, addr.Key)
|
||||||
}
|
}
|
||||||
if rs.EachMode == NoEach && len(rs.Instances) == 0 {
|
if len(rs.Instances) == 0 {
|
||||||
// Also clean up if we only expect to have one instance anyway
|
// Also clean up if we only expect to have one instance anyway
|
||||||
// and there are none. We leave the resource behind if an each mode
|
// and there are none. We leave the resource behind if an each mode
|
||||||
// is active because an empty list or map of instances is a valid state.
|
// is active because an empty list or map of instances is a valid state.
|
||||||
|
|
|
@ -14,12 +14,6 @@ type Resource struct {
|
||||||
// belongs to.
|
// belongs to.
|
||||||
Addr addrs.AbsResource
|
Addr addrs.AbsResource
|
||||||
|
|
||||||
// EachMode is the multi-instance mode currently in use for this resource,
|
|
||||||
// or NoEach if this is a single-instance resource. This dictates what
|
|
||||||
// type of value is returned when accessing this resource via expressions
|
|
||||||
// in the Terraform language.
|
|
||||||
EachMode EachMode
|
|
||||||
|
|
||||||
// Instances contains the potentially-multiple instances associated with
|
// Instances contains the potentially-multiple instances associated with
|
||||||
// this resource. This map can contain a mixture of different key types,
|
// this resource. This map can contain a mixture of different key types,
|
||||||
// but only the ones of InstanceKeyType are considered current.
|
// but only the ones of InstanceKeyType are considered current.
|
||||||
|
@ -173,31 +167,6 @@ func (i *ResourceInstance) findUnusedDeposedKey() DeposedKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EachMode specifies the multi-instance mode for a resource.
|
|
||||||
type EachMode rune
|
|
||||||
|
|
||||||
const (
|
|
||||||
NoEach EachMode = 0
|
|
||||||
EachList EachMode = 'L'
|
|
||||||
EachMap EachMode = 'M'
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:generate go run golang.org/x/tools/cmd/stringer -type EachMode
|
|
||||||
|
|
||||||
func eachModeForInstanceKey(key addrs.InstanceKey) EachMode {
|
|
||||||
switch key.(type) {
|
|
||||||
case addrs.IntKey:
|
|
||||||
return EachList
|
|
||||||
case addrs.StringKey:
|
|
||||||
return EachMap
|
|
||||||
default:
|
|
||||||
if key == addrs.NoKey {
|
|
||||||
return NoEach
|
|
||||||
}
|
|
||||||
panic(fmt.Sprintf("don't know an each mode for instance key %#v", key))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeposedKey is a 8-character hex string used to uniquely identify deposed
|
// DeposedKey is a 8-character hex string used to uniquely identify deposed
|
||||||
// instance objects in the state.
|
// instance objects in the state.
|
||||||
type DeposedKey string
|
type DeposedKey string
|
||||||
|
|
|
@ -88,7 +88,6 @@ func (rs *Resource) DeepCopy() *Resource {
|
||||||
|
|
||||||
return &Resource{
|
return &Resource{
|
||||||
Addr: rs.Addr,
|
Addr: rs.Addr,
|
||||||
EachMode: rs.EachMode,
|
|
||||||
Instances: instances,
|
Instances: instances,
|
||||||
ProviderConfig: rs.ProviderConfig, // technically mutable, but immutable by convention
|
ProviderConfig: rs.ProviderConfig, // technically mutable, but immutable by convention
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,6 @@ func TestState(t *testing.T) {
|
||||||
Name: "baz",
|
Name: "baz",
|
||||||
}.Absolute(addrs.RootModuleInstance),
|
}.Absolute(addrs.RootModuleInstance),
|
||||||
|
|
||||||
EachMode: EachList,
|
|
||||||
Instances: map[addrs.InstanceKey]*ResourceInstance{
|
Instances: map[addrs.InstanceKey]*ResourceInstance{
|
||||||
addrs.IntKey(0): {
|
addrs.IntKey(0): {
|
||||||
Current: &ResourceInstanceObjectSrc{
|
Current: &ResourceInstanceObjectSrc{
|
||||||
|
|
|
@ -95,27 +95,10 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var eachMode states.EachMode
|
|
||||||
switch rsV4.EachMode {
|
|
||||||
case "":
|
|
||||||
eachMode = states.NoEach
|
|
||||||
case "list":
|
|
||||||
eachMode = states.EachList
|
|
||||||
case "map":
|
|
||||||
eachMode = states.EachMap
|
|
||||||
default:
|
|
||||||
diags = diags.Append(tfdiags.Sourceless(
|
|
||||||
tfdiags.Error,
|
|
||||||
"Invalid resource metadata in state",
|
|
||||||
fmt.Sprintf("Resource %s has invalid \"each\" value %q in state.", rAddr.Absolute(moduleAddr), eachMode),
|
|
||||||
))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ms := state.EnsureModule(moduleAddr)
|
ms := state.EnsureModule(moduleAddr)
|
||||||
|
|
||||||
// Ensure the resource container object is present in the state.
|
// Ensure the resource container object is present in the state.
|
||||||
ms.SetResourceMeta(rAddr, eachMode, providerAddr)
|
ms.SetResourceProvider(rAddr, providerAddr)
|
||||||
|
|
||||||
for _, isV4 := range rsV4.Instances {
|
for _, isV4 := range rsV4.Instances {
|
||||||
keyRaw := isV4.IndexKey
|
keyRaw := isV4.IndexKey
|
||||||
|
@ -272,7 +255,7 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
|
||||||
// on the incoming objects. That behavior is useful when we're making
|
// on the incoming objects. That behavior is useful when we're making
|
||||||
// piecemeal updates to the state during an apply, but when we're
|
// piecemeal updates to the state during an apply, but when we're
|
||||||
// reading the state file we want to reflect its contents exactly.
|
// reading the state file we want to reflect its contents exactly.
|
||||||
ms.SetResourceMeta(rAddr, eachMode, providerAddr)
|
ms.SetResourceProvider(rAddr, providerAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The root module is special in that we persist its attributes and thus
|
// The root module is special in that we persist its attributes and thus
|
||||||
|
@ -394,29 +377,11 @@ func writeStateV4(file *File, w io.Writer) tfdiags.Diagnostics {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var eachMode string
|
|
||||||
switch rs.EachMode {
|
|
||||||
case states.NoEach:
|
|
||||||
eachMode = ""
|
|
||||||
case states.EachList:
|
|
||||||
eachMode = "list"
|
|
||||||
case states.EachMap:
|
|
||||||
eachMode = "map"
|
|
||||||
default:
|
|
||||||
diags = diags.Append(tfdiags.Sourceless(
|
|
||||||
tfdiags.Error,
|
|
||||||
"Failed to serialize resource in state",
|
|
||||||
fmt.Sprintf("Resource %s has \"each\" mode %s, which cannot be serialized in state", resourceAddr.Absolute(moduleAddr), rs.EachMode),
|
|
||||||
))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
sV4.Resources = append(sV4.Resources, resourceStateV4{
|
sV4.Resources = append(sV4.Resources, resourceStateV4{
|
||||||
Module: moduleAddr.String(),
|
Module: moduleAddr.String(),
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
Type: resourceAddr.Type,
|
Type: resourceAddr.Type,
|
||||||
Name: resourceAddr.Name,
|
Name: resourceAddr.Name,
|
||||||
EachMode: eachMode,
|
|
||||||
ProviderConfig: rs.ProviderConfig.String(),
|
ProviderConfig: rs.ProviderConfig.String(),
|
||||||
Instances: []instanceObjectStateV4{},
|
Instances: []instanceObjectStateV4{},
|
||||||
})
|
})
|
||||||
|
|
|
@ -154,6 +154,6 @@ func TestFullInitialState() *states.State {
|
||||||
Provider: addrs.NewLegacyProvider(rAddr.ImpliedProvider()),
|
Provider: addrs.NewLegacyProvider(rAddr.ImpliedProvider()),
|
||||||
Module: addrs.RootModule,
|
Module: addrs.RootModule,
|
||||||
}
|
}
|
||||||
childMod.SetResourceMeta(rAddr, states.EachList, providerAddr)
|
childMod.SetResourceProvider(rAddr, providerAddr)
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,12 +197,12 @@ func (s *SyncState) ResourceInstanceObject(addr addrs.AbsResourceInstance, gen G
|
||||||
// SetResourceMeta updates the resource-level metadata for the resource at
|
// SetResourceMeta updates the resource-level metadata for the resource at
|
||||||
// the given address, creating the containing module state and resource state
|
// the given address, creating the containing module state and resource state
|
||||||
// as a side-effect if not already present.
|
// as a side-effect if not already present.
|
||||||
func (s *SyncState) SetResourceMeta(addr addrs.AbsResource, eachMode EachMode, provider addrs.AbsProviderConfig) {
|
func (s *SyncState) SetResourceProvider(addr addrs.AbsResource, provider addrs.AbsProviderConfig) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
ms := s.state.EnsureModule(addr.Module)
|
ms := s.state.EnsureModule(addr.Module)
|
||||||
ms.SetResourceMeta(addr.Resource, eachMode, provider)
|
ms.SetResourceProvider(addr.Resource, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveResource removes the entire state for the given resource, taking with
|
// RemoveResource removes the entire state for the given resource, taking with
|
||||||
|
|
|
@ -2637,7 +2637,7 @@ func TestContext2Apply_orphanResource(t *testing.T) {
|
||||||
Type: "test_thing",
|
Type: "test_thing",
|
||||||
Name: "one",
|
Name: "one",
|
||||||
}.Absolute(addrs.RootModuleInstance)
|
}.Absolute(addrs.RootModuleInstance)
|
||||||
s.SetResourceMeta(oneAddr, states.EachList, providerAddr)
|
s.SetResourceProvider(oneAddr, providerAddr)
|
||||||
s.SetResourceInstanceCurrent(oneAddr.Instance(addrs.IntKey(0)), &states.ResourceInstanceObjectSrc{
|
s.SetResourceInstanceCurrent(oneAddr.Instance(addrs.IntKey(0)), &states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{}`),
|
AttrsJSON: []byte(`{}`),
|
||||||
|
@ -6111,9 +6111,7 @@ func TestContext2Apply_destroyWithModuleVariableAndCount(t *testing.T) {
|
||||||
//Test that things were destroyed
|
//Test that things were destroyed
|
||||||
actual := strings.TrimSpace(state.String())
|
actual := strings.TrimSpace(state.String())
|
||||||
expected := strings.TrimSpace(`
|
expected := strings.TrimSpace(`
|
||||||
<no state>
|
<no state>`)
|
||||||
module.child:
|
|
||||||
<no state>`)
|
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual)
|
t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual)
|
||||||
}
|
}
|
||||||
|
@ -6269,9 +6267,7 @@ func TestContext2Apply_destroyWithModuleVariableAndCountNested(t *testing.T) {
|
||||||
//Test that things were destroyed
|
//Test that things were destroyed
|
||||||
actual := strings.TrimSpace(state.String())
|
actual := strings.TrimSpace(state.String())
|
||||||
expected := strings.TrimSpace(`
|
expected := strings.TrimSpace(`
|
||||||
<no state>
|
<no state>`)
|
||||||
module.child.child2:
|
|
||||||
<no state>`)
|
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual)
|
t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual)
|
||||||
}
|
}
|
||||||
|
|
|
@ -475,7 +475,7 @@ func (n *EvalWriteResourceState) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
return nil, diags.Err()
|
return nil, diags.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
state.SetResourceMeta(n.Addr, states.EachList, n.ProviderAddr)
|
state.SetResourceProvider(n.Addr, n.ProviderAddr)
|
||||||
expander.SetResourceCount(n.Addr.Module, n.Addr.Resource, count)
|
expander.SetResourceCount(n.Addr.Module, n.Addr.Resource, count)
|
||||||
|
|
||||||
case n.Config.ForEach != nil:
|
case n.Config.ForEach != nil:
|
||||||
|
@ -487,11 +487,11 @@ func (n *EvalWriteResourceState) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
|
|
||||||
// This method takes care of all of the business logic of updating this
|
// This method takes care of all of the business logic of updating this
|
||||||
// while ensuring that any existing instances are preserved, etc.
|
// while ensuring that any existing instances are preserved, etc.
|
||||||
state.SetResourceMeta(n.Addr, states.EachMap, n.ProviderAddr)
|
state.SetResourceProvider(n.Addr, n.ProviderAddr)
|
||||||
expander.SetResourceForEach(n.Addr.Module, n.Addr.Resource, forEach)
|
expander.SetResourceForEach(n.Addr.Module, n.Addr.Resource, forEach)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
state.SetResourceMeta(n.Addr, states.NoEach, n.ProviderAddr)
|
state.SetResourceProvider(n.Addr, n.ProviderAddr)
|
||||||
expander.SetResourceSingle(n.Addr.Module, n.Addr.Resource)
|
expander.SetResourceSingle(n.Addr.Module, n.Addr.Resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/agext/levenshtein"
|
"github.com/agext/levenshtein"
|
||||||
|
@ -803,43 +802,6 @@ func (d *evaluationStateData) getResourceSchema(addr addrs.Resource, providerAdd
|
||||||
return schema
|
return schema
|
||||||
}
|
}
|
||||||
|
|
||||||
// coerceInstanceKey attempts to convert the given key to the type expected
|
|
||||||
// for the given EachMode.
|
|
||||||
//
|
|
||||||
// If the key is already of the correct type or if it cannot be converted then
|
|
||||||
// it is returned verbatim. If conversion is required and possible, the
|
|
||||||
// converted value is returned. Callers should not try to determine if
|
|
||||||
// conversion was possible, should instead just check if the result is of
|
|
||||||
// the expected type.
|
|
||||||
func (d *evaluationStateData) coerceInstanceKey(key addrs.InstanceKey, mode states.EachMode) addrs.InstanceKey {
|
|
||||||
if key == addrs.NoKey {
|
|
||||||
// An absent key can't be converted
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
switch mode {
|
|
||||||
case states.NoEach:
|
|
||||||
// No conversions possible at all
|
|
||||||
return key
|
|
||||||
case states.EachMap:
|
|
||||||
if intKey, isInt := key.(addrs.IntKey); isInt {
|
|
||||||
return addrs.StringKey(strconv.Itoa(int(intKey)))
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
case states.EachList:
|
|
||||||
if strKey, isStr := key.(addrs.StringKey); isStr {
|
|
||||||
i, err := strconv.Atoi(string(strKey))
|
|
||||||
if err != nil {
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
return addrs.IntKey(i)
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
default:
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *evaluationStateData) GetTerraformAttr(addr addrs.TerraformAttr, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
|
func (d *evaluationStateData) GetTerraformAttr(addr addrs.TerraformAttr, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
switch addr.Name {
|
switch addr.Name {
|
||||||
|
|
Loading…
Reference in New Issue