github.com/rmenn/terraform@v0.3.8-0.20150225065417-fc84b3a78802/terraform/state.go (about)

     1  package terraform
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io"
     9  	"log"
    10  	"reflect"
    11  	"sort"
    12  	"strings"
    13  
    14  	"github.com/hashicorp/terraform/config"
    15  )
    16  
    17  const (
    18  	// StateVersion is the current version for our state file
    19  	StateVersion = 1
    20  )
    21  
    22  // rootModulePath is the path of the root module
    23  var rootModulePath = []string{"root"}
    24  
    25  // State keeps track of a snapshot state-of-the-world that Terraform
    26  // can use to keep track of what real world resources it is actually
    27  // managing. This is the latest format as of Terraform 0.3
    28  type State struct {
    29  	// Version is the protocol version. Currently only "1".
    30  	Version int `json:"version"`
    31  
    32  	// Serial is incremented on any operation that modifies
    33  	// the State file. It is used to detect potentially conflicting
    34  	// updates.
    35  	Serial int64 `json:"serial"`
    36  
    37  	// Remote is used to track the metadata required to
    38  	// pull and push state files from a remote storage endpoint.
    39  	Remote *RemoteState `json:"remote,omitempty"`
    40  
    41  	// Modules contains all the modules in a breadth-first order
    42  	Modules []*ModuleState `json:"modules"`
    43  }
    44  
    45  // NewState is used to initialize a blank state
    46  func NewState() *State {
    47  	s := &State{}
    48  	s.init()
    49  	return s
    50  }
    51  
    52  // Children returns the ModuleStates that are direct children of
    53  // the given path. If the path is "root", for example, then children
    54  // returned might be "root.child", but not "root.child.grandchild".
    55  func (s *State) Children(path []string) []*ModuleState {
    56  	// TODO: test
    57  
    58  	result := make([]*ModuleState, 0)
    59  	for _, m := range s.Modules {
    60  		if len(m.Path) != len(path)+1 {
    61  			continue
    62  		}
    63  		if !reflect.DeepEqual(path, m.Path[:len(path)]) {
    64  			continue
    65  		}
    66  
    67  		result = append(result, m)
    68  	}
    69  
    70  	return result
    71  }
    72  
    73  // AddModule adds the module with the given path to the state.
    74  //
    75  // This should be the preferred method to add module states since it
    76  // allows us to optimize lookups later as well as control sorting.
    77  func (s *State) AddModule(path []string) *ModuleState {
    78  	m := &ModuleState{Path: path}
    79  	m.init()
    80  	s.Modules = append(s.Modules, m)
    81  	s.sort()
    82  	return m
    83  }
    84  
    85  // ModuleByPath is used to lookup the module state for the given path.
    86  // This should be the prefered lookup mechanism as it allows for future
    87  // lookup optimizations.
    88  func (s *State) ModuleByPath(path []string) *ModuleState {
    89  	if s == nil {
    90  		return nil
    91  	}
    92  	for _, mod := range s.Modules {
    93  		if mod.Path == nil {
    94  			panic("missing module path")
    95  		}
    96  		if reflect.DeepEqual(mod.Path, path) {
    97  			return mod
    98  		}
    99  	}
   100  	return nil
   101  }
   102  
   103  // ModuleOrphans returns all the module orphans in this state by
   104  // returning their full paths. These paths can be used with ModuleByPath
   105  // to return the actual state.
   106  func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string {
   107  	childrenKeys := make(map[string]struct{})
   108  	if c != nil {
   109  		for _, m := range c.Modules {
   110  			childrenKeys[m.Name] = struct{}{}
   111  		}
   112  	}
   113  
   114  	// Go over the direct children and find any that aren't in our
   115  	// keys.
   116  	var orphans [][]string
   117  	for _, m := range s.Children(path) {
   118  		if _, ok := childrenKeys[m.Path[len(m.Path)-1]]; ok {
   119  			continue
   120  		}
   121  
   122  		orphans = append(orphans, m.Path)
   123  	}
   124  
   125  	return orphans
   126  }
   127  
   128  // Empty returns true if the state is empty.
   129  func (s *State) Empty() bool {
   130  	if s == nil {
   131  		return true
   132  	}
   133  
   134  	return len(s.Modules) == 0
   135  }
   136  
   137  // IsRemote returns true if State represents a state that exists and is
   138  // remote.
   139  func (s *State) IsRemote() bool {
   140  	if s == nil {
   141  		return false
   142  	}
   143  	if s.Remote == nil {
   144  		return false
   145  	}
   146  	if s.Remote.Type == "" {
   147  		return false
   148  	}
   149  
   150  	return true
   151  }
   152  
   153  // RootModule returns the ModuleState for the root module
   154  func (s *State) RootModule() *ModuleState {
   155  	root := s.ModuleByPath(rootModulePath)
   156  	if root == nil {
   157  		panic("missing root module")
   158  	}
   159  	return root
   160  }
   161  
   162  // Equal tests if one state is equal to another.
   163  func (s *State) Equal(other *State) bool {
   164  	// If one is nil, we do a direct check
   165  	if s == nil || other == nil {
   166  		return s == other
   167  	}
   168  
   169  	// If the versions are different, they're certainly not equal
   170  	if s.Version != other.Version {
   171  		return false
   172  	}
   173  
   174  	// If any of the modules are not equal, then this state isn't equal
   175  	if len(s.Modules) != len(other.Modules) {
   176  		return false
   177  	}
   178  	for _, m := range s.Modules {
   179  		// This isn't very optimal currently but works.
   180  		otherM := other.ModuleByPath(m.Path)
   181  		if otherM == nil {
   182  			return false
   183  		}
   184  
   185  		// If they're not equal, then we're not equal!
   186  		if !m.Equal(otherM) {
   187  			return false
   188  		}
   189  	}
   190  
   191  	return true
   192  }
   193  
   194  // DeepCopy performs a deep copy of the state structure and returns
   195  // a new structure.
   196  func (s *State) DeepCopy() *State {
   197  	if s == nil {
   198  		return nil
   199  	}
   200  	n := &State{
   201  		Version: s.Version,
   202  		Serial:  s.Serial,
   203  		Modules: make([]*ModuleState, 0, len(s.Modules)),
   204  	}
   205  	for _, mod := range s.Modules {
   206  		n.Modules = append(n.Modules, mod.deepcopy())
   207  	}
   208  	if s.Remote != nil {
   209  		n.Remote = s.Remote.deepcopy()
   210  	}
   211  	return n
   212  }
   213  
   214  // IncrementSerialMaybe increments the serial number of this state
   215  // if it different from the other state.
   216  func (s *State) IncrementSerialMaybe(other *State) {
   217  	if !s.Equal(other) {
   218  		s.Serial++
   219  	}
   220  }
   221  
   222  func (s *State) init() {
   223  	if s.Version == 0 {
   224  		s.Version = StateVersion
   225  	}
   226  	if len(s.Modules) == 0 {
   227  		root := &ModuleState{
   228  			Path: rootModulePath,
   229  		}
   230  		root.init()
   231  		s.Modules = []*ModuleState{root}
   232  	}
   233  }
   234  
   235  // prune is used to remove any resources that are no longer required
   236  func (s *State) prune() {
   237  	if s == nil {
   238  		return
   239  	}
   240  	for _, mod := range s.Modules {
   241  		mod.prune()
   242  	}
   243  	if s.Remote != nil && s.Remote.Empty() {
   244  		s.Remote = nil
   245  	}
   246  }
   247  
   248  // sort sorts the modules
   249  func (s *State) sort() {
   250  	sort.Sort(moduleStateSort(s.Modules))
   251  
   252  	// Allow modules to be sorted
   253  	for _, m := range s.Modules {
   254  		m.sort()
   255  	}
   256  }
   257  
   258  func (s *State) GoString() string {
   259  	return fmt.Sprintf("*%#v", *s)
   260  }
   261  
   262  func (s *State) String() string {
   263  	var buf bytes.Buffer
   264  	for _, m := range s.Modules {
   265  		mStr := m.String()
   266  
   267  		// If we're the root module, we just write the output directly.
   268  		if reflect.DeepEqual(m.Path, rootModulePath) {
   269  			buf.WriteString(mStr + "\n")
   270  			continue
   271  		}
   272  
   273  		buf.WriteString(fmt.Sprintf("module.%s:\n", strings.Join(m.Path[1:], ".")))
   274  
   275  		s := bufio.NewScanner(strings.NewReader(mStr))
   276  		for s.Scan() {
   277  			text := s.Text()
   278  			if text != "" {
   279  				text = "  " + text
   280  			}
   281  
   282  			buf.WriteString(fmt.Sprintf("%s\n", text))
   283  		}
   284  	}
   285  
   286  	return strings.TrimSpace(buf.String())
   287  }
   288  
   289  // RemoteState is used to track the information about a remote
   290  // state store that we push/pull state to.
   291  type RemoteState struct {
   292  	// Type controls the client we use for the remote state
   293  	Type string `json:"type"`
   294  
   295  	// Config is used to store arbitrary configuration that
   296  	// is type specific
   297  	Config map[string]string `json:"config"`
   298  }
   299  
   300  func (r *RemoteState) deepcopy() *RemoteState {
   301  	confCopy := make(map[string]string, len(r.Config))
   302  	for k, v := range r.Config {
   303  		confCopy[k] = v
   304  	}
   305  	return &RemoteState{
   306  		Type:   r.Type,
   307  		Config: confCopy,
   308  	}
   309  }
   310  
   311  func (r *RemoteState) Empty() bool {
   312  	return r == nil || r.Type == ""
   313  }
   314  
   315  func (r *RemoteState) Equals(other *RemoteState) bool {
   316  	if r.Type != other.Type {
   317  		return false
   318  	}
   319  	if len(r.Config) != len(other.Config) {
   320  		return false
   321  	}
   322  	for k, v := range r.Config {
   323  		if other.Config[k] != v {
   324  			return false
   325  		}
   326  	}
   327  	return true
   328  }
   329  
   330  // ModuleState is used to track all the state relevant to a single
   331  // module. Previous to Terraform 0.3, all state belonged to the "root"
   332  // module.
   333  type ModuleState struct {
   334  	// Path is the import path from the root module. Modules imports are
   335  	// always disjoint, so the path represents amodule tree
   336  	Path []string `json:"path"`
   337  
   338  	// Outputs declared by the module and maintained for each module
   339  	// even though only the root module technically needs to be kept.
   340  	// This allows operators to inspect values at the boundaries.
   341  	Outputs map[string]string `json:"outputs"`
   342  
   343  	// Resources is a mapping of the logically named resource to
   344  	// the state of the resource. Each resource may actually have
   345  	// N instances underneath, although a user only needs to think
   346  	// about the 1:1 case.
   347  	Resources map[string]*ResourceState `json:"resources"`
   348  
   349  	// Dependencies are a list of things that this module relies on
   350  	// existing to remain intact. For example: an module may depend
   351  	// on a VPC ID given by an aws_vpc resource.
   352  	//
   353  	// Terraform uses this information to build valid destruction
   354  	// orders and to warn the user if they're destroying a module that
   355  	// another resource depends on.
   356  	//
   357  	// Things can be put into this list that may not be managed by
   358  	// Terraform. If Terraform doesn't find a matching ID in the
   359  	// overall state, then it assumes it isn't managed and doesn't
   360  	// worry about it.
   361  	Dependencies []string `json:"depends_on,omitempty"`
   362  }
   363  
   364  // Equal tests whether one module state is equal to another.
   365  func (m *ModuleState) Equal(other *ModuleState) bool {
   366  	// Paths must be equal
   367  	if !reflect.DeepEqual(m.Path, other.Path) {
   368  		return false
   369  	}
   370  
   371  	// Outputs must be equal
   372  	if len(m.Outputs) != len(other.Outputs) {
   373  		return false
   374  	}
   375  	for k, v := range m.Outputs {
   376  		if other.Outputs[k] != v {
   377  			return false
   378  		}
   379  	}
   380  
   381  	// Dependencies must be equal. This sorts these in place but
   382  	// this shouldn't cause any problems.
   383  	sort.Strings(m.Dependencies)
   384  	sort.Strings(other.Dependencies)
   385  	if len(m.Dependencies) != len(other.Dependencies) {
   386  		return false
   387  	}
   388  	for i, d := range m.Dependencies {
   389  		if other.Dependencies[i] != d {
   390  			return false
   391  		}
   392  	}
   393  
   394  	// Resources must be equal
   395  	if len(m.Resources) != len(other.Resources) {
   396  		return false
   397  	}
   398  	for k, r := range m.Resources {
   399  		otherR, ok := other.Resources[k]
   400  		if !ok {
   401  			return false
   402  		}
   403  
   404  		if !r.Equal(otherR) {
   405  			return false
   406  		}
   407  	}
   408  
   409  	return true
   410  }
   411  
   412  // IsRoot says whether or not this module diff is for the root module.
   413  func (m *ModuleState) IsRoot() bool {
   414  	return reflect.DeepEqual(m.Path, rootModulePath)
   415  }
   416  
   417  // Orphans returns a list of keys of resources that are in the State
   418  // but aren't present in the configuration itself. Hence, these keys
   419  // represent the state of resources that are orphans.
   420  func (m *ModuleState) Orphans(c *config.Config) []string {
   421  	keys := make(map[string]struct{})
   422  	for k, _ := range m.Resources {
   423  		keys[k] = struct{}{}
   424  	}
   425  
   426  	if c != nil {
   427  		for _, r := range c.Resources {
   428  			delete(keys, r.Id())
   429  
   430  			for k, _ := range keys {
   431  				if strings.HasPrefix(k, r.Id()+".") {
   432  					delete(keys, k)
   433  				}
   434  			}
   435  		}
   436  	}
   437  
   438  	result := make([]string, 0, len(keys))
   439  	for k, _ := range keys {
   440  		result = append(result, k)
   441  	}
   442  
   443  	return result
   444  }
   445  
   446  // View returns a view with the given resource prefix.
   447  func (m *ModuleState) View(id string) *ModuleState {
   448  	if m == nil {
   449  		return m
   450  	}
   451  
   452  	r := m.deepcopy()
   453  	for k, _ := range r.Resources {
   454  		if id == k || strings.HasPrefix(k, id+".") {
   455  			continue
   456  		}
   457  
   458  		delete(r.Resources, k)
   459  	}
   460  
   461  	return r
   462  }
   463  
   464  func (m *ModuleState) init() {
   465  	if m.Outputs == nil {
   466  		m.Outputs = make(map[string]string)
   467  	}
   468  	if m.Resources == nil {
   469  		m.Resources = make(map[string]*ResourceState)
   470  	}
   471  }
   472  
   473  func (m *ModuleState) deepcopy() *ModuleState {
   474  	if m == nil {
   475  		return nil
   476  	}
   477  	n := &ModuleState{
   478  		Path:      make([]string, len(m.Path)),
   479  		Outputs:   make(map[string]string, len(m.Outputs)),
   480  		Resources: make(map[string]*ResourceState, len(m.Resources)),
   481  	}
   482  	copy(n.Path, m.Path)
   483  	for k, v := range m.Outputs {
   484  		n.Outputs[k] = v
   485  	}
   486  	for k, v := range m.Resources {
   487  		n.Resources[k] = v.deepcopy()
   488  	}
   489  	return n
   490  }
   491  
   492  // prune is used to remove any resources that are no longer required
   493  func (m *ModuleState) prune() {
   494  	for k, v := range m.Resources {
   495  		v.prune()
   496  
   497  		if (v.Primary == nil || v.Primary.ID == "") && len(v.Tainted) == 0 {
   498  			delete(m.Resources, k)
   499  		}
   500  	}
   501  
   502  	for k, v := range m.Outputs {
   503  		if v == config.UnknownVariableValue {
   504  			delete(m.Outputs, k)
   505  		}
   506  	}
   507  }
   508  
   509  func (m *ModuleState) sort() {
   510  	for _, v := range m.Resources {
   511  		v.sort()
   512  	}
   513  }
   514  
   515  func (m *ModuleState) GoString() string {
   516  	return fmt.Sprintf("*%#v", *m)
   517  }
   518  
   519  func (m *ModuleState) String() string {
   520  	var buf bytes.Buffer
   521  
   522  	if len(m.Resources) == 0 {
   523  		buf.WriteString("<no state>")
   524  	}
   525  
   526  	names := make([]string, 0, len(m.Resources))
   527  	for name, _ := range m.Resources {
   528  		names = append(names, name)
   529  	}
   530  	sort.Strings(names)
   531  
   532  	for _, k := range names {
   533  		rs := m.Resources[k]
   534  		var id string
   535  		if rs.Primary != nil {
   536  			id = rs.Primary.ID
   537  		}
   538  		if id == "" {
   539  			id = "<not created>"
   540  		}
   541  
   542  		taintStr := ""
   543  		if len(rs.Tainted) > 0 {
   544  			taintStr = fmt.Sprintf(" (%d tainted)", len(rs.Tainted))
   545  		}
   546  
   547  		buf.WriteString(fmt.Sprintf("%s:%s\n", k, taintStr))
   548  		buf.WriteString(fmt.Sprintf("  ID = %s\n", id))
   549  
   550  		var attributes map[string]string
   551  		if rs.Primary != nil {
   552  			attributes = rs.Primary.Attributes
   553  		}
   554  		attrKeys := make([]string, 0, len(attributes))
   555  		for ak, _ := range attributes {
   556  			if ak == "id" {
   557  				continue
   558  			}
   559  
   560  			attrKeys = append(attrKeys, ak)
   561  		}
   562  		sort.Strings(attrKeys)
   563  
   564  		for _, ak := range attrKeys {
   565  			av := attributes[ak]
   566  			buf.WriteString(fmt.Sprintf("  %s = %s\n", ak, av))
   567  		}
   568  
   569  		for idx, t := range rs.Tainted {
   570  			buf.WriteString(fmt.Sprintf("  Tainted ID %d = %s\n", idx+1, t.ID))
   571  		}
   572  
   573  		if len(rs.Dependencies) > 0 {
   574  			buf.WriteString(fmt.Sprintf("\n  Dependencies:\n"))
   575  			for _, dep := range rs.Dependencies {
   576  				buf.WriteString(fmt.Sprintf("    %s\n", dep))
   577  			}
   578  		}
   579  	}
   580  
   581  	if len(m.Outputs) > 0 {
   582  		buf.WriteString("\nOutputs:\n\n")
   583  
   584  		ks := make([]string, 0, len(m.Outputs))
   585  		for k, _ := range m.Outputs {
   586  			ks = append(ks, k)
   587  		}
   588  		sort.Strings(ks)
   589  
   590  		for _, k := range ks {
   591  			v := m.Outputs[k]
   592  			buf.WriteString(fmt.Sprintf("%s = %s\n", k, v))
   593  		}
   594  	}
   595  
   596  	return buf.String()
   597  }
   598  
   599  // ResourceState holds the state of a resource that is used so that
   600  // a provider can find and manage an existing resource as well as for
   601  // storing attributes that are used to populate variables of child
   602  // resources.
   603  //
   604  // Attributes has attributes about the created resource that are
   605  // queryable in interpolation: "${type.id.attr}"
   606  //
   607  // Extra is just extra data that a provider can return that we store
   608  // for later, but is not exposed in any way to the user.
   609  //
   610  type ResourceState struct {
   611  	// This is filled in and managed by Terraform, and is the resource
   612  	// type itself such as "mycloud_instance". If a resource provider sets
   613  	// this value, it won't be persisted.
   614  	Type string `json:"type"`
   615  
   616  	// Dependencies are a list of things that this resource relies on
   617  	// existing to remain intact. For example: an AWS instance might
   618  	// depend on a subnet (which itself might depend on a VPC, and so
   619  	// on).
   620  	//
   621  	// Terraform uses this information to build valid destruction
   622  	// orders and to warn the user if they're destroying a resource that
   623  	// another resource depends on.
   624  	//
   625  	// Things can be put into this list that may not be managed by
   626  	// Terraform. If Terraform doesn't find a matching ID in the
   627  	// overall state, then it assumes it isn't managed and doesn't
   628  	// worry about it.
   629  	Dependencies []string `json:"depends_on,omitempty"`
   630  
   631  	// Primary is the current active instance for this resource.
   632  	// It can be replaced but only after a successful creation.
   633  	// This is the instances on which providers will act.
   634  	Primary *InstanceState `json:"primary"`
   635  
   636  	// Tainted is used to track any underlying instances that
   637  	// have been created but are in a bad or unknown state and
   638  	// need to be cleaned up subsequently.  In the
   639  	// standard case, there is only at most a single instance.
   640  	// However, in pathological cases, it is possible for the number
   641  	// of instances to accumulate.
   642  	Tainted []*InstanceState `json:"tainted,omitempty"`
   643  }
   644  
   645  // Equal tests whether two ResourceStates are equal.
   646  func (s *ResourceState) Equal(other *ResourceState) bool {
   647  	if s.Type != other.Type {
   648  		return false
   649  	}
   650  
   651  	// Dependencies must be equal
   652  	sort.Strings(s.Dependencies)
   653  	sort.Strings(other.Dependencies)
   654  	if len(s.Dependencies) != len(other.Dependencies) {
   655  		return false
   656  	}
   657  	for i, d := range s.Dependencies {
   658  		if other.Dependencies[i] != d {
   659  			return false
   660  		}
   661  	}
   662  
   663  	// States must be equal
   664  	if !s.Primary.Equal(other.Primary) {
   665  		return false
   666  	}
   667  
   668  	// Tainted
   669  	taints := make(map[string]*InstanceState)
   670  	for _, t := range other.Tainted {
   671  		if t == nil {
   672  			continue
   673  		}
   674  
   675  		taints[t.ID] = t
   676  	}
   677  	for _, t := range s.Tainted {
   678  		if t == nil {
   679  			continue
   680  		}
   681  
   682  		otherT, ok := taints[t.ID]
   683  		if !ok {
   684  			return false
   685  		}
   686  		delete(taints, t.ID)
   687  
   688  		if !t.Equal(otherT) {
   689  			return false
   690  		}
   691  	}
   692  
   693  	// This means that we have stuff in other tainted that we don't
   694  	// have, so it is not equal.
   695  	if len(taints) > 0 {
   696  		return false
   697  	}
   698  
   699  	return true
   700  }
   701  
   702  func (r *ResourceState) init() {
   703  	if r.Primary == nil {
   704  		r.Primary = &InstanceState{}
   705  	}
   706  	r.Primary.init()
   707  }
   708  
   709  func (r *ResourceState) deepcopy() *ResourceState {
   710  	if r == nil {
   711  		return nil
   712  	}
   713  	n := &ResourceState{
   714  		Type:         r.Type,
   715  		Dependencies: make([]string, len(r.Dependencies)),
   716  		Primary:      r.Primary.deepcopy(),
   717  		Tainted:      make([]*InstanceState, 0, len(r.Tainted)),
   718  	}
   719  	copy(n.Dependencies, r.Dependencies)
   720  	for _, inst := range r.Tainted {
   721  		n.Tainted = append(n.Tainted, inst.deepcopy())
   722  	}
   723  	return n
   724  }
   725  
   726  // prune is used to remove any instances that are no longer required
   727  func (r *ResourceState) prune() {
   728  	n := len(r.Tainted)
   729  	for i := 0; i < n; i++ {
   730  		inst := r.Tainted[i]
   731  		if inst == nil || inst.ID == "" {
   732  			copy(r.Tainted[i:], r.Tainted[i+1:])
   733  			r.Tainted[n-1] = nil
   734  			n--
   735  			i--
   736  		}
   737  	}
   738  
   739  	r.Tainted = r.Tainted[:n]
   740  }
   741  
   742  func (r *ResourceState) sort() {
   743  	sort.Strings(r.Dependencies)
   744  }
   745  
   746  func (s *ResourceState) GoString() string {
   747  	return fmt.Sprintf("*%#v", *s)
   748  }
   749  
   750  func (s *ResourceState) String() string {
   751  	var buf bytes.Buffer
   752  	buf.WriteString(fmt.Sprintf("Type = %s", s.Type))
   753  	return buf.String()
   754  }
   755  
   756  // InstanceState is used to track the unique state information belonging
   757  // to a given instance.
   758  type InstanceState struct {
   759  	// A unique ID for this resource. This is opaque to Terraform
   760  	// and is only meant as a lookup mechanism for the providers.
   761  	ID string `json:"id"`
   762  
   763  	// Attributes are basic information about the resource. Any keys here
   764  	// are accessible in variable format within Terraform configurations:
   765  	// ${resourcetype.name.attribute}.
   766  	Attributes map[string]string `json:"attributes,omitempty"`
   767  
   768  	// Ephemeral is used to store any state associated with this instance
   769  	// that is necessary for the Terraform run to complete, but is not
   770  	// persisted to a state file.
   771  	Ephemeral EphemeralState `json:"-"`
   772  }
   773  
   774  func (i *InstanceState) init() {
   775  	if i.Attributes == nil {
   776  		i.Attributes = make(map[string]string)
   777  	}
   778  	i.Ephemeral.init()
   779  }
   780  
   781  func (i *InstanceState) deepcopy() *InstanceState {
   782  	if i == nil {
   783  		return nil
   784  	}
   785  	n := &InstanceState{
   786  		ID:        i.ID,
   787  		Ephemeral: *i.Ephemeral.deepcopy(),
   788  	}
   789  	if i.Attributes != nil {
   790  		n.Attributes = make(map[string]string, len(i.Attributes))
   791  		for k, v := range i.Attributes {
   792  			n.Attributes[k] = v
   793  		}
   794  	}
   795  	return n
   796  }
   797  
   798  func (s *InstanceState) Equal(other *InstanceState) bool {
   799  	// Short circuit some nil checks
   800  	if s == nil || other == nil {
   801  		return s == other
   802  	}
   803  
   804  	// IDs must be equal
   805  	if s.ID != other.ID {
   806  		return false
   807  	}
   808  
   809  	// Attributes must be equal
   810  	if len(s.Attributes) != len(other.Attributes) {
   811  		return false
   812  	}
   813  	for k, v := range s.Attributes {
   814  		otherV, ok := other.Attributes[k]
   815  		if !ok {
   816  			return false
   817  		}
   818  
   819  		if v != otherV {
   820  			return false
   821  		}
   822  	}
   823  
   824  	return true
   825  }
   826  
   827  // MergeDiff takes a ResourceDiff and merges the attributes into
   828  // this resource state in order to generate a new state. This new
   829  // state can be used to provide updated attribute lookups for
   830  // variable interpolation.
   831  //
   832  // If the diff attribute requires computing the value, and hence
   833  // won't be available until apply, the value is replaced with the
   834  // computeID.
   835  func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState {
   836  	result := s.deepcopy()
   837  	if result == nil {
   838  		result = new(InstanceState)
   839  	}
   840  	result.init()
   841  
   842  	if s != nil {
   843  		for k, v := range s.Attributes {
   844  			result.Attributes[k] = v
   845  		}
   846  	}
   847  	if d != nil {
   848  		for k, diff := range d.Attributes {
   849  			if diff.NewRemoved {
   850  				delete(result.Attributes, k)
   851  				continue
   852  			}
   853  			if diff.NewComputed {
   854  				result.Attributes[k] = config.UnknownVariableValue
   855  				continue
   856  			}
   857  
   858  			result.Attributes[k] = diff.New
   859  		}
   860  	}
   861  
   862  	return result
   863  }
   864  
   865  func (i *InstanceState) GoString() string {
   866  	return fmt.Sprintf("*%#v", *i)
   867  }
   868  
   869  func (i *InstanceState) String() string {
   870  	var buf bytes.Buffer
   871  
   872  	if i == nil || i.ID == "" {
   873  		return "<not created>"
   874  	}
   875  
   876  	buf.WriteString(fmt.Sprintf("ID = %s\n", i.ID))
   877  
   878  	attributes := i.Attributes
   879  	attrKeys := make([]string, 0, len(attributes))
   880  	for ak, _ := range attributes {
   881  		if ak == "id" {
   882  			continue
   883  		}
   884  
   885  		attrKeys = append(attrKeys, ak)
   886  	}
   887  	sort.Strings(attrKeys)
   888  
   889  	for _, ak := range attrKeys {
   890  		av := attributes[ak]
   891  		buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av))
   892  	}
   893  
   894  	return buf.String()
   895  }
   896  
   897  // EphemeralState is used for transient state that is only kept in-memory
   898  type EphemeralState struct {
   899  	// ConnInfo is used for the providers to export information which is
   900  	// used to connect to the resource for provisioning. For example,
   901  	// this could contain SSH or WinRM credentials.
   902  	ConnInfo map[string]string `json:"-"`
   903  }
   904  
   905  func (e *EphemeralState) init() {
   906  	if e.ConnInfo == nil {
   907  		e.ConnInfo = make(map[string]string)
   908  	}
   909  }
   910  
   911  func (e *EphemeralState) deepcopy() *EphemeralState {
   912  	if e == nil {
   913  		return nil
   914  	}
   915  	n := &EphemeralState{}
   916  	if e.ConnInfo != nil {
   917  		n.ConnInfo = make(map[string]string, len(e.ConnInfo))
   918  		for k, v := range e.ConnInfo {
   919  			n.ConnInfo[k] = v
   920  		}
   921  	}
   922  	return n
   923  }
   924  
   925  // ReadState reads a state structure out of a reader in the format that
   926  // was written by WriteState.
   927  func ReadState(src io.Reader) (*State, error) {
   928  	buf := bufio.NewReader(src)
   929  
   930  	// Check if this is a V1 format
   931  	start, err := buf.Peek(len(stateFormatMagic))
   932  	if err != nil {
   933  		return nil, fmt.Errorf("Failed to check for magic bytes: %v", err)
   934  	}
   935  	if string(start) == stateFormatMagic {
   936  		// Read the old state
   937  		old, err := ReadStateV1(buf)
   938  		if err != nil {
   939  			return nil, err
   940  		}
   941  		return upgradeV1State(old)
   942  	}
   943  
   944  	// Otherwise, must be V2
   945  	dec := json.NewDecoder(buf)
   946  	state := &State{}
   947  	if err := dec.Decode(state); err != nil {
   948  		return nil, fmt.Errorf("Decoding state file failed: %v", err)
   949  	}
   950  
   951  	// Check the version, this to ensure we don't read a future
   952  	// version that we don't understand
   953  	if state.Version > StateVersion {
   954  		return nil, fmt.Errorf("State version %d not supported, please update.",
   955  			state.Version)
   956  	}
   957  
   958  	// Sort it
   959  	state.sort()
   960  
   961  	return state, nil
   962  }
   963  
   964  // WriteState writes a state somewhere in a binary format.
   965  func WriteState(d *State, dst io.Writer) error {
   966  	// Make sure it is sorted
   967  	d.sort()
   968  
   969  	// Ensure the version is set
   970  	d.Version = StateVersion
   971  
   972  	// Encode the data in a human-friendly way
   973  	data, err := json.MarshalIndent(d, "", "    ")
   974  	if err != nil {
   975  		return fmt.Errorf("Failed to encode state: %s", err)
   976  	}
   977  
   978  	// We append a newline to the data because MarshalIndent doesn't
   979  	data = append(data, '\n')
   980  
   981  	// Write the data out to the dst
   982  	if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil {
   983  		return fmt.Errorf("Failed to write state: %v", err)
   984  	}
   985  
   986  	return nil
   987  }
   988  
   989  // upgradeV1State is used to upgrade a V1 state representation
   990  // into a proper State representation.
   991  func upgradeV1State(old *StateV1) (*State, error) {
   992  	s := &State{}
   993  	s.init()
   994  
   995  	// Old format had no modules, so we migrate everything
   996  	// directly into the root module.
   997  	root := s.RootModule()
   998  
   999  	// Copy the outputs
  1000  	root.Outputs = old.Outputs
  1001  
  1002  	// Upgrade the resources
  1003  	for id, rs := range old.Resources {
  1004  		newRs := &ResourceState{
  1005  			Type: rs.Type,
  1006  		}
  1007  		root.Resources[id] = newRs
  1008  
  1009  		// Migrate to an instance state
  1010  		instance := &InstanceState{
  1011  			ID:         rs.ID,
  1012  			Attributes: rs.Attributes,
  1013  		}
  1014  
  1015  		// Check if this is the primary or tainted instance
  1016  		if _, ok := old.Tainted[id]; ok {
  1017  			newRs.Tainted = append(newRs.Tainted, instance)
  1018  		} else {
  1019  			newRs.Primary = instance
  1020  		}
  1021  
  1022  		// Warn if the resource uses Extra, as there is
  1023  		// no upgrade path for this! Now totally deprecated.
  1024  		if len(rs.Extra) > 0 {
  1025  			log.Printf(
  1026  				"[WARN] Resource %s uses deprecated attribute "+
  1027  					"storage, state file upgrade may be incomplete.",
  1028  				rs.ID,
  1029  			)
  1030  		}
  1031  	}
  1032  	return s, nil
  1033  }
  1034  
  1035  // moduleStateSort implements sort.Interface to sort module states
  1036  type moduleStateSort []*ModuleState
  1037  
  1038  func (s moduleStateSort) Len() int {
  1039  	return len(s)
  1040  }
  1041  
  1042  func (s moduleStateSort) Less(i, j int) bool {
  1043  	a := s[i]
  1044  	b := s[j]
  1045  
  1046  	// If the lengths are different, then the shorter one always wins
  1047  	if len(a.Path) != len(b.Path) {
  1048  		return len(a.Path) < len(b.Path)
  1049  	}
  1050  
  1051  	// Otherwise, compare by last path element
  1052  	idx := len(a.Path) - 1
  1053  	return a.Path[idx] < b.Path[idx]
  1054  }
  1055  
  1056  func (s moduleStateSort) Swap(i, j int) {
  1057  	s[i], s[j] = s[j], s[i]
  1058  }