Merge pull request #10504 from hashicorp/b-no-prune

terraform: don't prune state on init()
This commit is contained in:
Mitchell Hashimoto 2016-12-02 13:13:32 -05:00 committed by GitHub
commit be012a5ebb
4 changed files with 87 additions and 16 deletions

View File

@ -108,6 +108,10 @@ func (s *State) Children(path []string) []*ModuleState {
func (s *State) children(path []string) []*ModuleState {
result := make([]*ModuleState, 0)
for _, m := range s.Modules {
if m == nil {
continue
}
if len(m.Path) != len(path)+1 {
continue
}
@ -161,6 +165,9 @@ func (s *State) ModuleByPath(path []string) *ModuleState {
func (s *State) moduleByPath(path []string) *ModuleState {
for _, mod := range s.Modules {
if mod == nil {
continue
}
if mod.Path == nil {
panic("missing module path")
}
@ -213,6 +220,10 @@ func (s *State) moduleOrphans(path []string, c *config.Config) [][]string {
// Find the orphans that are nested...
for _, m := range s.Modules {
if m == nil {
continue
}
// We only want modules that are at least grandchildren
if len(m.Path) < len(path)+2 {
continue
@ -328,6 +339,10 @@ func (s *State) Validate() error {
{
found := make(map[string]struct{})
for _, ms := range s.Modules {
if ms == nil {
continue
}
key := strings.Join(ms.Path, ".")
if _, ok := found[key]; ok {
result = multierror.Append(result, fmt.Errorf(
@ -644,12 +659,10 @@ func (s *State) init() {
}
s.ensureHasLineage()
// We can't trust that state read from a file doesn't have nil/empty
// modules
s.prune()
for _, mod := range s.Modules {
mod.init()
if mod != nil {
mod.init()
}
}
if s.Remote != nil {
@ -726,7 +739,9 @@ func (s *State) sort() {
// Allow modules to be sorted
for _, m := range s.Modules {
m.sort()
if m != nil {
m.sort()
}
}
}
@ -1810,6 +1825,10 @@ func ReadState(src io.Reader) (*State, error) {
panic("resulting state in load not set, assertion failed")
}
// Prune the state when read it. Its possible to write unpruned states or
// for a user to make a state unpruned (nil-ing a module state for example).
result.prune()
// Validate the state file is valid
if err := result.Validate(); err != nil {
return nil, err
@ -1968,6 +1987,11 @@ func (s moduleStateSort) Less(i, j int) bool {
a := s[i]
b := s[j]
// If either is nil, then the nil one is "less" than
if a == nil || b == nil {
return a == nil
}
// If the lengths are different, then the shorter one always wins
if len(a.Path) != len(b.Path) {
return len(a.Path) < len(b.Path)

View File

@ -1695,16 +1695,34 @@ func TestStateModuleOrphans_empty(t *testing.T) {
// just calling this to check for panic
state.ModuleOrphans(RootModulePath, nil)
}
for _, mod := range state.Modules {
if mod == nil {
t.Fatal("found nil module")
}
if mod.Path == nil {
t.Fatal("found nil module path")
}
if len(mod.Path) == 0 {
t.Fatal("found empty module path")
}
func TestReadState_prune(t *testing.T) {
state := &State{
Modules: []*ModuleState{
&ModuleState{Path: rootModulePath},
nil,
},
}
state.init()
buf := new(bytes.Buffer)
if err := WriteState(state, buf); err != nil {
t.Fatalf("err: %s", err)
}
actual, err := ReadState(buf)
if err != nil {
t.Fatalf("err: %s", err)
}
expected := &State{
Version: state.Version,
Lineage: state.Lineage,
}
expected.init()
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("got:\n%#v", actual)
}
}

View File

@ -42,6 +42,10 @@ func (t *OrphanResourceTransformer) Transform(g *Graph) error {
}
func (t *OrphanResourceTransformer) transform(g *Graph, ms *ModuleState) error {
if ms == nil {
return nil
}
// Get the configuration for this path. The configuration might be
// nil if the module was removed from the configuration. This is okay,
// this just means that every resource is an orphan.

View File

@ -59,6 +59,31 @@ func TestOrphanResourceTransformer(t *testing.T) {
}
}
func TestOrphanResourceTransformer_nilModule(t *testing.T) {
mod := testModule(t, "transform-orphan-basic")
state := &State{
Modules: []*ModuleState{nil},
}
g := Graph{Path: RootModulePath}
{
tf := &ConfigTransformer{Module: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
{
tf := &OrphanResourceTransformer{
Concrete: testOrphanResourceConcreteFunc,
State: state, Module: mod,
}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
}
func TestOrphanResourceTransformer_countGood(t *testing.T) {
mod := testModule(t, "transform-orphan-count")
state := &State{