func (s *State) Validate() error {
	s.Lock()
	defer s.Unlock()
	var result 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(
					strings.TrimSpace(stateValidateErrMultiModule), key))
				continue
			}
			found[key] = struct{}{}
		}
	}
	return result
}
Validate validates the integrity of this state file.

Certain properties of the statefile are expected by Terraform in order
to behave properly. The core of Terraform will assume that once it
receives a State structure that it has been validated. This validation
check should be called to ensure that.

If this returns an error, then the user should be notified. The error
response will include detailed information on the nature of the error.
package terraform
import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"reflect"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"
	"github.com/hashicorp/go-multierror"
	"github.com/hashicorp/go-version"
	"github.com/hashicorp/terraform/config"
	"github.com/mitchellh/copystructure"
	"github.com/satori/go.uuid"
)
const (
	StateVersion = 3
)
var rootModulePath = []string{"root"}
func normalizeModulePath(p []string) []string {
	k := len(rootModulePath)
	if len(p) >= len(rootModulePath) {
		if reflect.DeepEqual(p[:k], rootModulePath) {
			return p
		}
	}
	result := make([]string, len(rootModulePath)+len(p))
	copy(result, rootModulePath)
	copy(result[k:], p)
	return result
}
type State struct {
	Version int `json:"version"`
	TFVersion string `json:"terraform_version,omitempty"`
	Serial int64 `json:"serial"`
	Lineage string `json:"lineage"`
	Remote *RemoteState `json:"remote,omitempty"`
	Backend *BackendState `json:"backend,omitempty"`
	Modules []*ModuleState `json:"modules"`
	mu sync.Mutex
}
func (s *State) Lock()   { s.mu.Lock() }
func (s *State) Unlock() { s.mu.Unlock() }
func NewState() *State {
	s := &State{}
	s.init()
	return s
}
func (s *State) Children(path []string) []*ModuleState {
	s.Lock()
	defer s.Unlock()
	return s.children(path)
}
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
		}
		if !reflect.DeepEqual(path, m.Path[:len(path)]) {
			continue
		}
		result = append(result, m)
	}
	return result
}
func (s *State) AddModule(path []string) *ModuleState {
	s.Lock()
	defer s.Unlock()
	return s.addModule(path)
}
func (s *State) addModule(path []string) *ModuleState {
	m := s.moduleByPath(path)
	if m != nil {
		return m
	}
	m = &ModuleState{Path: path}
	m.init()
	s.Modules = append(s.Modules, m)
	s.sort()
	return m
}
func (s *State) ModuleByPath(path []string) *ModuleState {
	if s == nil {
		return nil
	}
	s.Lock()
	defer s.Unlock()
	return s.moduleByPath(path)
}
func (s *State) moduleByPath(path []string) *ModuleState {
	for _, mod := range s.Modules {
		if mod == nil {
			continue
		}
		if mod.Path == nil {
			panic("missing module path")
		}
		if reflect.DeepEqual(mod.Path, path) {
			return mod
		}
	}
	return nil
}
func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string {
	s.Lock()
	defer s.Unlock()
	return s.moduleOrphans(path, c)
}
func (s *State) moduleOrphans(path []string, c *config.Config) [][]string {
	direct := make(map[string]struct{})
	childrenKeys := make(map[string]struct{})
	if c != nil {
		for _, m := range c.Modules {
			childrenKeys[m.Name] = struct{}{}
			direct[m.Name] = struct{}{}
		}
	}
	var orphans [][]string
	for _, m := range s.children(path) {
		key := m.Path[len(m.Path)-1]
		direct[key] = struct{}{}
		if _, ok := childrenKeys[key]; ok {
			continue
		}
		orphans = append(orphans, m.Path)
	}
	for _, m := range s.Modules {
		if m == nil {
			continue
		}
		if len(m.Path) < len(path)+2 {
			continue
		}
		if !reflect.DeepEqual(path, m.Path[:len(path)]) {
			continue
		}
		key := m.Path[len(path)]
		if _, ok := direct[key]; ok {
			continue
		}
		orphanPath := m.Path[:len(path)+1]
		alreadyAdded := false
		for _, o := range orphans {
			if reflect.DeepEqual(o, orphanPath) {
				alreadyAdded = true
				break
			}
		}
		if alreadyAdded {
			continue
		}
		orphans = append(orphans, orphanPath)
	}
	return orphans
}
func (s *State) Empty() bool {
	if s == nil {
		return true
	}
	s.Lock()
	defer s.Unlock()
	return len(s.Modules) == 0
}
func (s *State) HasResources() bool {
	if s.Empty() {
		return false
	}
	for _, mod := range s.Modules {
		if len(mod.Resources) > 0 {
			return true
		}
	}
	return false
}
func (s *State) IsRemote() bool {
	if s == nil {
		return false
	}
	s.Lock()
	defer s.Unlock()
	if s.Remote == nil {
		return false
	}
	if s.Remote.Type == "" {
		return false
	}
	return true
}