Merge pull request #10504 from hashicorp/b-no-prune
terraform: don't prune state on init()
This commit is contained in:
commit
be012a5ebb
|
@ -108,6 +108,10 @@ func (s *State) Children(path []string) []*ModuleState {
|
||||||
func (s *State) children(path []string) []*ModuleState {
|
func (s *State) children(path []string) []*ModuleState {
|
||||||
result := make([]*ModuleState, 0)
|
result := make([]*ModuleState, 0)
|
||||||
for _, m := range s.Modules {
|
for _, m := range s.Modules {
|
||||||
|
if m == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if len(m.Path) != len(path)+1 {
|
if len(m.Path) != len(path)+1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -161,6 +165,9 @@ func (s *State) ModuleByPath(path []string) *ModuleState {
|
||||||
|
|
||||||
func (s *State) moduleByPath(path []string) *ModuleState {
|
func (s *State) moduleByPath(path []string) *ModuleState {
|
||||||
for _, mod := range s.Modules {
|
for _, mod := range s.Modules {
|
||||||
|
if mod == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if mod.Path == nil {
|
if mod.Path == nil {
|
||||||
panic("missing module path")
|
panic("missing module path")
|
||||||
}
|
}
|
||||||
|
@ -213,6 +220,10 @@ func (s *State) moduleOrphans(path []string, c *config.Config) [][]string {
|
||||||
|
|
||||||
// Find the orphans that are nested...
|
// Find the orphans that are nested...
|
||||||
for _, m := range s.Modules {
|
for _, m := range s.Modules {
|
||||||
|
if m == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// We only want modules that are at least grandchildren
|
// We only want modules that are at least grandchildren
|
||||||
if len(m.Path) < len(path)+2 {
|
if len(m.Path) < len(path)+2 {
|
||||||
continue
|
continue
|
||||||
|
@ -328,6 +339,10 @@ func (s *State) Validate() error {
|
||||||
{
|
{
|
||||||
found := make(map[string]struct{})
|
found := make(map[string]struct{})
|
||||||
for _, ms := range s.Modules {
|
for _, ms := range s.Modules {
|
||||||
|
if ms == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
key := strings.Join(ms.Path, ".")
|
key := strings.Join(ms.Path, ".")
|
||||||
if _, ok := found[key]; ok {
|
if _, ok := found[key]; ok {
|
||||||
result = multierror.Append(result, fmt.Errorf(
|
result = multierror.Append(result, fmt.Errorf(
|
||||||
|
@ -644,13 +659,11 @@ func (s *State) init() {
|
||||||
}
|
}
|
||||||
s.ensureHasLineage()
|
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 {
|
for _, mod := range s.Modules {
|
||||||
|
if mod != nil {
|
||||||
mod.init()
|
mod.init()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if s.Remote != nil {
|
if s.Remote != nil {
|
||||||
s.Remote.init()
|
s.Remote.init()
|
||||||
|
@ -726,9 +739,11 @@ func (s *State) sort() {
|
||||||
|
|
||||||
// Allow modules to be sorted
|
// Allow modules to be sorted
|
||||||
for _, m := range s.Modules {
|
for _, m := range s.Modules {
|
||||||
|
if m != nil {
|
||||||
m.sort()
|
m.sort()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *State) String() string {
|
func (s *State) String() string {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
|
@ -1810,6 +1825,10 @@ func ReadState(src io.Reader) (*State, error) {
|
||||||
panic("resulting state in load not set, assertion failed")
|
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
|
// Validate the state file is valid
|
||||||
if err := result.Validate(); err != nil {
|
if err := result.Validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1968,6 +1987,11 @@ func (s moduleStateSort) Less(i, j int) bool {
|
||||||
a := s[i]
|
a := s[i]
|
||||||
b := s[j]
|
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 the lengths are different, then the shorter one always wins
|
||||||
if len(a.Path) != len(b.Path) {
|
if len(a.Path) != len(b.Path) {
|
||||||
return len(a.Path) < len(b.Path)
|
return len(a.Path) < len(b.Path)
|
||||||
|
|
|
@ -1695,16 +1695,34 @@ func TestStateModuleOrphans_empty(t *testing.T) {
|
||||||
|
|
||||||
// just calling this to check for panic
|
// just calling this to check for panic
|
||||||
state.ModuleOrphans(RootModulePath, nil)
|
state.ModuleOrphans(RootModulePath, nil)
|
||||||
|
}
|
||||||
|
|
||||||
for _, mod := range state.Modules {
|
func TestReadState_prune(t *testing.T) {
|
||||||
if mod == nil {
|
state := &State{
|
||||||
t.Fatal("found nil module")
|
Modules: []*ModuleState{
|
||||||
|
&ModuleState{Path: rootModulePath},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if mod.Path == nil {
|
state.init()
|
||||||
t.Fatal("found nil module path")
|
|
||||||
}
|
buf := new(bytes.Buffer)
|
||||||
if len(mod.Path) == 0 {
|
if err := WriteState(state, buf); err != nil {
|
||||||
t.Fatal("found empty module path")
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,10 @@ func (t *OrphanResourceTransformer) Transform(g *Graph) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *OrphanResourceTransformer) transform(g *Graph, ms *ModuleState) 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
|
// Get the configuration for this path. The configuration might be
|
||||||
// nil if the module was removed from the configuration. This is okay,
|
// nil if the module was removed from the configuration. This is okay,
|
||||||
// this just means that every resource is an orphan.
|
// this just means that every resource is an orphan.
|
||||||
|
|
|
@ -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) {
|
func TestOrphanResourceTransformer_countGood(t *testing.T) {
|
||||||
mod := testModule(t, "transform-orphan-count")
|
mod := testModule(t, "transform-orphan-count")
|
||||||
state := &State{
|
state := &State{
|
||||||
|
|
Loading…
Reference in New Issue