github.com/jrasell/terraform@v0.6.17-0.20160523115548-2652f5232949/terraform/state.go (about)

     1  package terraform
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"reflect"
    11  	"sort"
    12  	"strconv"
    13  	"strings"
    14  
    15  	"github.com/hashicorp/go-version"
    16  	"github.com/hashicorp/terraform/config"
    17  	"github.com/mitchellh/copystructure"
    18  )
    19  
    20  const (
    21  	// StateVersion is the current version for our state file
    22  	StateVersion = 2
    23  )
    24  
    25  // rootModulePath is the path of the root module
    26  var rootModulePath = []string{"root"}
    27  
    28  // normalizeModulePath takes a raw module path and returns a path that
    29  // has the rootModulePath prepended to it. If I could go back in time I
    30  // would've never had a rootModulePath (empty path would be root). We can
    31  // still fix this but thats a big refactor that my branch doesn't make sense
    32  // for. Instead, this function normalizes paths.
    33  func normalizeModulePath(p []string) []string {
    34  	k := len(rootModulePath)
    35  
    36  	// If we already have a root module prefix, we're done
    37  	if len(p) >= len(rootModulePath) {
    38  		if reflect.DeepEqual(p[:k], rootModulePath) {
    39  			return p
    40  		}
    41  	}
    42  
    43  	// None? Prefix it
    44  	result := make([]string, len(rootModulePath)+len(p))
    45  	copy(result, rootModulePath)
    46  	copy(result[k:], p)
    47  	return result
    48  }
    49  
    50  // State keeps track of a snapshot state-of-the-world that Terraform
    51  // can use to keep track of what real world resources it is actually
    52  // managing. This is the latest format as of Terraform 0.3
    53  type State struct {
    54  	// Version is the protocol version. Currently only "1".
    55  	Version int `json:"version"`
    56  
    57  	// TFVersion is the version of Terraform that wrote this state.
    58  	TFVersion string `json:"terraform_version,omitempty"`
    59  
    60  	// Serial is incremented on any operation that modifies
    61  	// the State file. It is used to detect potentially conflicting
    62  	// updates.
    63  	Serial int64 `json:"serial"`
    64  
    65  	// Remote is used to track the metadata required to
    66  	// pull and push state files from a remote storage endpoint.
    67  	Remote *RemoteState `json:"remote,omitempty"`
    68  
    69  	// Modules contains all the modules in a breadth-first order
    70  	Modules []*ModuleState `json:"modules"`
    71  }
    72  
    73  // NewState is used to initialize a blank state
    74  func NewState() *State {
    75  	s := &State{}
    76  	s.init()
    77  	return s
    78  }
    79  
    80  // Children returns the ModuleStates that are direct children of
    81  // the given path. If the path is "root", for example, then children
    82  // returned might be "root.child", but not "root.child.grandchild".
    83  func (s *State) Children(path []string) []*ModuleState {
    84  	// TODO: test
    85  
    86  	result := make([]*ModuleState, 0)
    87  	for _, m := range s.Modules {
    88  		if len(m.Path) != len(path)+1 {
    89  			continue
    90  		}
    91  		if !reflect.DeepEqual(path, m.Path[:len(path)]) {
    92  			continue
    93  		}
    94  
    95  		result = append(result, m)
    96  	}
    97  
    98  	return result
    99  }
   100  
   101  // AddModule adds the module with the given path to the state.
   102  //
   103  // This should be the preferred method to add module states since it
   104  // allows us to optimize lookups later as well as control sorting.
   105  func (s *State) AddModule(path []string) *ModuleState {
   106  	m := &ModuleState{Path: path}
   107  	m.init()
   108  	s.Modules = append(s.Modules, m)
   109  	s.sort()
   110  	return m
   111  }
   112  
   113  // ModuleByPath is used to lookup the module state for the given path.
   114  // This should be the preferred lookup mechanism as it allows for future
   115  // lookup optimizations.
   116  func (s *State) ModuleByPath(path []string) *ModuleState {
   117  	if s == nil {
   118  		return nil
   119  	}
   120  	for _, mod := range s.Modules {
   121  		if mod.Path == nil {
   122  			panic("missing module path")
   123  		}
   124  		if reflect.DeepEqual(mod.Path, path) {
   125  			return mod
   126  		}
   127  	}
   128  	return nil
   129  }
   130  
   131  // ModuleOrphans returns all the module orphans in this state by
   132  // returning their full paths. These paths can be used with ModuleByPath
   133  // to return the actual state.
   134  func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string {
   135  	// direct keeps track of what direct children we have both in our config
   136  	// and in our state. childrenKeys keeps track of what isn't an orphan.
   137  	direct := make(map[string]struct{})
   138  	childrenKeys := make(map[string]struct{})
   139  	if c != nil {
   140  		for _, m := range c.Modules {
   141  			childrenKeys[m.Name] = struct{}{}
   142  			direct[m.Name] = struct{}{}
   143  		}
   144  	}
   145  
   146  	// Go over the direct children and find any that aren't in our keys.
   147  	var orphans [][]string
   148  	for _, m := range s.Children(path) {
   149  		key := m.Path[len(m.Path)-1]
   150  
   151  		// Record that we found this key as a direct child. We use this
   152  		// later to find orphan nested modules.
   153  		direct[key] = struct{}{}
   154  
   155  		// If we have a direct child still in our config, it is not an orphan
   156  		if _, ok := childrenKeys[key]; ok {
   157  			continue
   158  		}
   159  
   160  		orphans = append(orphans, m.Path)
   161  	}
   162  
   163  	// Find the orphans that are nested...
   164  	for _, m := range s.Modules {
   165  		// We only want modules that are at least grandchildren
   166  		if len(m.Path) < len(path)+2 {
   167  			continue
   168  		}
   169  
   170  		// If it isn't part of our tree, continue
   171  		if !reflect.DeepEqual(path, m.Path[:len(path)]) {
   172  			continue
   173  		}
   174  
   175  		// If we have the direct child, then just skip it.
   176  		key := m.Path[len(path)]
   177  		if _, ok := direct[key]; ok {
   178  			continue
   179  		}
   180  
   181  		orphanPath := m.Path[:len(path)+1]
   182  
   183  		// Don't double-add if we've already added this orphan (which can happen if
   184  		// there are multiple nested sub-modules that get orphaned together).
   185  		alreadyAdded := false
   186  		for _, o := range orphans {
   187  			if reflect.DeepEqual(o, orphanPath) {
   188  				alreadyAdded = true
   189  				break
   190  			}
   191  		}
   192  		if alreadyAdded {
   193  			continue
   194  		}
   195  
   196  		// Add this orphan
   197  		orphans = append(orphans, orphanPath)
   198  	}
   199  
   200  	return orphans
   201  }
   202  
   203  // Empty returns true if the state is empty.
   204  func (s *State) Empty() bool {
   205  	if s == nil {
   206  		return true
   207  	}
   208  
   209  	return len(s.Modules) == 0
   210  }
   211  
   212  // IsRemote returns true if State represents a state that exists and is
   213  // remote.
   214  func (s *State) IsRemote() bool {
   215  	if s == nil {
   216  		return false
   217  	}
   218  	if s.Remote == nil {
   219  		return false
   220  	}
   221  	if s.Remote.Type == "" {
   222  		return false
   223  	}
   224  
   225  	return true
   226  }
   227  
   228  // Remove removes the item in the state at the given address, returning
   229  // any errors that may have occurred.
   230  //
   231  // If the address references a module state or resource, it will delete
   232  // all children as well. To check what will be deleted, use a StateFilter
   233  // first.
   234  func (s *State) Remove(addr ...string) error {
   235  	// Filter out what we need to delete
   236  	filter := &StateFilter{State: s}
   237  	results, err := filter.Filter(addr...)
   238  	if err != nil {
   239  		return err
   240  	}
   241  
   242  	// If we have no results, just exit early, we're not going to do anything.
   243  	// While what happens below is fairly fast, this is an important early
   244  	// exit since the prune below might modify the state more and we don't
   245  	// want to modify the state if we don't have to.
   246  	if len(results) == 0 {
   247  		return nil
   248  	}
   249  
   250  	// Go through each result and grab what we need
   251  	removed := make(map[interface{}]struct{})
   252  	for _, r := range results {
   253  		// Convert the path to our own type
   254  		path := append([]string{"root"}, r.Path...)
   255  
   256  		// If we removed this already, then ignore
   257  		if _, ok := removed[r.Value]; ok {
   258  			continue
   259  		}
   260  
   261  		// If we removed the parent already, then ignore
   262  		if r.Parent != nil {
   263  			if _, ok := removed[r.Parent.Value]; ok {
   264  				continue
   265  			}
   266  		}
   267  
   268  		// Add this to the removed list
   269  		removed[r.Value] = struct{}{}
   270  
   271  		switch v := r.Value.(type) {
   272  		case *ModuleState:
   273  			s.removeModule(path, v)
   274  		case *ResourceState:
   275  			s.removeResource(path, v)
   276  		case *InstanceState:
   277  			s.removeInstance(path, r.Parent.Value.(*ResourceState), v)
   278  		default:
   279  			return fmt.Errorf("unknown type to delete: %T", r.Value)
   280  		}
   281  	}
   282  
   283  	// Prune since the removal functions often do the bare minimum to
   284  	// remove a thing and may leave around dangling empty modules, resources,
   285  	// etc. Prune will clean that all up.
   286  	s.prune()
   287  
   288  	return nil
   289  }
   290  
   291  func (s *State) removeModule(path []string, v *ModuleState) {
   292  	for i, m := range s.Modules {
   293  		if m == v {
   294  			s.Modules, s.Modules[len(s.Modules)-1] = append(s.Modules[:i], s.Modules[i+1:]...), nil
   295  			return
   296  		}
   297  	}
   298  }
   299  
   300  func (s *State) removeResource(path []string, v *ResourceState) {
   301  	// Get the module this resource lives in. If it doesn't exist, we're done.
   302  	mod := s.ModuleByPath(path)
   303  	if mod == nil {
   304  		return
   305  	}
   306  
   307  	// Find this resource. This is a O(N) lookup when if we had the key
   308  	// it could be O(1) but even with thousands of resources this shouldn't
   309  	// matter right now. We can easily up performance here when the time comes.
   310  	for k, r := range mod.Resources {
   311  		if r == v {
   312  			// Found it
   313  			delete(mod.Resources, k)
   314  			return
   315  		}
   316  	}
   317  }
   318  
   319  func (s *State) removeInstance(path []string, r *ResourceState, v *InstanceState) {
   320  	// Go through the resource and find the instance that matches this
   321  	// (if any) and remove it.
   322  
   323  	// Check primary
   324  	if r.Primary == v {
   325  		r.Primary = nil
   326  		return
   327  	}
   328  
   329  	// Check lists
   330  	lists := [][]*InstanceState{r.Tainted, r.Deposed}
   331  	for _, is := range lists {
   332  		for i, instance := range is {
   333  			if instance == v {
   334  				// Found it, remove it
   335  				is, is[len(is)-1] = append(is[:i], is[i+1:]...), nil
   336  
   337  				// Done
   338  				return
   339  			}
   340  		}
   341  	}
   342  }
   343  
   344  // RootModule returns the ModuleState for the root module
   345  func (s *State) RootModule() *ModuleState {
   346  	root := s.ModuleByPath(rootModulePath)
   347  	if root == nil {
   348  		panic("missing root module")
   349  	}
   350  	return root
   351  }
   352  
   353  // Equal tests if one state is equal to another.
   354  func (s *State) Equal(other *State) bool {
   355  	// If one is nil, we do a direct check
   356  	if s == nil || other == nil {
   357  		return s == other
   358  	}
   359  
   360  	// If the versions are different, they're certainly not equal
   361  	if s.Version != other.Version {
   362  		return false
   363  	}
   364  
   365  	// If any of the modules are not equal, then this state isn't equal
   366  	if len(s.Modules) != len(other.Modules) {
   367  		return false
   368  	}
   369  	for _, m := range s.Modules {
   370  		// This isn't very optimal currently but works.
   371  		otherM := other.ModuleByPath(m.Path)
   372  		if otherM == nil {
   373  			return false
   374  		}
   375  
   376  		// If they're not equal, then we're not equal!
   377  		if !m.Equal(otherM) {
   378  			return false
   379  		}
   380  	}
   381  
   382  	return true
   383  }
   384  
   385  // DeepCopy performs a deep copy of the state structure and returns
   386  // a new structure.
   387  func (s *State) DeepCopy() *State {
   388  	if s == nil {
   389  		return nil
   390  	}
   391  	n := &State{
   392  		Version:   s.Version,
   393  		TFVersion: s.TFVersion,
   394  		Serial:    s.Serial,
   395  		Modules:   make([]*ModuleState, 0, len(s.Modules)),
   396  	}
   397  	for _, mod := range s.Modules {
   398  		n.Modules = append(n.Modules, mod.deepcopy())
   399  	}
   400  	if s.Remote != nil {
   401  		n.Remote = s.Remote.deepcopy()
   402  	}
   403  	return n
   404  }
   405  
   406  // IncrementSerialMaybe increments the serial number of this state
   407  // if it different from the other state.
   408  func (s *State) IncrementSerialMaybe(other *State) {
   409  	if s == nil {
   410  		return
   411  	}
   412  	if other == nil {
   413  		return
   414  	}
   415  	if s.Serial > other.Serial {
   416  		return
   417  	}
   418  	if other.TFVersion != s.TFVersion || !s.Equal(other) {
   419  		if other.Serial > s.Serial {
   420  			s.Serial = other.Serial
   421  		}
   422  
   423  		s.Serial++
   424  	}
   425  }
   426  
   427  // FromFutureTerraform checks if this state was written by a Terraform
   428  // version from the future.
   429  func (s *State) FromFutureTerraform() bool {
   430  	// No TF version means it is certainly from the past
   431  	if s.TFVersion == "" {
   432  		return false
   433  	}
   434  
   435  	v := version.Must(version.NewVersion(s.TFVersion))
   436  	return SemVersion.LessThan(v)
   437  }
   438  
   439  func (s *State) init() {
   440  	if s.Version == 0 {
   441  		s.Version = StateVersion
   442  	}
   443  	if s.ModuleByPath(rootModulePath) == nil {
   444  		s.AddModule(rootModulePath)
   445  	}
   446  }
   447  
   448  // prune is used to remove any resources that are no longer required
   449  func (s *State) prune() {
   450  	if s == nil {
   451  		return
   452  	}
   453  	for _, mod := range s.Modules {
   454  		mod.prune()
   455  	}
   456  	if s.Remote != nil && s.Remote.Empty() {
   457  		s.Remote = nil
   458  	}
   459  }
   460  
   461  // sort sorts the modules
   462  func (s *State) sort() {
   463  	sort.Sort(moduleStateSort(s.Modules))
   464  
   465  	// Allow modules to be sorted
   466  	for _, m := range s.Modules {
   467  		m.sort()
   468  	}
   469  }
   470  
   471  func (s *State) GoString() string {
   472  	return fmt.Sprintf("*%#v", *s)
   473  }
   474  
   475  func (s *State) String() string {
   476  	if s == nil {
   477  		return "<nil>"
   478  	}
   479  
   480  	var buf bytes.Buffer
   481  	for _, m := range s.Modules {
   482  		mStr := m.String()
   483  
   484  		// If we're the root module, we just write the output directly.
   485  		if reflect.DeepEqual(m.Path, rootModulePath) {
   486  			buf.WriteString(mStr + "\n")
   487  			continue
   488  		}
   489  
   490  		buf.WriteString(fmt.Sprintf("module.%s:\n", strings.Join(m.Path[1:], ".")))
   491  
   492  		s := bufio.NewScanner(strings.NewReader(mStr))
   493  		for s.Scan() {
   494  			text := s.Text()
   495  			if text != "" {
   496  				text = "  " + text
   497  			}
   498  
   499  			buf.WriteString(fmt.Sprintf("%s\n", text))
   500  		}
   501  	}
   502  
   503  	return strings.TrimSpace(buf.String())
   504  }
   505  
   506  // RemoteState is used to track the information about a remote
   507  // state store that we push/pull state to.
   508  type RemoteState struct {
   509  	// Type controls the client we use for the remote state
   510  	Type string `json:"type"`
   511  
   512  	// Config is used to store arbitrary configuration that
   513  	// is type specific
   514  	Config map[string]string `json:"config"`
   515  }
   516  
   517  func (r *RemoteState) deepcopy() *RemoteState {
   518  	confCopy := make(map[string]string, len(r.Config))
   519  	for k, v := range r.Config {
   520  		confCopy[k] = v
   521  	}
   522  	return &RemoteState{
   523  		Type:   r.Type,
   524  		Config: confCopy,
   525  	}
   526  }
   527  
   528  func (r *RemoteState) Empty() bool {
   529  	return r == nil || r.Type == ""
   530  }
   531  
   532  func (r *RemoteState) Equals(other *RemoteState) bool {
   533  	if r.Type != other.Type {
   534  		return false
   535  	}
   536  	if len(r.Config) != len(other.Config) {
   537  		return false
   538  	}
   539  	for k, v := range r.Config {
   540  		if other.Config[k] != v {
   541  			return false
   542  		}
   543  	}
   544  	return true
   545  }
   546  
   547  func (r *RemoteState) GoString() string {
   548  	return fmt.Sprintf("*%#v", *r)
   549  }
   550  
   551  // OutputState is used to track the state relevant to a single output.
   552  type OutputState struct {
   553  	// Sensitive describes whether the output is considered sensitive,
   554  	// which may lead to masking the value on screen in some cases.
   555  	Sensitive bool `json:"sensitive"`
   556  	// Type describes the structure of Value. Valid values are "string",
   557  	// "map" and "list"
   558  	Type string `json:"type"`
   559  	// Value contains the value of the output, in the structure described
   560  	// by the Type field.
   561  	Value interface{} `json:"value"`
   562  }
   563  
   564  func (s *OutputState) String() string {
   565  	// This is a v0.6.x implementation only
   566  	return fmt.Sprintf("%s", s.Value.(string))
   567  }
   568  
   569  // Equal compares two OutputState structures for equality. nil values are
   570  // considered equal.
   571  func (s *OutputState) Equal(other *OutputState) bool {
   572  	if s == nil && other == nil {
   573  		return true
   574  	}
   575  
   576  	if s == nil || other == nil {
   577  		return false
   578  	}
   579  
   580  	if s.Type != other.Type {
   581  		return false
   582  	}
   583  
   584  	if s.Sensitive != other.Sensitive {
   585  		return false
   586  	}
   587  
   588  	if !reflect.DeepEqual(s.Value, other.Value) {
   589  		return false
   590  	}
   591  
   592  	return true
   593  }
   594  
   595  func (s *OutputState) deepcopy() *OutputState {
   596  	if s == nil {
   597  		return nil
   598  	}
   599  
   600  	valueCopy, err := copystructure.Copy(s.Value)
   601  	if err != nil {
   602  		panic(fmt.Errorf("Error copying output value: %s", err))
   603  	}
   604  
   605  	n := &OutputState{
   606  		Type:      s.Type,
   607  		Sensitive: s.Sensitive,
   608  		Value:     valueCopy,
   609  	}
   610  
   611  	return n
   612  }
   613  
   614  // ModuleState is used to track all the state relevant to a single
   615  // module. Previous to Terraform 0.3, all state belonged to the "root"
   616  // module.
   617  type ModuleState struct {
   618  	// Path is the import path from the root module. Modules imports are
   619  	// always disjoint, so the path represents amodule tree
   620  	Path []string `json:"path"`
   621  
   622  	// Outputs declared by the module and maintained for each module
   623  	// even though only the root module technically needs to be kept.
   624  	// This allows operators to inspect values at the boundaries.
   625  	Outputs map[string]*OutputState `json:"outputs"`
   626  
   627  	// Resources is a mapping of the logically named resource to
   628  	// the state of the resource. Each resource may actually have
   629  	// N instances underneath, although a user only needs to think
   630  	// about the 1:1 case.
   631  	Resources map[string]*ResourceState `json:"resources"`
   632  
   633  	// Dependencies are a list of things that this module relies on
   634  	// existing to remain intact. For example: an module may depend
   635  	// on a VPC ID given by an aws_vpc resource.
   636  	//
   637  	// Terraform uses this information to build valid destruction
   638  	// orders and to warn the user if they're destroying a module that
   639  	// another resource depends on.
   640  	//
   641  	// Things can be put into this list that may not be managed by
   642  	// Terraform. If Terraform doesn't find a matching ID in the
   643  	// overall state, then it assumes it isn't managed and doesn't
   644  	// worry about it.
   645  	Dependencies []string `json:"depends_on,omitempty"`
   646  }
   647  
   648  // Equal tests whether one module state is equal to another.
   649  func (m *ModuleState) Equal(other *ModuleState) bool {
   650  	// Paths must be equal
   651  	if !reflect.DeepEqual(m.Path, other.Path) {
   652  		return false
   653  	}
   654  
   655  	// Outputs must be equal
   656  	if len(m.Outputs) != len(other.Outputs) {
   657  		return false
   658  	}
   659  	for k, v := range m.Outputs {
   660  		if !other.Outputs[k].Equal(v) {
   661  			return false
   662  		}
   663  	}
   664  
   665  	// Dependencies must be equal. This sorts these in place but
   666  	// this shouldn't cause any problems.
   667  	sort.Strings(m.Dependencies)
   668  	sort.Strings(other.Dependencies)
   669  	if len(m.Dependencies) != len(other.Dependencies) {
   670  		return false
   671  	}
   672  	for i, d := range m.Dependencies {
   673  		if other.Dependencies[i] != d {
   674  			return false
   675  		}
   676  	}
   677  
   678  	// Resources must be equal
   679  	if len(m.Resources) != len(other.Resources) {
   680  		return false
   681  	}
   682  	for k, r := range m.Resources {
   683  		otherR, ok := other.Resources[k]
   684  		if !ok {
   685  			return false
   686  		}
   687  
   688  		if !r.Equal(otherR) {
   689  			return false
   690  		}
   691  	}
   692  
   693  	return true
   694  }
   695  
   696  // IsRoot says whether or not this module diff is for the root module.
   697  func (m *ModuleState) IsRoot() bool {
   698  	return reflect.DeepEqual(m.Path, rootModulePath)
   699  }
   700  
   701  // Orphans returns a list of keys of resources that are in the State
   702  // but aren't present in the configuration itself. Hence, these keys
   703  // represent the state of resources that are orphans.
   704  func (m *ModuleState) Orphans(c *config.Config) []string {
   705  	keys := make(map[string]struct{})
   706  	for k, _ := range m.Resources {
   707  		keys[k] = struct{}{}
   708  	}
   709  
   710  	if c != nil {
   711  		for _, r := range c.Resources {
   712  			delete(keys, r.Id())
   713  
   714  			for k, _ := range keys {
   715  				if strings.HasPrefix(k, r.Id()+".") {
   716  					delete(keys, k)
   717  				}
   718  			}
   719  		}
   720  	}
   721  
   722  	result := make([]string, 0, len(keys))
   723  	for k, _ := range keys {
   724  		result = append(result, k)
   725  	}
   726  
   727  	return result
   728  }
   729  
   730  // View returns a view with the given resource prefix.
   731  func (m *ModuleState) View(id string) *ModuleState {
   732  	if m == nil {
   733  		return m
   734  	}
   735  
   736  	r := m.deepcopy()
   737  	for k, _ := range r.Resources {
   738  		if id == k || strings.HasPrefix(k, id+".") {
   739  			continue
   740  		}
   741  
   742  		delete(r.Resources, k)
   743  	}
   744  
   745  	return r
   746  }
   747  
   748  func (m *ModuleState) init() {
   749  	if m.Outputs == nil {
   750  		m.Outputs = make(map[string]*OutputState)
   751  	}
   752  	if m.Resources == nil {
   753  		m.Resources = make(map[string]*ResourceState)
   754  	}
   755  }
   756  
   757  func (m *ModuleState) deepcopy() *ModuleState {
   758  	if m == nil {
   759  		return nil
   760  	}
   761  	n := &ModuleState{
   762  		Path:         make([]string, len(m.Path)),
   763  		Outputs:      make(map[string]*OutputState, len(m.Outputs)),
   764  		Resources:    make(map[string]*ResourceState, len(m.Resources)),
   765  		Dependencies: make([]string, len(m.Dependencies)),
   766  	}
   767  	copy(n.Path, m.Path)
   768  	copy(n.Dependencies, m.Dependencies)
   769  	for k, v := range m.Outputs {
   770  		n.Outputs[k] = v.deepcopy()
   771  	}
   772  	for k, v := range m.Resources {
   773  		n.Resources[k] = v.deepcopy()
   774  	}
   775  	return n
   776  }
   777  
   778  // prune is used to remove any resources that are no longer required
   779  func (m *ModuleState) prune() {
   780  	for k, v := range m.Resources {
   781  		v.prune()
   782  
   783  		if (v.Primary == nil || v.Primary.ID == "") && len(v.Tainted) == 0 && len(v.Deposed) == 0 {
   784  			delete(m.Resources, k)
   785  		}
   786  	}
   787  
   788  	for k, v := range m.Outputs {
   789  		if v.Value == config.UnknownVariableValue {
   790  			delete(m.Outputs, k)
   791  		}
   792  	}
   793  }
   794  
   795  func (m *ModuleState) sort() {
   796  	for _, v := range m.Resources {
   797  		v.sort()
   798  	}
   799  }
   800  
   801  func (m *ModuleState) GoString() string {
   802  	return fmt.Sprintf("*%#v", *m)
   803  }
   804  
   805  func (m *ModuleState) String() string {
   806  	var buf bytes.Buffer
   807  
   808  	if len(m.Resources) == 0 {
   809  		buf.WriteString("<no state>")
   810  	}
   811  
   812  	names := make([]string, 0, len(m.Resources))
   813  	for name, _ := range m.Resources {
   814  		names = append(names, name)
   815  	}
   816  	sort.Strings(names)
   817  
   818  	for _, k := range names {
   819  		rs := m.Resources[k]
   820  		var id string
   821  		if rs.Primary != nil {
   822  			id = rs.Primary.ID
   823  		}
   824  		if id == "" {
   825  			id = "<not created>"
   826  		}
   827  
   828  		taintStr := ""
   829  		if len(rs.Tainted) > 0 {
   830  			taintStr = fmt.Sprintf(" (%d tainted)", len(rs.Tainted))
   831  		}
   832  
   833  		deposedStr := ""
   834  		if len(rs.Deposed) > 0 {
   835  			deposedStr = fmt.Sprintf(" (%d deposed)", len(rs.Deposed))
   836  		}
   837  
   838  		buf.WriteString(fmt.Sprintf("%s:%s%s\n", k, taintStr, deposedStr))
   839  		buf.WriteString(fmt.Sprintf("  ID = %s\n", id))
   840  		if rs.Provider != "" {
   841  			buf.WriteString(fmt.Sprintf("  provider = %s\n", rs.Provider))
   842  		}
   843  
   844  		var attributes map[string]string
   845  		if rs.Primary != nil {
   846  			attributes = rs.Primary.Attributes
   847  		}
   848  		attrKeys := make([]string, 0, len(attributes))
   849  		for ak, _ := range attributes {
   850  			if ak == "id" {
   851  				continue
   852  			}
   853  
   854  			attrKeys = append(attrKeys, ak)
   855  		}
   856  		sort.Strings(attrKeys)
   857  
   858  		for _, ak := range attrKeys {
   859  			av := attributes[ak]
   860  			buf.WriteString(fmt.Sprintf("  %s = %s\n", ak, av))
   861  		}
   862  
   863  		for idx, t := range rs.Tainted {
   864  			buf.WriteString(fmt.Sprintf("  Tainted ID %d = %s\n", idx+1, t.ID))
   865  		}
   866  
   867  		for idx, t := range rs.Deposed {
   868  			buf.WriteString(fmt.Sprintf("  Deposed ID %d = %s\n", idx+1, t.ID))
   869  		}
   870  
   871  		if len(rs.Dependencies) > 0 {
   872  			buf.WriteString(fmt.Sprintf("\n  Dependencies:\n"))
   873  			for _, dep := range rs.Dependencies {
   874  				buf.WriteString(fmt.Sprintf("    %s\n", dep))
   875  			}
   876  		}
   877  	}
   878  
   879  	if len(m.Outputs) > 0 {
   880  		buf.WriteString("\nOutputs:\n\n")
   881  
   882  		ks := make([]string, 0, len(m.Outputs))
   883  		for k, _ := range m.Outputs {
   884  			ks = append(ks, k)
   885  		}
   886  		sort.Strings(ks)
   887  
   888  		for _, k := range ks {
   889  			v := m.Outputs[k]
   890  			switch vTyped := v.Value.(type) {
   891  			case string:
   892  				buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped))
   893  			case []interface{}:
   894  				buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped))
   895  			case map[string]interface{}:
   896  				var mapKeys []string
   897  				for key, _ := range vTyped {
   898  					mapKeys = append(mapKeys, key)
   899  				}
   900  				sort.Strings(mapKeys)
   901  
   902  				var mapBuf bytes.Buffer
   903  				mapBuf.WriteString("{")
   904  				for _, key := range mapKeys {
   905  					mapBuf.WriteString(fmt.Sprintf("%s:%s ", key, vTyped[key]))
   906  				}
   907  				mapBuf.WriteString("}")
   908  
   909  				buf.WriteString(fmt.Sprintf("%s = %s\n", k, mapBuf.String()))
   910  			}
   911  		}
   912  	}
   913  
   914  	return buf.String()
   915  }
   916  
   917  // ResourceStateKey is a structured representation of the key used for the
   918  // ModuleState.Resources mapping
   919  type ResourceStateKey struct {
   920  	Name  string
   921  	Type  string
   922  	Mode  config.ResourceMode
   923  	Index int
   924  }
   925  
   926  // Equal determines whether two ResourceStateKeys are the same
   927  func (rsk *ResourceStateKey) Equal(other *ResourceStateKey) bool {
   928  	if rsk == nil || other == nil {
   929  		return false
   930  	}
   931  	if rsk.Mode != other.Mode {
   932  		return false
   933  	}
   934  	if rsk.Type != other.Type {
   935  		return false
   936  	}
   937  	if rsk.Name != other.Name {
   938  		return false
   939  	}
   940  	if rsk.Index != other.Index {
   941  		return false
   942  	}
   943  	return true
   944  }
   945  
   946  func (rsk *ResourceStateKey) String() string {
   947  	if rsk == nil {
   948  		return ""
   949  	}
   950  	var prefix string
   951  	switch rsk.Mode {
   952  	case config.ManagedResourceMode:
   953  		prefix = ""
   954  	case config.DataResourceMode:
   955  		prefix = "data."
   956  	default:
   957  		panic(fmt.Errorf("unknown resource mode %s", rsk.Mode))
   958  	}
   959  	if rsk.Index == -1 {
   960  		return fmt.Sprintf("%s%s.%s", prefix, rsk.Type, rsk.Name)
   961  	}
   962  	return fmt.Sprintf("%s%s.%s.%d", prefix, rsk.Type, rsk.Name, rsk.Index)
   963  }
   964  
   965  // ParseResourceStateKey accepts a key in the format used by
   966  // ModuleState.Resources and returns a resource name and resource index. In the
   967  // state, a resource has the format "type.name.index" or "type.name". In the
   968  // latter case, the index is returned as -1.
   969  func ParseResourceStateKey(k string) (*ResourceStateKey, error) {
   970  	parts := strings.Split(k, ".")
   971  	mode := config.ManagedResourceMode
   972  	if len(parts) > 0 && parts[0] == "data" {
   973  		mode = config.DataResourceMode
   974  		// Don't need the constant "data" prefix for parsing
   975  		// now that we've figured out the mode.
   976  		parts = parts[1:]
   977  	}
   978  	if len(parts) < 2 || len(parts) > 3 {
   979  		return nil, fmt.Errorf("Malformed resource state key: %s", k)
   980  	}
   981  	rsk := &ResourceStateKey{
   982  		Mode:  mode,
   983  		Type:  parts[0],
   984  		Name:  parts[1],
   985  		Index: -1,
   986  	}
   987  	if len(parts) == 3 {
   988  		index, err := strconv.Atoi(parts[2])
   989  		if err != nil {
   990  			return nil, fmt.Errorf("Malformed resource state key index: %s", k)
   991  		}
   992  		rsk.Index = index
   993  	}
   994  	return rsk, nil
   995  }
   996  
   997  // ResourceState holds the state of a resource that is used so that
   998  // a provider can find and manage an existing resource as well as for
   999  // storing attributes that are used to populate variables of child
  1000  // resources.
  1001  //
  1002  // Attributes has attributes about the created resource that are
  1003  // queryable in interpolation: "${type.id.attr}"
  1004  //
  1005  // Extra is just extra data that a provider can return that we store
  1006  // for later, but is not exposed in any way to the user.
  1007  //
  1008  type ResourceState struct {
  1009  	// This is filled in and managed by Terraform, and is the resource
  1010  	// type itself such as "mycloud_instance". If a resource provider sets
  1011  	// this value, it won't be persisted.
  1012  	Type string `json:"type"`
  1013  
  1014  	// Dependencies are a list of things that this resource relies on
  1015  	// existing to remain intact. For example: an AWS instance might
  1016  	// depend on a subnet (which itself might depend on a VPC, and so
  1017  	// on).
  1018  	//
  1019  	// Terraform uses this information to build valid destruction
  1020  	// orders and to warn the user if they're destroying a resource that
  1021  	// another resource depends on.
  1022  	//
  1023  	// Things can be put into this list that may not be managed by
  1024  	// Terraform. If Terraform doesn't find a matching ID in the
  1025  	// overall state, then it assumes it isn't managed and doesn't
  1026  	// worry about it.
  1027  	Dependencies []string `json:"depends_on,omitempty"`
  1028  
  1029  	// Primary is the current active instance for this resource.
  1030  	// It can be replaced but only after a successful creation.
  1031  	// This is the instances on which providers will act.
  1032  	Primary *InstanceState `json:"primary"`
  1033  
  1034  	// Tainted is used to track any underlying instances that
  1035  	// have been created but are in a bad or unknown state and
  1036  	// need to be cleaned up subsequently.  In the
  1037  	// standard case, there is only at most a single instance.
  1038  	// However, in pathological cases, it is possible for the number
  1039  	// of instances to accumulate.
  1040  	Tainted []*InstanceState `json:"tainted,omitempty"`
  1041  
  1042  	// Deposed is used in the mechanics of CreateBeforeDestroy: the existing
  1043  	// Primary is Deposed to get it out of the way for the replacement Primary to
  1044  	// be created by Apply. If the replacement Primary creates successfully, the
  1045  	// Deposed instance is cleaned up. If there were problems creating the
  1046  	// replacement, the instance remains in the Deposed list so it can be
  1047  	// destroyed in a future run. Functionally, Deposed instances are very
  1048  	// similar to Tainted instances in that Terraform is only tracking them in
  1049  	// order to remember to destroy them.
  1050  	Deposed []*InstanceState `json:"deposed,omitempty"`
  1051  
  1052  	// Provider is used when a resource is connected to a provider with an alias.
  1053  	// If this string is empty, the resource is connected to the default provider,
  1054  	// e.g. "aws_instance" goes with the "aws" provider.
  1055  	// If the resource block contained a "provider" key, that value will be set here.
  1056  	Provider string `json:"provider,omitempty"`
  1057  }
  1058  
  1059  // Equal tests whether two ResourceStates are equal.
  1060  func (s *ResourceState) Equal(other *ResourceState) bool {
  1061  	if s.Type != other.Type {
  1062  		return false
  1063  	}
  1064  
  1065  	if s.Provider != other.Provider {
  1066  		return false
  1067  	}
  1068  
  1069  	// Dependencies must be equal
  1070  	sort.Strings(s.Dependencies)
  1071  	sort.Strings(other.Dependencies)
  1072  	if len(s.Dependencies) != len(other.Dependencies) {
  1073  		return false
  1074  	}
  1075  	for i, d := range s.Dependencies {
  1076  		if other.Dependencies[i] != d {
  1077  			return false
  1078  		}
  1079  	}
  1080  
  1081  	// States must be equal
  1082  	if !s.Primary.Equal(other.Primary) {
  1083  		return false
  1084  	}
  1085  
  1086  	// Tainted
  1087  	taints := make(map[string]*InstanceState)
  1088  	for _, t := range other.Tainted {
  1089  		if t == nil {
  1090  			continue
  1091  		}
  1092  
  1093  		taints[t.ID] = t
  1094  	}
  1095  	for _, t := range s.Tainted {
  1096  		if t == nil {
  1097  			continue
  1098  		}
  1099  
  1100  		otherT, ok := taints[t.ID]
  1101  		if !ok {
  1102  			return false
  1103  		}
  1104  		delete(taints, t.ID)
  1105  
  1106  		if !t.Equal(otherT) {
  1107  			return false
  1108  		}
  1109  	}
  1110  
  1111  	// This means that we have stuff in other tainted that we don't
  1112  	// have, so it is not equal.
  1113  	if len(taints) > 0 {
  1114  		return false
  1115  	}
  1116  
  1117  	return true
  1118  }
  1119  
  1120  // Taint takes the primary state and marks it as tainted. If there is no
  1121  // primary state, this does nothing.
  1122  func (r *ResourceState) Taint() {
  1123  	// If there is no primary, nothing to do
  1124  	if r.Primary == nil {
  1125  		return
  1126  	}
  1127  
  1128  	// Shuffle to the end of the taint list and set primary to nil
  1129  	r.Tainted = append(r.Tainted, r.Primary)
  1130  	r.Primary = nil
  1131  }
  1132  
  1133  // Untaint takes a tainted InstanceState and marks it as primary.
  1134  // The index argument is used to select a single InstanceState from the
  1135  // array of Tainted when there are more than one. If index is -1, the
  1136  // first Tainted InstanceState will be untainted iff there is only one
  1137  // Tainted InstanceState. Index must be >= 0 to specify an InstanceState
  1138  // when Tainted has more than one member.
  1139  func (r *ResourceState) Untaint(index int) error {
  1140  	if len(r.Tainted) == 0 {
  1141  		return fmt.Errorf("Nothing to untaint.")
  1142  	}
  1143  	if r.Primary != nil {
  1144  		return fmt.Errorf("Resource has a primary instance in the state that would be overwritten by untainting. If you want to restore a tainted resource to primary, taint the existing primary instance first.")
  1145  	}
  1146  	if index == -1 && len(r.Tainted) > 1 {
  1147  		return fmt.Errorf("There are %d tainted instances for this resource, please specify an index to select which one to untaint.", len(r.Tainted))
  1148  	}
  1149  	if index == -1 {
  1150  		index = 0
  1151  	}
  1152  	if index >= len(r.Tainted) {
  1153  		return fmt.Errorf("There are %d tainted instances for this resource, the index specified (%d) is out of range.", len(r.Tainted), index)
  1154  	}
  1155  
  1156  	// Perform the untaint
  1157  	r.Primary = r.Tainted[index]
  1158  	r.Tainted = append(r.Tainted[:index], r.Tainted[index+1:]...)
  1159  
  1160  	return nil
  1161  }
  1162  
  1163  func (r *ResourceState) init() {
  1164  	if r.Primary == nil {
  1165  		r.Primary = &InstanceState{}
  1166  	}
  1167  	r.Primary.init()
  1168  }
  1169  
  1170  func (r *ResourceState) deepcopy() *ResourceState {
  1171  	if r == nil {
  1172  		return nil
  1173  	}
  1174  
  1175  	n := &ResourceState{
  1176  		Type:         r.Type,
  1177  		Dependencies: nil,
  1178  		Primary:      r.Primary.DeepCopy(),
  1179  		Tainted:      nil,
  1180  		Provider:     r.Provider,
  1181  	}
  1182  	if r.Dependencies != nil {
  1183  		n.Dependencies = make([]string, len(r.Dependencies))
  1184  		copy(n.Dependencies, r.Dependencies)
  1185  	}
  1186  	if r.Tainted != nil {
  1187  		n.Tainted = make([]*InstanceState, 0, len(r.Tainted))
  1188  		for _, inst := range r.Tainted {
  1189  			n.Tainted = append(n.Tainted, inst.DeepCopy())
  1190  		}
  1191  	}
  1192  	if r.Deposed != nil {
  1193  		n.Deposed = make([]*InstanceState, 0, len(r.Deposed))
  1194  		for _, inst := range r.Deposed {
  1195  			n.Deposed = append(n.Deposed, inst.DeepCopy())
  1196  		}
  1197  	}
  1198  
  1199  	return n
  1200  }
  1201  
  1202  // prune is used to remove any instances that are no longer required
  1203  func (r *ResourceState) prune() {
  1204  	n := len(r.Tainted)
  1205  	for i := 0; i < n; i++ {
  1206  		inst := r.Tainted[i]
  1207  		if inst == nil || inst.ID == "" {
  1208  			copy(r.Tainted[i:], r.Tainted[i+1:])
  1209  			r.Tainted[n-1] = nil
  1210  			n--
  1211  			i--
  1212  		}
  1213  	}
  1214  
  1215  	r.Tainted = r.Tainted[:n]
  1216  
  1217  	n = len(r.Deposed)
  1218  	for i := 0; i < n; i++ {
  1219  		inst := r.Deposed[i]
  1220  		if inst == nil || inst.ID == "" {
  1221  			copy(r.Deposed[i:], r.Deposed[i+1:])
  1222  			r.Deposed[n-1] = nil
  1223  			n--
  1224  			i--
  1225  		}
  1226  	}
  1227  
  1228  	r.Deposed = r.Deposed[:n]
  1229  }
  1230  
  1231  func (r *ResourceState) sort() {
  1232  	sort.Strings(r.Dependencies)
  1233  }
  1234  
  1235  func (s *ResourceState) GoString() string {
  1236  	return fmt.Sprintf("*%#v", *s)
  1237  }
  1238  
  1239  func (s *ResourceState) String() string {
  1240  	var buf bytes.Buffer
  1241  	buf.WriteString(fmt.Sprintf("Type = %s", s.Type))
  1242  	return buf.String()
  1243  }
  1244  
  1245  // InstanceState is used to track the unique state information belonging
  1246  // to a given instance.
  1247  type InstanceState struct {
  1248  	// A unique ID for this resource. This is opaque to Terraform
  1249  	// and is only meant as a lookup mechanism for the providers.
  1250  	ID string `json:"id"`
  1251  
  1252  	// Attributes are basic information about the resource. Any keys here
  1253  	// are accessible in variable format within Terraform configurations:
  1254  	// ${resourcetype.name.attribute}.
  1255  	Attributes map[string]string `json:"attributes,omitempty"`
  1256  
  1257  	// Ephemeral is used to store any state associated with this instance
  1258  	// that is necessary for the Terraform run to complete, but is not
  1259  	// persisted to a state file.
  1260  	Ephemeral EphemeralState `json:"-"`
  1261  
  1262  	// Meta is a simple K/V map that is persisted to the State but otherwise
  1263  	// ignored by Terraform core. It's meant to be used for accounting by
  1264  	// external client code.
  1265  	Meta map[string]string `json:"meta,omitempty"`
  1266  }
  1267  
  1268  func (i *InstanceState) init() {
  1269  	if i.Attributes == nil {
  1270  		i.Attributes = make(map[string]string)
  1271  	}
  1272  	if i.Meta == nil {
  1273  		i.Meta = make(map[string]string)
  1274  	}
  1275  	i.Ephemeral.init()
  1276  }
  1277  
  1278  func (i *InstanceState) DeepCopy() *InstanceState {
  1279  	if i == nil {
  1280  		return nil
  1281  	}
  1282  	n := &InstanceState{
  1283  		ID:        i.ID,
  1284  		Ephemeral: *i.Ephemeral.DeepCopy(),
  1285  	}
  1286  	if i.Attributes != nil {
  1287  		n.Attributes = make(map[string]string, len(i.Attributes))
  1288  		for k, v := range i.Attributes {
  1289  			n.Attributes[k] = v
  1290  		}
  1291  	}
  1292  	if i.Meta != nil {
  1293  		n.Meta = make(map[string]string, len(i.Meta))
  1294  		for k, v := range i.Meta {
  1295  			n.Meta[k] = v
  1296  		}
  1297  	}
  1298  	return n
  1299  }
  1300  
  1301  func (s *InstanceState) Empty() bool {
  1302  	return s == nil || s.ID == ""
  1303  }
  1304  
  1305  func (s *InstanceState) Equal(other *InstanceState) bool {
  1306  	// Short circuit some nil checks
  1307  	if s == nil || other == nil {
  1308  		return s == other
  1309  	}
  1310  
  1311  	// IDs must be equal
  1312  	if s.ID != other.ID {
  1313  		return false
  1314  	}
  1315  
  1316  	// Attributes must be equal
  1317  	if len(s.Attributes) != len(other.Attributes) {
  1318  		return false
  1319  	}
  1320  	for k, v := range s.Attributes {
  1321  		otherV, ok := other.Attributes[k]
  1322  		if !ok {
  1323  			return false
  1324  		}
  1325  
  1326  		if v != otherV {
  1327  			return false
  1328  		}
  1329  	}
  1330  
  1331  	// Meta must be equal
  1332  	if len(s.Meta) != len(other.Meta) {
  1333  		return false
  1334  	}
  1335  	for k, v := range s.Meta {
  1336  		otherV, ok := other.Meta[k]
  1337  		if !ok {
  1338  			return false
  1339  		}
  1340  
  1341  		if v != otherV {
  1342  			return false
  1343  		}
  1344  	}
  1345  
  1346  	return true
  1347  }
  1348  
  1349  // MergeDiff takes a ResourceDiff and merges the attributes into
  1350  // this resource state in order to generate a new state. This new
  1351  // state can be used to provide updated attribute lookups for
  1352  // variable interpolation.
  1353  //
  1354  // If the diff attribute requires computing the value, and hence
  1355  // won't be available until apply, the value is replaced with the
  1356  // computeID.
  1357  func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState {
  1358  	result := s.DeepCopy()
  1359  	if result == nil {
  1360  		result = new(InstanceState)
  1361  	}
  1362  	result.init()
  1363  
  1364  	if s != nil {
  1365  		for k, v := range s.Attributes {
  1366  			result.Attributes[k] = v
  1367  		}
  1368  	}
  1369  	if d != nil {
  1370  		for k, diff := range d.Attributes {
  1371  			if diff.NewRemoved {
  1372  				delete(result.Attributes, k)
  1373  				continue
  1374  			}
  1375  			if diff.NewComputed {
  1376  				result.Attributes[k] = config.UnknownVariableValue
  1377  				continue
  1378  			}
  1379  
  1380  			result.Attributes[k] = diff.New
  1381  		}
  1382  	}
  1383  
  1384  	return result
  1385  }
  1386  
  1387  func (i *InstanceState) GoString() string {
  1388  	return fmt.Sprintf("*%#v", *i)
  1389  }
  1390  
  1391  func (i *InstanceState) String() string {
  1392  	var buf bytes.Buffer
  1393  
  1394  	if i == nil || i.ID == "" {
  1395  		return "<not created>"
  1396  	}
  1397  
  1398  	buf.WriteString(fmt.Sprintf("ID = %s\n", i.ID))
  1399  
  1400  	attributes := i.Attributes
  1401  	attrKeys := make([]string, 0, len(attributes))
  1402  	for ak, _ := range attributes {
  1403  		if ak == "id" {
  1404  			continue
  1405  		}
  1406  
  1407  		attrKeys = append(attrKeys, ak)
  1408  	}
  1409  	sort.Strings(attrKeys)
  1410  
  1411  	for _, ak := range attrKeys {
  1412  		av := attributes[ak]
  1413  		buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av))
  1414  	}
  1415  
  1416  	return buf.String()
  1417  }
  1418  
  1419  // EphemeralState is used for transient state that is only kept in-memory
  1420  type EphemeralState struct {
  1421  	// ConnInfo is used for the providers to export information which is
  1422  	// used to connect to the resource for provisioning. For example,
  1423  	// this could contain SSH or WinRM credentials.
  1424  	ConnInfo map[string]string `json:"-"`
  1425  
  1426  	// Type is used to specify the resource type for this instance. This is only
  1427  	// required for import operations (as documented). If the documentation
  1428  	// doesn't state that you need to set this, then don't worry about
  1429  	// setting it.
  1430  	Type string `json:"-"`
  1431  }
  1432  
  1433  func (e *EphemeralState) init() {
  1434  	if e.ConnInfo == nil {
  1435  		e.ConnInfo = make(map[string]string)
  1436  	}
  1437  }
  1438  
  1439  func (e *EphemeralState) DeepCopy() *EphemeralState {
  1440  	if e == nil {
  1441  		return nil
  1442  	}
  1443  	n := &EphemeralState{}
  1444  	if e.ConnInfo != nil {
  1445  		n.ConnInfo = make(map[string]string, len(e.ConnInfo))
  1446  		for k, v := range e.ConnInfo {
  1447  			n.ConnInfo[k] = v
  1448  		}
  1449  	}
  1450  	return n
  1451  }
  1452  
  1453  type jsonStateVersionIdentifier struct {
  1454  	Version int `json:"version"`
  1455  }
  1456  
  1457  // ReadState reads a state structure out of a reader in the format that
  1458  // was written by WriteState.
  1459  func ReadState(src io.Reader) (*State, error) {
  1460  	buf := bufio.NewReader(src)
  1461  
  1462  	// Check if this is a V0 format
  1463  	start, err := buf.Peek(len(stateFormatMagic))
  1464  	if err != nil {
  1465  		return nil, fmt.Errorf("Failed to check for magic bytes: %v", err)
  1466  	}
  1467  	if string(start) == stateFormatMagic {
  1468  		// Read the old state
  1469  		old, err := ReadStateV0(buf)
  1470  		if err != nil {
  1471  			return nil, err
  1472  		}
  1473  		return old.upgrade()
  1474  	}
  1475  
  1476  	// If we are JSON we buffer the whole thing in memory so we can read it twice.
  1477  	// This is suboptimal, but will work for now.
  1478  	jsonBytes, err := ioutil.ReadAll(buf)
  1479  	if err != nil {
  1480  		return nil, fmt.Errorf("Reading state file failed: %v", err)
  1481  	}
  1482  
  1483  	versionIdentifier := &jsonStateVersionIdentifier{}
  1484  	if err := json.Unmarshal(jsonBytes, versionIdentifier); err != nil {
  1485  		return nil, fmt.Errorf("Decoding state file version failed: %v", err)
  1486  	}
  1487  
  1488  	switch versionIdentifier.Version {
  1489  	case 0:
  1490  		return nil, fmt.Errorf("State version 0 is not supported as JSON.")
  1491  	case 1:
  1492  		old, err := ReadStateV1(jsonBytes)
  1493  		if err != nil {
  1494  			return nil, err
  1495  		}
  1496  		return old.upgrade()
  1497  	case 2:
  1498  		state, err := ReadStateV2(jsonBytes)
  1499  		if err != nil {
  1500  			return nil, err
  1501  		}
  1502  		return state, nil
  1503  	default:
  1504  		return nil, fmt.Errorf("State version %d not supported, please update.",
  1505  			versionIdentifier.Version)
  1506  	}
  1507  }
  1508  
  1509  func ReadStateV1(jsonBytes []byte) (*stateV1, error) {
  1510  	state := &stateV1{}
  1511  	if err := json.Unmarshal(jsonBytes, state); err != nil {
  1512  		return nil, fmt.Errorf("Decoding state file failed: %v", err)
  1513  	}
  1514  
  1515  	if state.Version != 1 {
  1516  		return nil, fmt.Errorf("Decoded state version did not match the decoder selection: "+
  1517  			"read %d, expected 1", state.Version)
  1518  	}
  1519  
  1520  	return state, nil
  1521  }
  1522  
  1523  func ReadStateV2(jsonBytes []byte) (*State, error) {
  1524  	state := &State{}
  1525  	if err := json.Unmarshal(jsonBytes, state); err != nil {
  1526  		return nil, fmt.Errorf("Decoding state file failed: %v", err)
  1527  	}
  1528  
  1529  	// Check the version, this to ensure we don't read a future
  1530  	// version that we don't understand
  1531  	if state.Version > StateVersion {
  1532  		return nil, fmt.Errorf("State version %d not supported, please update.",
  1533  			state.Version)
  1534  	}
  1535  
  1536  	// Make sure the version is semantic
  1537  	if state.TFVersion != "" {
  1538  		if _, err := version.NewVersion(state.TFVersion); err != nil {
  1539  			return nil, fmt.Errorf(
  1540  				"State contains invalid version: %s\n\n"+
  1541  					"Terraform validates the version format prior to writing it. This\n"+
  1542  					"means that this is invalid of the state becoming corrupted through\n"+
  1543  					"some external means. Please manually modify the Terraform version\n"+
  1544  					"field to be a proper semantic version.",
  1545  				state.TFVersion)
  1546  		}
  1547  	}
  1548  
  1549  	// Sort it
  1550  	state.sort()
  1551  
  1552  	return state, nil
  1553  }
  1554  
  1555  // WriteState writes a state somewhere in a binary format.
  1556  func WriteState(d *State, dst io.Writer) error {
  1557  	// Make sure it is sorted
  1558  	d.sort()
  1559  
  1560  	// Ensure the version is set
  1561  	d.Version = StateVersion
  1562  
  1563  	// If the TFVersion is set, verify it. We used to just set the version
  1564  	// here, but this isn't safe since it changes the MD5 sum on some remote
  1565  	// state storage backends such as Atlas. We now leave it be if needed.
  1566  	if d.TFVersion != "" {
  1567  		if _, err := version.NewVersion(d.TFVersion); err != nil {
  1568  			return fmt.Errorf(
  1569  				"Error writing state, invalid version: %s\n\n"+
  1570  					"The Terraform version when writing the state must be a semantic\n"+
  1571  					"version.",
  1572  				d.TFVersion)
  1573  		}
  1574  	}
  1575  
  1576  	// Encode the data in a human-friendly way
  1577  	data, err := json.MarshalIndent(d, "", "    ")
  1578  	if err != nil {
  1579  		return fmt.Errorf("Failed to encode state: %s", err)
  1580  	}
  1581  
  1582  	// We append a newline to the data because MarshalIndent doesn't
  1583  	data = append(data, '\n')
  1584  
  1585  	// Write the data out to the dst
  1586  	if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil {
  1587  		return fmt.Errorf("Failed to write state: %v", err)
  1588  	}
  1589  
  1590  	return nil
  1591  }
  1592  
  1593  // moduleStateSort implements sort.Interface to sort module states
  1594  type moduleStateSort []*ModuleState
  1595  
  1596  func (s moduleStateSort) Len() int {
  1597  	return len(s)
  1598  }
  1599  
  1600  func (s moduleStateSort) Less(i, j int) bool {
  1601  	a := s[i]
  1602  	b := s[j]
  1603  
  1604  	// If the lengths are different, then the shorter one always wins
  1605  	if len(a.Path) != len(b.Path) {
  1606  		return len(a.Path) < len(b.Path)
  1607  	}
  1608  
  1609  	// Otherwise, compare lexically
  1610  	return strings.Join(a.Path, ".") < strings.Join(b.Path, ".")
  1611  }
  1612  
  1613  func (s moduleStateSort) Swap(i, j int) {
  1614  	s[i], s[j] = s[j], s[i]
  1615  }