mirror of https://github.com/hashicorp/terraform
parent
b54cc1d95f
commit
7ec3f96e3a
@ -1,374 +0,0 @@
|
||||
package terraform
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Add adds the item in the state at the given address.
|
||||
//
|
||||
// The item can be a ModuleState, ResourceState, or InstanceState. Depending
|
||||
// on the item type, the address may or may not be valid. For example, a
|
||||
// module cannot be moved to a resource address, however a resource can be
|
||||
// moved to a module address (it retains the same name, under that resource).
|
||||
//
|
||||
// The item can also be a []*ModuleState, which is the case for nested
|
||||
// modules. In this case, Add will expect the zero-index to be the top-most
|
||||
// module to add and will only nest children from there. For semantics, this
|
||||
// is equivalent to module => module.
|
||||
//
|
||||
// The full semantics of Add:
|
||||
//
|
||||
// ┌───────────────────┬───────────────────┬───────────────────┐
|
||||
// │ Module Address │ Resource Address │ Instance Address │
|
||||
// ┌─────────────────┼───────────────────┼───────────────────┼───────────────────┤
|
||||
// │ ModuleState │ ✓ │ x │ x │
|
||||
// ├─────────────────┼───────────────────┼───────────────────┼───────────────────┤
|
||||
// │ ResourceState │ ✓ │ ✓ │ maybe* │
|
||||
// ├─────────────────┼───────────────────┼───────────────────┼───────────────────┤
|
||||
// │ Instance State │ ✓ │ ✓ │ ✓ │
|
||||
// └─────────────────┴───────────────────┴───────────────────┴───────────────────┘
|
||||
//
|
||||
// *maybe - Resources can be added at an instance address only if the resource
|
||||
// represents a single instance (primary). Example:
|
||||
// "aws_instance.foo" can be moved to "aws_instance.bar.tainted"
|
||||
//
|
||||
func (s *State) Add(fromAddrRaw string, toAddrRaw string, raw interface{}) error {
|
||||
// Parse the address
|
||||
|
||||
toAddr, err := ParseResourceAddress(toAddrRaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse the from address
|
||||
fromAddr, err := ParseResourceAddress(fromAddrRaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Determine the types
|
||||
from := detectValueAddLoc(raw)
|
||||
to := detectAddrAddLoc(toAddr)
|
||||
|
||||
// Find the function to do this
|
||||
fromMap, ok := stateAddFuncs[from]
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid source to add to state: %T", raw)
|
||||
}
|
||||
f, ok := fromMap[to]
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid destination: %s (%d)", toAddr, to)
|
||||
}
|
||||
|
||||
// Call the migrator
|
||||
if err := f(s, fromAddr, toAddr, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prune the state
|
||||
s.prune()
|
||||
return nil
|
||||
}
|
||||
|
||||
func stateAddFunc_Module_Module(s *State, fromAddr, addr *ResourceAddress, raw interface{}) error {
|
||||
// raw can be either *ModuleState or []*ModuleState. The former means
|
||||
// we're moving just one module. The latter means we're moving a module
|
||||
// and children.
|
||||
root := raw
|
||||
var rest []*ModuleState
|
||||
if list, ok := raw.([]*ModuleState); ok {
|
||||
// We need at least one item
|
||||
if len(list) == 0 {
|
||||
return fmt.Errorf("module move with no value to: %s", addr)
|
||||
}
|
||||
|
||||
// The first item is always the root
|
||||
root = list[0]
|
||||
if len(list) > 1 {
|
||||
rest = list[1:]
|
||||
}
|
||||
}
|
||||
|
||||
// Get the actual module state
|
||||
src := root.(*ModuleState).deepcopy()
|
||||
|
||||
// If the target module exists, it is an error
|
||||
path := normalizeModulePath(addr.Path)
|
||||
if s.ModuleByPath(path) != nil {
|
||||
return fmt.Errorf("module target is not empty: %s", addr)
|
||||
}
|
||||
|
||||
// Create it and copy our outputs and dependencies
|
||||
mod := s.AddModule(path)
|
||||
mod.Outputs = src.Outputs
|
||||
mod.Dependencies = src.Dependencies
|
||||
|
||||
// Go through the resources perform an add for each of those
|
||||
for k, v := range src.Resources {
|
||||
resourceKey, err := ParseResourceStateKey(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the resource address for this
|
||||
addrCopy := *addr
|
||||
addrCopy.Type = resourceKey.Type
|
||||
addrCopy.Name = resourceKey.Name
|
||||
addrCopy.Index = resourceKey.Index
|
||||
addrCopy.Mode = resourceKey.Mode
|
||||
|
||||
// Perform an add
|
||||
if err := s.Add(fromAddr.String(), addrCopy.String(), v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Add all the children if we have them
|
||||
for _, item := range rest {
|
||||
// If item isn't a descendent of our root, then ignore it
|
||||
if !src.IsDescendent(item) {
|
||||
continue
|
||||
}
|
||||
|
||||
// It is! Strip the leading prefix and attach that to our address
|
||||
extra := item.Path[len(src.Path):]
|
||||
addrCopy := addr.Copy()
|
||||
addrCopy.Path = append(addrCopy.Path, extra...)
|
||||
|
||||
// Add it
|
||||
s.Add(fromAddr.String(), addrCopy.String(), item)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func stateAddFunc_Resource_Module(
|
||||
s *State, from, to *ResourceAddress, raw interface{}) error {
|
||||
// Build the more specific to addr
|
||||
addr := *to
|
||||
addr.Type = from.Type
|
||||
addr.Name = from.Name
|
||||
|
||||
return s.Add(from.String(), addr.String(), raw)
|
||||
}
|
||||
|
||||
func stateAddFunc_Resource_Resource(s *State, fromAddr, addr *ResourceAddress, raw interface{}) error {
|
||||
// raw can be either *ResourceState or []*ResourceState. The former means
|
||||
// we're moving just one resource. The latter means we're moving a count
|
||||
// of resources.
|
||||
if list, ok := raw.([]*ResourceState); ok {
|
||||
// We need at least one item
|
||||
if len(list) == 0 {
|
||||
return fmt.Errorf("resource move with no value to: %s", addr)
|
||||
}
|
||||
|
||||
// If there is an index, this is an error since we can't assign
|
||||
// a set of resources to a single index
|
||||
if addr.Index >= 0 && len(list) > 1 {
|
||||
return fmt.Errorf(
|
||||
"multiple resources can't be moved to a single index: "+
|
||||
"%s => %s", fromAddr, addr)
|
||||
}
|
||||
|
||||
// Add each with a specific index
|
||||
for i, rs := range list {
|
||||
addrCopy := addr.Copy()
|
||||
addrCopy.Index = i
|
||||
|
||||
if err := s.Add(fromAddr.String(), addrCopy.String(), rs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
src := raw.(*ResourceState).deepcopy()
|
||||
|
||||
// Initialize the resource
|
||||
resourceRaw, exists := stateAddInitAddr(s, addr)
|
||||
if exists {
|
||||
return fmt.Errorf("resource exists and not empty: %s", addr)
|
||||
}
|
||||
resource := resourceRaw.(*ResourceState)
|
||||
resource.Type = src.Type
|
||||
resource.Dependencies = src.Dependencies
|
||||
resource.Provider = src.Provider
|
||||
|
||||
// Move the primary
|
||||
if src.Primary != nil {
|
||||
addrCopy := *addr
|
||||
addrCopy.InstanceType = TypePrimary
|
||||
addrCopy.InstanceTypeSet = true
|
||||
if err := s.Add(fromAddr.String(), addrCopy.String(), src.Primary); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Move all deposed
|
||||
if len(src.Deposed) > 0 {
|
||||
resource.Deposed = src.Deposed
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func stateAddFunc_Instance_Instance(s *State, fromAddr, addr *ResourceAddress, raw interface{}) error {
|
||||
src := raw.(*InstanceState).DeepCopy()
|
||||
|
||||
// Create the instance
|
||||
instanceRaw, _ := stateAddInitAddr(s, addr)
|
||||
instance := instanceRaw.(*InstanceState)
|
||||
|
||||
// Set it
|
||||
instance.Set(src)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func stateAddFunc_Instance_Module(
|
||||
s *State, from, to *ResourceAddress, raw interface{}) error {
|
||||
addr := *to
|
||||
addr.Type = from.Type
|
||||
addr.Name = from.Name
|
||||
|
||||
return s.Add(from.String(), addr.String(), raw)
|
||||
}
|
||||
|
||||
func stateAddFunc_Instance_Resource(
|
||||
s *State, from, to *ResourceAddress, raw interface{}) error {
|
||||
addr := *to
|
||||
addr.InstanceType = TypePrimary
|
||||
addr.InstanceTypeSet = true
|
||||
|
||||
return s.Add(from.String(), addr.String(), raw)
|
||||
}
|
||||
|
||||
// stateAddFunc is the type of function for adding an item to a state
|
||||
type stateAddFunc func(s *State, from, to *ResourceAddress, item interface{}) error
|
||||
|
||||
// stateAddFuncs has the full matrix mapping of the state adders.
|
||||
var stateAddFuncs map[stateAddLoc]map[stateAddLoc]stateAddFunc
|
||||
|
||||
func init() {
|
||||
stateAddFuncs = map[stateAddLoc]map[stateAddLoc]stateAddFunc{
|
||||
stateAddModule: {
|
||||
stateAddModule: stateAddFunc_Module_Module,
|
||||
},
|
||||
stateAddResource: {
|
||||
stateAddModule: stateAddFunc_Resource_Module,
|
||||
stateAddResource: stateAddFunc_Resource_Resource,
|
||||
},
|
||||
stateAddInstance: {
|
||||
stateAddInstance: stateAddFunc_Instance_Instance,
|
||||
stateAddModule: stateAddFunc_Instance_Module,
|
||||
stateAddResource: stateAddFunc_Instance_Resource,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// stateAddLoc is an enum to represent the location where state is being
|
||||
// moved from/to. We use this for quick lookups in a function map.
|
||||
type stateAddLoc uint
|
||||
|
||||
const (
|
||||
stateAddInvalid stateAddLoc = iota
|
||||
stateAddModule
|
||||
stateAddResource
|
||||
stateAddInstance
|
||||
)
|
||||
|
||||
// detectAddrAddLoc detects the state type for the given address. This
|
||||
// function is specifically not unit tested since we consider the State.Add
|
||||
// functionality to be comprehensive enough to cover this.
|
||||
func detectAddrAddLoc(addr *ResourceAddress) stateAddLoc {
|
||||
if addr.Name == "" {
|
||||
return stateAddModule
|
||||
}
|
||||
|
||||
if !addr.InstanceTypeSet {
|
||||
return stateAddResource
|
||||
}
|
||||
|
||||
return stateAddInstance
|
||||
}
|
||||
|
||||
// detectValueAddLoc determines the stateAddLoc value from the raw value
|
||||
// that is some State structure.
|
||||
func detectValueAddLoc(raw interface{}) stateAddLoc {
|
||||
switch raw.(type) {
|
||||
case *ModuleState:
|
||||
return stateAddModule
|
||||
case []*ModuleState:
|
||||
return stateAddModule
|
||||
case *ResourceState:
|
||||
return stateAddResource
|
||||
case []*ResourceState:
|
||||
return stateAddResource
|
||||
case *InstanceState:
|
||||
return stateAddInstance
|
||||
default:
|
||||
return stateAddInvalid
|
||||
}
|
||||
}
|
||||
|
||||
// stateAddInitAddr takes a ResourceAddress and creates the non-existing
|
||||
// resources up to that point, returning the empty (or existing) interface
|
||||
// at that address.
|
||||
func stateAddInitAddr(s *State, addr *ResourceAddress) (interface{}, bool) {
|
||||
addType := detectAddrAddLoc(addr)
|
||||
|
||||
// Get the module
|
||||
path := normalizeModulePath(addr.Path)
|
||||
exists := true
|
||||
mod := s.ModuleByPath(path)
|
||||
if mod == nil {
|
||||
mod = s.AddModule(path)
|
||||
exists = false
|
||||
}
|
||||
if addType == stateAddModule {
|
||||
return mod, exists
|
||||
}
|
||||
|
||||
// Add the resource
|
||||
resourceKey := (&ResourceStateKey{
|
||||
Name: addr.Name,
|
||||
Type: addr.Type,
|
||||
Index: addr.Index,
|
||||
Mode: addr.Mode,
|
||||
}).String()
|
||||
exists = true
|
||||
resource, ok := mod.Resources[resourceKey]
|
||||
if !ok {
|
||||
resource = &ResourceState{Type: addr.Type}
|
||||
resource.init()
|
||||
mod.Resources[resourceKey] = resource
|
||||
exists = false
|
||||
}
|
||||
if addType == stateAddResource {
|
||||
return resource, exists
|
||||
}
|
||||
|
||||
// Get the instance
|
||||
exists = true
|
||||
instance := &InstanceState{}
|
||||
switch addr.InstanceType {
|
||||
case TypePrimary, TypeTainted:
|
||||
if v := resource.Primary; v != nil {
|
||||
instance = resource.Primary
|
||||
} else {
|
||||
exists = false
|
||||
}
|
||||
case TypeDeposed:
|
||||
idx := addr.Index
|
||||
if addr.Index < 0 {
|
||||
idx = 0
|
||||
}
|
||||
if len(resource.Deposed) > idx {
|
||||
instance = resource.Deposed[idx]
|
||||
} else {
|
||||
resource.Deposed = append(resource.Deposed, instance)
|
||||
exists = false
|
||||
}
|
||||
}
|
||||
|
||||
return instance, exists
|
||||
}
|
||||
@ -1,695 +0,0 @@
|
||||
package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStateAdd(t *testing.T) {
|
||||
cases := []struct {
|
||||
Name string
|
||||
Err bool
|
||||
From, To string
|
||||
Value interface{}
|
||||
One, Two *State
|
||||
}{
|
||||
{
|
||||
"ModuleState => Module Addr (new)",
|
||||
false,
|
||||
"",
|
||||
"module.foo",
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
"test_instance.bar": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
"test_instance.bar": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ModuleState => Nested Module Addr (new)",
|
||||
false,
|
||||
"",
|
||||
"module.foo.module.bar",
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
"test_instance.bar": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo", "bar"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
"test_instance.bar": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ModuleState w/ outputs and deps => Module Addr (new)",
|
||||
false,
|
||||
"",
|
||||
"module.foo",
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
Outputs: map[string]*OutputState{
|
||||
"foo": &OutputState{
|
||||
Type: "string",
|
||||
Sensitive: false,
|
||||
Value: "bar",
|
||||
},
|
||||
},
|
||||
Dependencies: []string{"foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
"test_instance.bar": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo"},
|
||||
Outputs: map[string]*OutputState{
|
||||
"foo": &OutputState{
|
||||
Type: "string",
|
||||
Sensitive: false,
|
||||
Value: "bar",
|
||||
},
|
||||
},
|
||||
Dependencies: []string{"foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
"test_instance.bar": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ModuleState => Module Addr (existing)",
|
||||
true,
|
||||
"",
|
||||
"module.foo",
|
||||
&ModuleState{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.baz": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
},
|
||||
|
||||
{
|
||||
"ModuleState with children => Module Addr (new)",
|
||||
false,
|
||||
"module.foo",
|
||||
"module.bar",
|
||||
|
||||
[]*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo"},
|
||||
Resources: map[string]*ResourceState{},
|
||||
},
|
||||
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo", "child1"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo", "child2"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Should be ignored
|
||||
&ModuleState{
|
||||
Path: []string{"root", "baz", "child2"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root", "bar"},
|
||||
Resources: map[string]*ResourceState{},
|
||||
},
|
||||
|
||||
&ModuleState{
|
||||
Path: []string{"root", "bar", "child1"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&ModuleState{
|
||||
Path: []string{"root", "bar", "child2"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ResourceState => Resource Addr (new)",
|
||||
false,
|
||||
"aws_instance.bar",
|
||||
"aws_instance.foo",
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ResourceState w/ deps, provider => Resource Addr (new)",
|
||||
false,
|
||||
"aws_instance.bar",
|
||||
"aws_instance.foo",
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Provider: "foo",
|
||||
Dependencies: []string{"bar"},
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Provider: "foo",
|
||||
Dependencies: []string{"bar"},
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ResourceState tainted => Resource Addr (new)",
|
||||
false,
|
||||
"aws_instance.bar",
|
||||
"aws_instance.foo",
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
Tainted: true,
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
Tainted: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ResourceState with count unspecified => Resource Addr (new)",
|
||||
false,
|
||||
"aws_instance.bar",
|
||||
"aws_instance.foo",
|
||||
[]*ResourceState{
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.foo.0": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
"aws_instance.foo.1": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ResourceState with count unspecified => Resource Addr (new with count)",
|
||||
true,
|
||||
"aws_instance.bar",
|
||||
"aws_instance.foo[0]",
|
||||
[]*ResourceState{
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
nil,
|
||||
},
|
||||
|
||||
{
|
||||
"ResourceState with single count unspecified => Resource Addr (new with count)",
|
||||
false,
|
||||
"aws_instance.bar",
|
||||
"aws_instance.foo[0]",
|
||||
[]*ResourceState{
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.foo.0": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ResourceState => Resource Addr (new with count)",
|
||||
false,
|
||||
"aws_instance.bar",
|
||||
"aws_instance.foo[0]",
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.foo.0": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ResourceState => Resource Addr (existing)",
|
||||
true,
|
||||
"aws_instance.bar",
|
||||
"aws_instance.foo",
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
},
|
||||
|
||||
{
|
||||
"ResourceState => Module (new)",
|
||||
false,
|
||||
"aws_instance.bar",
|
||||
"module.foo",
|
||||
&ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.bar": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"InstanceState => Resource (new)",
|
||||
false,
|
||||
"aws_instance.bar.primary",
|
||||
"aws_instance.baz",
|
||||
&InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.baz": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"InstanceState => Module (new)",
|
||||
false,
|
||||
"aws_instance.bar.primary",
|
||||
"module.foo",
|
||||
&InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.bar": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
"ModuleState => Module Addr (new with data source)",
|
||||
false,
|
||||
"",
|
||||
"module.foo",
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"data.test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&State{},
|
||||
&State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: []string{"root", "foo"},
|
||||
Resources: map[string]*ResourceState{
|
||||
"data.test_instance.foo": &ResourceState{
|
||||
Type: "test_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
|
||||
// Make sure they're both initialized as normal
|
||||
tc.One.init()
|
||||
if tc.Two != nil {
|
||||
tc.Two.init()
|
||||
}
|
||||
|
||||
// Add the value
|
||||
err := tc.One.Add(tc.From, tc.To, tc.Value)
|
||||
if (err != nil) != tc.Err {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tc.Err {
|
||||
return
|
||||
}
|
||||
|
||||
// Prune them both to be sure
|
||||
tc.One.prune()
|
||||
tc.Two.prune()
|
||||
|
||||
// Verify equality
|
||||
if !tc.One.Equal(tc.Two) {
|
||||
//t.Fatalf("Bad: %s\n\n%#v\n\n%#v", k, tc.One, tc.Two)
|
||||
t.Fatalf("Bad: \n\n%s\n\n%s", tc.One.String(), tc.Two.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue