]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/terraform/terraform/state.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / state.go
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
4 "bufio"
5 "bytes"
6 "encoding/json"
7 "errors"
8 "fmt"
9 "io"
10 "io/ioutil"
11 "log"
15c0b25d 12 "os"
bae9f6d2
JC
13 "reflect"
14 "sort"
15 "strconv"
16 "strings"
17 "sync"
18
107c1cdb
ND
19 "github.com/hashicorp/errwrap"
20 multierror "github.com/hashicorp/go-multierror"
21 uuid "github.com/hashicorp/go-uuid"
22 version "github.com/hashicorp/go-version"
23 "github.com/hashicorp/hcl2/hcl"
24 "github.com/hashicorp/hcl2/hcl/hclsyntax"
bae9f6d2 25 "github.com/mitchellh/copystructure"
107c1cdb
ND
26 "github.com/zclconf/go-cty/cty"
27 ctyjson "github.com/zclconf/go-cty/cty/json"
15c0b25d 28
107c1cdb
ND
29 "github.com/hashicorp/terraform/addrs"
30 "github.com/hashicorp/terraform/config"
31 "github.com/hashicorp/terraform/config/hcl2shim"
32 "github.com/hashicorp/terraform/configs"
33 "github.com/hashicorp/terraform/configs/configschema"
34 "github.com/hashicorp/terraform/plans"
35 "github.com/hashicorp/terraform/tfdiags"
15c0b25d 36 tfversion "github.com/hashicorp/terraform/version"
bae9f6d2
JC
37)
38
39const (
40 // StateVersion is the current version for our state file
41 StateVersion = 3
42)
43
44// rootModulePath is the path of the root module
45var rootModulePath = []string{"root"}
46
107c1cdb
ND
47// normalizeModulePath transforms a legacy module path (which may or may not
48// have a redundant "root" label at the start of it) into an
49// addrs.ModuleInstance representing the same module.
50//
51// For legacy reasons, different parts of Terraform disagree about whether the
52// root module has the path []string{} or []string{"root"}, and so this
53// function accepts both and trims off the "root". An implication of this is
54// that it's not possible to actually have a module call in the root module
55// that is itself named "root", since that would be ambiguous.
56//
bae9f6d2
JC
57// normalizeModulePath takes a raw module path and returns a path that
58// has the rootModulePath prepended to it. If I could go back in time I
59// would've never had a rootModulePath (empty path would be root). We can
60// still fix this but thats a big refactor that my branch doesn't make sense
61// for. Instead, this function normalizes paths.
107c1cdb
ND
62func normalizeModulePath(p []string) addrs.ModuleInstance {
63 // FIXME: Remove this once everyone is using addrs.ModuleInstance.
bae9f6d2 64
107c1cdb
ND
65 if len(p) > 0 && p[0] == "root" {
66 p = p[1:]
bae9f6d2
JC
67 }
68
107c1cdb
ND
69 ret := make(addrs.ModuleInstance, len(p))
70 for i, name := range p {
71 // For now we don't actually support modules with multiple instances
72 // identified by keys, so we just treat every path element as a
73 // step with no key.
74 ret[i] = addrs.ModuleInstanceStep{
75 Name: name,
76 }
77 }
78 return ret
bae9f6d2
JC
79}
80
81// State keeps track of a snapshot state-of-the-world that Terraform
82// can use to keep track of what real world resources it is actually
83// managing.
84type State struct {
85 // Version is the state file protocol version.
86 Version int `json:"version"`
87
88 // TFVersion is the version of Terraform that wrote this state.
89 TFVersion string `json:"terraform_version,omitempty"`
90
91 // Serial is incremented on any operation that modifies
92 // the State file. It is used to detect potentially conflicting
93 // updates.
94 Serial int64 `json:"serial"`
95
96 // Lineage is set when a new, blank state is created and then
97 // never updated. This allows us to determine whether the serials
98 // of two states can be meaningfully compared.
99 // Apart from the guarantee that collisions between two lineages
100 // are very unlikely, this value is opaque and external callers
101 // should only compare lineage strings byte-for-byte for equality.
102 Lineage string `json:"lineage"`
103
104 // Remote is used to track the metadata required to
105 // pull and push state files from a remote storage endpoint.
106 Remote *RemoteState `json:"remote,omitempty"`
107
108 // Backend tracks the configuration for the backend in use with
109 // this state. This is used to track any changes in the backend
110 // configuration.
111 Backend *BackendState `json:"backend,omitempty"`
112
113 // Modules contains all the modules in a breadth-first order
114 Modules []*ModuleState `json:"modules"`
115
116 mu sync.Mutex
117}
118
119func (s *State) Lock() { s.mu.Lock() }
120func (s *State) Unlock() { s.mu.Unlock() }
121
122// NewState is used to initialize a blank state
123func NewState() *State {
124 s := &State{}
125 s.init()
126 return s
127}
128
129// Children returns the ModuleStates that are direct children of
130// the given path. If the path is "root", for example, then children
131// returned might be "root.child", but not "root.child.grandchild".
132func (s *State) Children(path []string) []*ModuleState {
133 s.Lock()
134 defer s.Unlock()
135 // TODO: test
136
137 return s.children(path)
138}
139
140func (s *State) children(path []string) []*ModuleState {
141 result := make([]*ModuleState, 0)
142 for _, m := range s.Modules {
143 if m == nil {
144 continue
145 }
146
147 if len(m.Path) != len(path)+1 {
148 continue
149 }
150 if !reflect.DeepEqual(path, m.Path[:len(path)]) {
151 continue
152 }
153
154 result = append(result, m)
155 }
156
157 return result
158}
159
160// AddModule adds the module with the given path to the state.
161//
162// This should be the preferred method to add module states since it
163// allows us to optimize lookups later as well as control sorting.
107c1cdb 164func (s *State) AddModule(path addrs.ModuleInstance) *ModuleState {
bae9f6d2
JC
165 s.Lock()
166 defer s.Unlock()
167
168 return s.addModule(path)
169}
170
107c1cdb 171func (s *State) addModule(path addrs.ModuleInstance) *ModuleState {
bae9f6d2
JC
172 // check if the module exists first
173 m := s.moduleByPath(path)
174 if m != nil {
175 return m
176 }
177
107c1cdb
ND
178 // Lower the new-style address into a legacy-style address.
179 // This requires that none of the steps have instance keys, which is
180 // true for all addresses at the time of implementing this because
181 // "count" and "for_each" are not yet implemented for modules.
182 // For the purposes of state, the legacy address format also includes
183 // a redundant extra prefix element "root". It is important to include
184 // this because the "prune" method will remove any module that has a
185 // path length less than one, and other parts of the state code will
186 // trim off the first element indiscriminately.
187 legacyPath := make([]string, len(path)+1)
188 legacyPath[0] = "root"
189 for i, step := range path {
190 if step.InstanceKey != addrs.NoKey {
191 // FIXME: Once the rest of Terraform is ready to use count and
192 // for_each, remove all of this and just write the addrs.ModuleInstance
193 // value itself into the ModuleState.
194 panic("state cannot represent modules with count or for_each keys")
195 }
196
197 legacyPath[i+1] = step.Name
198 }
199
200 m = &ModuleState{Path: legacyPath}
bae9f6d2
JC
201 m.init()
202 s.Modules = append(s.Modules, m)
203 s.sort()
204 return m
205}
206
207// ModuleByPath is used to lookup the module state for the given path.
208// This should be the preferred lookup mechanism as it allows for future
209// lookup optimizations.
107c1cdb 210func (s *State) ModuleByPath(path addrs.ModuleInstance) *ModuleState {
bae9f6d2
JC
211 if s == nil {
212 return nil
213 }
214 s.Lock()
215 defer s.Unlock()
216
217 return s.moduleByPath(path)
218}
219
107c1cdb 220func (s *State) moduleByPath(path addrs.ModuleInstance) *ModuleState {
bae9f6d2
JC
221 for _, mod := range s.Modules {
222 if mod == nil {
223 continue
224 }
225 if mod.Path == nil {
226 panic("missing module path")
227 }
107c1cdb
ND
228 modPath := normalizeModulePath(mod.Path)
229 if modPath.String() == path.String() {
bae9f6d2
JC
230 return mod
231 }
232 }
233 return nil
234}
235
bae9f6d2
JC
236// Empty returns true if the state is empty.
237func (s *State) Empty() bool {
238 if s == nil {
239 return true
240 }
241 s.Lock()
242 defer s.Unlock()
243
244 return len(s.Modules) == 0
245}
246
247// HasResources returns true if the state contains any resources.
248//
249// This is similar to !s.Empty, but returns true also in the case where the
250// state has modules but all of them are devoid of resources.
251func (s *State) HasResources() bool {
252 if s.Empty() {
253 return false
254 }
255
256 for _, mod := range s.Modules {
257 if len(mod.Resources) > 0 {
258 return true
259 }
260 }
261
262 return false
263}
264
265// IsRemote returns true if State represents a state that exists and is
266// remote.
267func (s *State) IsRemote() bool {
268 if s == nil {
269 return false
270 }
271 s.Lock()
272 defer s.Unlock()
273
274 if s.Remote == nil {
275 return false
276 }
277 if s.Remote.Type == "" {
278 return false
279 }
280
281 return true
282}
283
284// Validate validates the integrity of this state file.
285//
286// Certain properties of the statefile are expected by Terraform in order
287// to behave properly. The core of Terraform will assume that once it
288// receives a State structure that it has been validated. This validation
289// check should be called to ensure that.
290//
291// If this returns an error, then the user should be notified. The error
292// response will include detailed information on the nature of the error.
293func (s *State) Validate() error {
294 s.Lock()
295 defer s.Unlock()
296
297 var result error
298
299 // !!!! FOR DEVELOPERS !!!!
300 //
301 // Any errors returned from this Validate function will BLOCK TERRAFORM
302 // from loading a state file. Therefore, this should only contain checks
303 // that are only resolvable through manual intervention.
304 //
305 // !!!! FOR DEVELOPERS !!!!
306
307 // Make sure there are no duplicate module states. We open a new
308 // block here so we can use basic variable names and future validations
309 // can do the same.
310 {
311 found := make(map[string]struct{})
312 for _, ms := range s.Modules {
313 if ms == nil {
314 continue
315 }
316
317 key := strings.Join(ms.Path, ".")
318 if _, ok := found[key]; ok {
319 result = multierror.Append(result, fmt.Errorf(
320 strings.TrimSpace(stateValidateErrMultiModule), key))
321 continue
322 }
323
324 found[key] = struct{}{}
325 }
326 }
327
328 return result
329}
330
331// Remove removes the item in the state at the given address, returning
332// any errors that may have occurred.
333//
334// If the address references a module state or resource, it will delete
335// all children as well. To check what will be deleted, use a StateFilter
336// first.
337func (s *State) Remove(addr ...string) error {
338 s.Lock()
339 defer s.Unlock()
340
341 // Filter out what we need to delete
342 filter := &StateFilter{State: s}
343 results, err := filter.Filter(addr...)
344 if err != nil {
345 return err
346 }
347
348 // If we have no results, just exit early, we're not going to do anything.
349 // While what happens below is fairly fast, this is an important early
350 // exit since the prune below might modify the state more and we don't
351 // want to modify the state if we don't have to.
352 if len(results) == 0 {
353 return nil
354 }
355
356 // Go through each result and grab what we need
357 removed := make(map[interface{}]struct{})
358 for _, r := range results {
359 // Convert the path to our own type
360 path := append([]string{"root"}, r.Path...)
361
362 // If we removed this already, then ignore
363 if _, ok := removed[r.Value]; ok {
364 continue
365 }
366
367 // If we removed the parent already, then ignore
368 if r.Parent != nil {
369 if _, ok := removed[r.Parent.Value]; ok {
370 continue
371 }
372 }
373
374 // Add this to the removed list
375 removed[r.Value] = struct{}{}
376
377 switch v := r.Value.(type) {
378 case *ModuleState:
379 s.removeModule(path, v)
380 case *ResourceState:
381 s.removeResource(path, v)
382 case *InstanceState:
383 s.removeInstance(path, r.Parent.Value.(*ResourceState), v)
384 default:
385 return fmt.Errorf("unknown type to delete: %T", r.Value)
386 }
387 }
388
389 // Prune since the removal functions often do the bare minimum to
390 // remove a thing and may leave around dangling empty modules, resources,
391 // etc. Prune will clean that all up.
392 s.prune()
393
394 return nil
395}
396
397func (s *State) removeModule(path []string, v *ModuleState) {
398 for i, m := range s.Modules {
399 if m == v {
400 s.Modules, s.Modules[len(s.Modules)-1] = append(s.Modules[:i], s.Modules[i+1:]...), nil
401 return
402 }
403 }
404}
405
406func (s *State) removeResource(path []string, v *ResourceState) {
407 // Get the module this resource lives in. If it doesn't exist, we're done.
107c1cdb 408 mod := s.moduleByPath(normalizeModulePath(path))
bae9f6d2
JC
409 if mod == nil {
410 return
411 }
412
413 // Find this resource. This is a O(N) lookup when if we had the key
414 // it could be O(1) but even with thousands of resources this shouldn't
415 // matter right now. We can easily up performance here when the time comes.
416 for k, r := range mod.Resources {
417 if r == v {
418 // Found it
419 delete(mod.Resources, k)
420 return
421 }
422 }
423}
424
425func (s *State) removeInstance(path []string, r *ResourceState, v *InstanceState) {
426 // Go through the resource and find the instance that matches this
427 // (if any) and remove it.
428
429 // Check primary
430 if r.Primary == v {
431 r.Primary = nil
432 return
433 }
434
435 // Check lists
436 lists := [][]*InstanceState{r.Deposed}
437 for _, is := range lists {
438 for i, instance := range is {
439 if instance == v {
440 // Found it, remove it
441 is, is[len(is)-1] = append(is[:i], is[i+1:]...), nil
442
443 // Done
444 return
445 }
446 }
447 }
448}
449
450// RootModule returns the ModuleState for the root module
451func (s *State) RootModule() *ModuleState {
107c1cdb 452 root := s.ModuleByPath(addrs.RootModuleInstance)
bae9f6d2
JC
453 if root == nil {
454 panic("missing root module")
455 }
456 return root
457}
458
459// Equal tests if one state is equal to another.
460func (s *State) Equal(other *State) bool {
461 // If one is nil, we do a direct check
462 if s == nil || other == nil {
463 return s == other
464 }
465
466 s.Lock()
467 defer s.Unlock()
468 return s.equal(other)
469}
470
471func (s *State) equal(other *State) bool {
472 if s == nil || other == nil {
473 return s == other
474 }
475
476 // If the versions are different, they're certainly not equal
477 if s.Version != other.Version {
478 return false
479 }
480
481 // If any of the modules are not equal, then this state isn't equal
482 if len(s.Modules) != len(other.Modules) {
483 return false
484 }
485 for _, m := range s.Modules {
486 // This isn't very optimal currently but works.
107c1cdb 487 otherM := other.moduleByPath(normalizeModulePath(m.Path))
bae9f6d2
JC
488 if otherM == nil {
489 return false
490 }
491
492 // If they're not equal, then we're not equal!
493 if !m.Equal(otherM) {
494 return false
495 }
496 }
497
498 return true
499}
500
c680a8e1
RS
501// MarshalEqual is similar to Equal but provides a stronger definition of
502// "equal", where two states are equal if and only if their serialized form
503// is byte-for-byte identical.
504//
505// This is primarily useful for callers that are trying to save snapshots
506// of state to persistent storage, allowing them to detect when a new
507// snapshot must be taken.
508//
509// Note that the serial number and lineage are included in the serialized form,
510// so it's the caller's responsibility to properly manage these attributes
511// so that this method is only called on two states that have the same
512// serial and lineage, unless detecting such differences is desired.
513func (s *State) MarshalEqual(other *State) bool {
514 if s == nil && other == nil {
515 return true
516 } else if s == nil || other == nil {
517 return false
518 }
519
520 recvBuf := &bytes.Buffer{}
521 otherBuf := &bytes.Buffer{}
522
523 err := WriteState(s, recvBuf)
524 if err != nil {
525 // should never happen, since we're writing to a buffer
526 panic(err)
527 }
528
529 err = WriteState(other, otherBuf)
530 if err != nil {
531 // should never happen, since we're writing to a buffer
532 panic(err)
533 }
534
535 return bytes.Equal(recvBuf.Bytes(), otherBuf.Bytes())
536}
537
bae9f6d2
JC
538type StateAgeComparison int
539
540const (
541 StateAgeEqual StateAgeComparison = 0
542 StateAgeReceiverNewer StateAgeComparison = 1
543 StateAgeReceiverOlder StateAgeComparison = -1
544)
545
546// CompareAges compares one state with another for which is "older".
547//
548// This is a simple check using the state's serial, and is thus only as
549// reliable as the serial itself. In the normal case, only one state
550// exists for a given combination of lineage/serial, but Terraform
551// does not guarantee this and so the result of this method should be
552// used with care.
553//
554// Returns an integer that is negative if the receiver is older than
555// the argument, positive if the converse, and zero if they are equal.
556// An error is returned if the two states are not of the same lineage,
557// in which case the integer returned has no meaning.
558func (s *State) CompareAges(other *State) (StateAgeComparison, error) {
559 // nil states are "older" than actual states
560 switch {
561 case s != nil && other == nil:
562 return StateAgeReceiverNewer, nil
563 case s == nil && other != nil:
564 return StateAgeReceiverOlder, nil
565 case s == nil && other == nil:
566 return StateAgeEqual, nil
567 }
568
569 if !s.SameLineage(other) {
570 return StateAgeEqual, fmt.Errorf(
571 "can't compare two states of differing lineage",
572 )
573 }
574
575 s.Lock()
576 defer s.Unlock()
577
578 switch {
579 case s.Serial < other.Serial:
580 return StateAgeReceiverOlder, nil
581 case s.Serial > other.Serial:
582 return StateAgeReceiverNewer, nil
583 default:
584 return StateAgeEqual, nil
585 }
586}
587
588// SameLineage returns true only if the state given in argument belongs
589// to the same "lineage" of states as the receiver.
590func (s *State) SameLineage(other *State) bool {
591 s.Lock()
592 defer s.Unlock()
593
594 // If one of the states has no lineage then it is assumed to predate
595 // this concept, and so we'll accept it as belonging to any lineage
596 // so that a lineage string can be assigned to newer versions
597 // without breaking compatibility with older versions.
598 if s.Lineage == "" || other.Lineage == "" {
599 return true
600 }
601
602 return s.Lineage == other.Lineage
603}
604
605// DeepCopy performs a deep copy of the state structure and returns
606// a new structure.
607func (s *State) DeepCopy() *State {
c680a8e1
RS
608 if s == nil {
609 return nil
610 }
611
bae9f6d2
JC
612 copy, err := copystructure.Config{Lock: true}.Copy(s)
613 if err != nil {
614 panic(err)
615 }
616
617 return copy.(*State)
618}
619
bae9f6d2
JC
620// FromFutureTerraform checks if this state was written by a Terraform
621// version from the future.
622func (s *State) FromFutureTerraform() bool {
623 s.Lock()
624 defer s.Unlock()
625
626 // No TF version means it is certainly from the past
627 if s.TFVersion == "" {
628 return false
629 }
630
631 v := version.Must(version.NewVersion(s.TFVersion))
15c0b25d 632 return tfversion.SemVer.LessThan(v)
bae9f6d2
JC
633}
634
635func (s *State) Init() {
636 s.Lock()
637 defer s.Unlock()
638 s.init()
639}
640
641func (s *State) init() {
642 if s.Version == 0 {
643 s.Version = StateVersion
644 }
c680a8e1 645
107c1cdb
ND
646 if s.moduleByPath(addrs.RootModuleInstance) == nil {
647 s.addModule(addrs.RootModuleInstance)
bae9f6d2
JC
648 }
649 s.ensureHasLineage()
650
651 for _, mod := range s.Modules {
652 if mod != nil {
653 mod.init()
654 }
655 }
656
657 if s.Remote != nil {
658 s.Remote.init()
659 }
660
661}
662
663func (s *State) EnsureHasLineage() {
664 s.Lock()
665 defer s.Unlock()
666
667 s.ensureHasLineage()
668}
669
670func (s *State) ensureHasLineage() {
671 if s.Lineage == "" {
15c0b25d
AP
672 lineage, err := uuid.GenerateUUID()
673 if err != nil {
674 panic(fmt.Errorf("Failed to generate lineage: %v", err))
675 }
676 s.Lineage = lineage
bae9f6d2
JC
677 log.Printf("[DEBUG] New state was assigned lineage %q\n", s.Lineage)
678 } else {
679 log.Printf("[TRACE] Preserving existing state lineage %q\n", s.Lineage)
680 }
681}
682
683// AddModuleState insert this module state and override any existing ModuleState
684func (s *State) AddModuleState(mod *ModuleState) {
685 mod.init()
686 s.Lock()
687 defer s.Unlock()
688
689 s.addModuleState(mod)
690}
691
692func (s *State) addModuleState(mod *ModuleState) {
693 for i, m := range s.Modules {
694 if reflect.DeepEqual(m.Path, mod.Path) {
695 s.Modules[i] = mod
696 return
697 }
698 }
699
700 s.Modules = append(s.Modules, mod)
701 s.sort()
702}
703
704// prune is used to remove any resources that are no longer required
705func (s *State) prune() {
706 if s == nil {
707 return
708 }
709
710 // Filter out empty modules.
711 // A module is always assumed to have a path, and it's length isn't always
712 // bounds checked later on. Modules may be "emptied" during destroy, but we
713 // never want to store those in the state.
714 for i := 0; i < len(s.Modules); i++ {
715 if s.Modules[i] == nil || len(s.Modules[i].Path) == 0 {
716 s.Modules = append(s.Modules[:i], s.Modules[i+1:]...)
717 i--
718 }
719 }
720
721 for _, mod := range s.Modules {
722 mod.prune()
723 }
724 if s.Remote != nil && s.Remote.Empty() {
725 s.Remote = nil
726 }
727}
728
729// sort sorts the modules
730func (s *State) sort() {
731 sort.Sort(moduleStateSort(s.Modules))
732
733 // Allow modules to be sorted
734 for _, m := range s.Modules {
735 if m != nil {
736 m.sort()
737 }
738 }
739}
740
741func (s *State) String() string {
742 if s == nil {
743 return "<nil>"
744 }
745 s.Lock()
746 defer s.Unlock()
747
748 var buf bytes.Buffer
749 for _, m := range s.Modules {
750 mStr := m.String()
751
752 // If we're the root module, we just write the output directly.
753 if reflect.DeepEqual(m.Path, rootModulePath) {
754 buf.WriteString(mStr + "\n")
755 continue
756 }
757
758 buf.WriteString(fmt.Sprintf("module.%s:\n", strings.Join(m.Path[1:], ".")))
759
760 s := bufio.NewScanner(strings.NewReader(mStr))
761 for s.Scan() {
762 text := s.Text()
763 if text != "" {
764 text = " " + text
765 }
766
767 buf.WriteString(fmt.Sprintf("%s\n", text))
768 }
769 }
770
771 return strings.TrimSpace(buf.String())
772}
773
774// BackendState stores the configuration to connect to a remote backend.
775type BackendState struct {
107c1cdb
ND
776 Type string `json:"type"` // Backend type
777 ConfigRaw json.RawMessage `json:"config"` // Backend raw config
778 Hash uint64 `json:"hash"` // Hash of portion of configuration from config files
bae9f6d2
JC
779}
780
781// Empty returns true if BackendState has no state.
782func (s *BackendState) Empty() bool {
783 return s == nil || s.Type == ""
784}
785
107c1cdb
ND
786// Config decodes the type-specific configuration object using the provided
787// schema and returns the result as a cty.Value.
788//
789// An error is returned if the stored configuration does not conform to the
790// given schema.
791func (s *BackendState) Config(schema *configschema.Block) (cty.Value, error) {
792 ty := schema.ImpliedType()
bae9f6d2 793 if s == nil {
107c1cdb 794 return cty.NullVal(ty), nil
bae9f6d2 795 }
107c1cdb
ND
796 return ctyjson.Unmarshal(s.ConfigRaw, ty)
797}
bae9f6d2 798
107c1cdb
ND
799// SetConfig replaces (in-place) the type-specific configuration object using
800// the provided value and associated schema.
801//
802// An error is returned if the given value does not conform to the implied
803// type of the schema.
804func (s *BackendState) SetConfig(val cty.Value, schema *configschema.Block) error {
805 ty := schema.ImpliedType()
806 buf, err := ctyjson.Marshal(val, ty)
807 if err != nil {
808 return err
bae9f6d2 809 }
107c1cdb
ND
810 s.ConfigRaw = buf
811 return nil
812}
bae9f6d2 813
107c1cdb
ND
814// ForPlan produces an alternative representation of the reciever that is
815// suitable for storing in a plan. The current workspace must additionally
816// be provided, to be stored alongside the backend configuration.
817//
818// The backend configuration schema is required in order to properly
819// encode the backend-specific configuration settings.
820func (s *BackendState) ForPlan(schema *configschema.Block, workspaceName string) (*plans.Backend, error) {
821 if s == nil {
822 return nil, nil
823 }
824
825 configVal, err := s.Config(schema)
826 if err != nil {
827 return nil, errwrap.Wrapf("failed to decode backend config: {{err}}", err)
828 }
829 return plans.NewBackend(s.Type, configVal, schema, workspaceName)
bae9f6d2
JC
830}
831
832// RemoteState is used to track the information about a remote
833// state store that we push/pull state to.
834type RemoteState struct {
835 // Type controls the client we use for the remote state
836 Type string `json:"type"`
837
838 // Config is used to store arbitrary configuration that
839 // is type specific
840 Config map[string]string `json:"config"`
841
842 mu sync.Mutex
843}
844
845func (s *RemoteState) Lock() { s.mu.Lock() }
846func (s *RemoteState) Unlock() { s.mu.Unlock() }
847
848func (r *RemoteState) init() {
849 r.Lock()
850 defer r.Unlock()
851
852 if r.Config == nil {
853 r.Config = make(map[string]string)
854 }
855}
856
857func (r *RemoteState) deepcopy() *RemoteState {
858 r.Lock()
859 defer r.Unlock()
860
861 confCopy := make(map[string]string, len(r.Config))
862 for k, v := range r.Config {
863 confCopy[k] = v
864 }
865 return &RemoteState{
866 Type: r.Type,
867 Config: confCopy,
868 }
869}
870
871func (r *RemoteState) Empty() bool {
872 if r == nil {
873 return true
874 }
875 r.Lock()
876 defer r.Unlock()
877
878 return r.Type == ""
879}
880
881func (r *RemoteState) Equals(other *RemoteState) bool {
882 r.Lock()
883 defer r.Unlock()
884
885 if r.Type != other.Type {
886 return false
887 }
888 if len(r.Config) != len(other.Config) {
889 return false
890 }
891 for k, v := range r.Config {
892 if other.Config[k] != v {
893 return false
894 }
895 }
896 return true
897}
898
899// OutputState is used to track the state relevant to a single output.
900type OutputState struct {
901 // Sensitive describes whether the output is considered sensitive,
902 // which may lead to masking the value on screen in some cases.
903 Sensitive bool `json:"sensitive"`
904 // Type describes the structure of Value. Valid values are "string",
905 // "map" and "list"
906 Type string `json:"type"`
907 // Value contains the value of the output, in the structure described
908 // by the Type field.
909 Value interface{} `json:"value"`
910
911 mu sync.Mutex
912}
913
914func (s *OutputState) Lock() { s.mu.Lock() }
915func (s *OutputState) Unlock() { s.mu.Unlock() }
916
917func (s *OutputState) String() string {
918 return fmt.Sprintf("%#v", s.Value)
919}
920
921// Equal compares two OutputState structures for equality. nil values are
922// considered equal.
923func (s *OutputState) Equal(other *OutputState) bool {
924 if s == nil && other == nil {
925 return true
926 }
927
928 if s == nil || other == nil {
929 return false
930 }
931 s.Lock()
932 defer s.Unlock()
933
934 if s.Type != other.Type {
935 return false
936 }
937
938 if s.Sensitive != other.Sensitive {
939 return false
940 }
941
942 if !reflect.DeepEqual(s.Value, other.Value) {
943 return false
944 }
945
946 return true
947}
948
949func (s *OutputState) deepcopy() *OutputState {
950 if s == nil {
951 return nil
952 }
953
954 stateCopy, err := copystructure.Config{Lock: true}.Copy(s)
955 if err != nil {
956 panic(fmt.Errorf("Error copying output value: %s", err))
957 }
958
959 return stateCopy.(*OutputState)
960}
961
962// ModuleState is used to track all the state relevant to a single
963// module. Previous to Terraform 0.3, all state belonged to the "root"
964// module.
965type ModuleState struct {
966 // Path is the import path from the root module. Modules imports are
967 // always disjoint, so the path represents amodule tree
968 Path []string `json:"path"`
969
15c0b25d
AP
970 // Locals are kept only transiently in-memory, because we can always
971 // re-compute them.
972 Locals map[string]interface{} `json:"-"`
973
bae9f6d2
JC
974 // Outputs declared by the module and maintained for each module
975 // even though only the root module technically needs to be kept.
976 // This allows operators to inspect values at the boundaries.
977 Outputs map[string]*OutputState `json:"outputs"`
978
979 // Resources is a mapping of the logically named resource to
980 // the state of the resource. Each resource may actually have
981 // N instances underneath, although a user only needs to think
982 // about the 1:1 case.
983 Resources map[string]*ResourceState `json:"resources"`
984
985 // Dependencies are a list of things that this module relies on
986 // existing to remain intact. For example: an module may depend
987 // on a VPC ID given by an aws_vpc resource.
988 //
989 // Terraform uses this information to build valid destruction
990 // orders and to warn the user if they're destroying a module that
991 // another resource depends on.
992 //
993 // Things can be put into this list that may not be managed by
994 // Terraform. If Terraform doesn't find a matching ID in the
995 // overall state, then it assumes it isn't managed and doesn't
996 // worry about it.
997 Dependencies []string `json:"depends_on"`
998
999 mu sync.Mutex
1000}
1001
1002func (s *ModuleState) Lock() { s.mu.Lock() }
1003func (s *ModuleState) Unlock() { s.mu.Unlock() }
1004
1005// Equal tests whether one module state is equal to another.
1006func (m *ModuleState) Equal(other *ModuleState) bool {
1007 m.Lock()
1008 defer m.Unlock()
1009
1010 // Paths must be equal
1011 if !reflect.DeepEqual(m.Path, other.Path) {
1012 return false
1013 }
1014
1015 // Outputs must be equal
1016 if len(m.Outputs) != len(other.Outputs) {
1017 return false
1018 }
1019 for k, v := range m.Outputs {
1020 if !other.Outputs[k].Equal(v) {
1021 return false
1022 }
1023 }
1024
1025 // Dependencies must be equal. This sorts these in place but
1026 // this shouldn't cause any problems.
1027 sort.Strings(m.Dependencies)
1028 sort.Strings(other.Dependencies)
1029 if len(m.Dependencies) != len(other.Dependencies) {
1030 return false
1031 }
1032 for i, d := range m.Dependencies {
1033 if other.Dependencies[i] != d {
1034 return false
1035 }
1036 }
1037
1038 // Resources must be equal
1039 if len(m.Resources) != len(other.Resources) {
1040 return false
1041 }
1042 for k, r := range m.Resources {
1043 otherR, ok := other.Resources[k]
1044 if !ok {
1045 return false
1046 }
1047
1048 if !r.Equal(otherR) {
1049 return false
1050 }
1051 }
1052
1053 return true
1054}
1055
1056// IsRoot says whether or not this module diff is for the root module.
1057func (m *ModuleState) IsRoot() bool {
1058 m.Lock()
1059 defer m.Unlock()
1060 return reflect.DeepEqual(m.Path, rootModulePath)
1061}
1062
1063// IsDescendent returns true if other is a descendent of this module.
1064func (m *ModuleState) IsDescendent(other *ModuleState) bool {
1065 m.Lock()
1066 defer m.Unlock()
1067
1068 i := len(m.Path)
1069 return len(other.Path) > i && reflect.DeepEqual(other.Path[:i], m.Path)
1070}
1071
1072// Orphans returns a list of keys of resources that are in the State
1073// but aren't present in the configuration itself. Hence, these keys
1074// represent the state of resources that are orphans.
107c1cdb 1075func (m *ModuleState) Orphans(c *configs.Module) []addrs.ResourceInstance {
bae9f6d2
JC
1076 m.Lock()
1077 defer m.Unlock()
1078
107c1cdb 1079 inConfig := make(map[string]struct{})
bae9f6d2 1080 if c != nil {
107c1cdb
ND
1081 for _, r := range c.ManagedResources {
1082 inConfig[r.Addr().String()] = struct{}{}
1083 }
1084 for _, r := range c.DataResources {
1085 inConfig[r.Addr().String()] = struct{}{}
bae9f6d2
JC
1086 }
1087 }
1088
107c1cdb
ND
1089 var result []addrs.ResourceInstance
1090 for k := range m.Resources {
1091 // Since we've not yet updated state to use our new address format,
1092 // we need to do some shimming here.
1093 legacyAddr, err := parseResourceAddressInternal(k)
1094 if err != nil {
1095 // Suggests that the user tampered with the state, since we always
1096 // generate valid internal addresses.
1097 log.Printf("ModuleState has invalid resource key %q. Ignoring.", k)
1098 continue
1099 }
15c0b25d 1100
107c1cdb
ND
1101 addr := legacyAddr.AbsResourceInstanceAddr().Resource
1102 compareKey := addr.Resource.String() // compare by resource address, ignoring instance key
1103 if _, exists := inConfig[compareKey]; !exists {
1104 result = append(result, addr)
1105 }
1106 }
15c0b25d
AP
1107 return result
1108}
1109
1110// RemovedOutputs returns a list of outputs that are in the State but aren't
1111// present in the configuration itself.
107c1cdb
ND
1112func (s *ModuleState) RemovedOutputs(outputs map[string]*configs.Output) []addrs.OutputValue {
1113 if outputs == nil {
1114 // If we got no output map at all then we'll just treat our set of
1115 // configured outputs as empty, since that suggests that they've all
1116 // been removed by removing their containing module.
1117 outputs = make(map[string]*configs.Output)
15c0b25d
AP
1118 }
1119
107c1cdb
ND
1120 s.Lock()
1121 defer s.Unlock()
15c0b25d 1122
107c1cdb
ND
1123 var ret []addrs.OutputValue
1124 for n := range s.Outputs {
1125 if _, declared := outputs[n]; !declared {
1126 ret = append(ret, addrs.OutputValue{
1127 Name: n,
1128 })
1129 }
bae9f6d2
JC
1130 }
1131
107c1cdb 1132 return ret
bae9f6d2
JC
1133}
1134
1135// View returns a view with the given resource prefix.
1136func (m *ModuleState) View(id string) *ModuleState {
1137 if m == nil {
1138 return m
1139 }
1140
1141 r := m.deepcopy()
1142 for k, _ := range r.Resources {
1143 if id == k || strings.HasPrefix(k, id+".") {
1144 continue
1145 }
1146
1147 delete(r.Resources, k)
1148 }
1149
1150 return r
1151}
1152
1153func (m *ModuleState) init() {
1154 m.Lock()
1155 defer m.Unlock()
1156
1157 if m.Path == nil {
1158 m.Path = []string{}
1159 }
1160 if m.Outputs == nil {
1161 m.Outputs = make(map[string]*OutputState)
1162 }
1163 if m.Resources == nil {
1164 m.Resources = make(map[string]*ResourceState)
1165 }
1166
1167 if m.Dependencies == nil {
1168 m.Dependencies = make([]string, 0)
1169 }
1170
1171 for _, rs := range m.Resources {
1172 rs.init()
1173 }
1174}
1175
1176func (m *ModuleState) deepcopy() *ModuleState {
1177 if m == nil {
1178 return nil
1179 }
1180
1181 stateCopy, err := copystructure.Config{Lock: true}.Copy(m)
1182 if err != nil {
1183 panic(err)
1184 }
1185
1186 return stateCopy.(*ModuleState)
1187}
1188
1189// prune is used to remove any resources that are no longer required
1190func (m *ModuleState) prune() {
1191 m.Lock()
1192 defer m.Unlock()
1193
1194 for k, v := range m.Resources {
1195 if v == nil || (v.Primary == nil || v.Primary.ID == "") && len(v.Deposed) == 0 {
1196 delete(m.Resources, k)
1197 continue
1198 }
1199
1200 v.prune()
1201 }
1202
1203 for k, v := range m.Outputs {
1204 if v.Value == config.UnknownVariableValue {
1205 delete(m.Outputs, k)
1206 }
1207 }
1208
1209 m.Dependencies = uniqueStrings(m.Dependencies)
1210}
1211
1212func (m *ModuleState) sort() {
1213 for _, v := range m.Resources {
1214 v.sort()
1215 }
1216}
1217
1218func (m *ModuleState) String() string {
1219 m.Lock()
1220 defer m.Unlock()
1221
1222 var buf bytes.Buffer
1223
1224 if len(m.Resources) == 0 {
1225 buf.WriteString("<no state>")
1226 }
1227
1228 names := make([]string, 0, len(m.Resources))
1229 for name, _ := range m.Resources {
1230 names = append(names, name)
1231 }
1232
1233 sort.Sort(resourceNameSort(names))
1234
1235 for _, k := range names {
1236 rs := m.Resources[k]
1237 var id string
1238 if rs.Primary != nil {
1239 id = rs.Primary.ID
1240 }
1241 if id == "" {
1242 id = "<not created>"
1243 }
1244
1245 taintStr := ""
1246 if rs.Primary.Tainted {
1247 taintStr = " (tainted)"
1248 }
1249
1250 deposedStr := ""
1251 if len(rs.Deposed) > 0 {
1252 deposedStr = fmt.Sprintf(" (%d deposed)", len(rs.Deposed))
1253 }
1254
1255 buf.WriteString(fmt.Sprintf("%s:%s%s\n", k, taintStr, deposedStr))
1256 buf.WriteString(fmt.Sprintf(" ID = %s\n", id))
1257 if rs.Provider != "" {
1258 buf.WriteString(fmt.Sprintf(" provider = %s\n", rs.Provider))
1259 }
1260
1261 var attributes map[string]string
1262 if rs.Primary != nil {
1263 attributes = rs.Primary.Attributes
1264 }
1265 attrKeys := make([]string, 0, len(attributes))
1266 for ak, _ := range attributes {
1267 if ak == "id" {
1268 continue
1269 }
1270
1271 attrKeys = append(attrKeys, ak)
1272 }
1273
1274 sort.Strings(attrKeys)
1275
1276 for _, ak := range attrKeys {
1277 av := attributes[ak]
1278 buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av))
1279 }
1280
1281 for idx, t := range rs.Deposed {
1282 taintStr := ""
1283 if t.Tainted {
1284 taintStr = " (tainted)"
1285 }
1286 buf.WriteString(fmt.Sprintf(" Deposed ID %d = %s%s\n", idx+1, t.ID, taintStr))
1287 }
1288
1289 if len(rs.Dependencies) > 0 {
1290 buf.WriteString(fmt.Sprintf("\n Dependencies:\n"))
1291 for _, dep := range rs.Dependencies {
1292 buf.WriteString(fmt.Sprintf(" %s\n", dep))
1293 }
1294 }
1295 }
1296
1297 if len(m.Outputs) > 0 {
1298 buf.WriteString("\nOutputs:\n\n")
1299
1300 ks := make([]string, 0, len(m.Outputs))
1301 for k, _ := range m.Outputs {
1302 ks = append(ks, k)
1303 }
1304
1305 sort.Strings(ks)
1306
1307 for _, k := range ks {
1308 v := m.Outputs[k]
1309 switch vTyped := v.Value.(type) {
1310 case string:
1311 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped))
1312 case []interface{}:
1313 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped))
1314 case map[string]interface{}:
1315 var mapKeys []string
1316 for key, _ := range vTyped {
1317 mapKeys = append(mapKeys, key)
1318 }
1319 sort.Strings(mapKeys)
1320
1321 var mapBuf bytes.Buffer
1322 mapBuf.WriteString("{")
1323 for _, key := range mapKeys {
1324 mapBuf.WriteString(fmt.Sprintf("%s:%s ", key, vTyped[key]))
1325 }
1326 mapBuf.WriteString("}")
1327
1328 buf.WriteString(fmt.Sprintf("%s = %s\n", k, mapBuf.String()))
1329 }
1330 }
1331 }
1332
1333 return buf.String()
1334}
1335
15c0b25d
AP
1336func (m *ModuleState) Empty() bool {
1337 return len(m.Locals) == 0 && len(m.Outputs) == 0 && len(m.Resources) == 0
1338}
1339
bae9f6d2
JC
1340// ResourceStateKey is a structured representation of the key used for the
1341// ModuleState.Resources mapping
1342type ResourceStateKey struct {
1343 Name string
1344 Type string
1345 Mode config.ResourceMode
1346 Index int
1347}
1348
1349// Equal determines whether two ResourceStateKeys are the same
1350func (rsk *ResourceStateKey) Equal(other *ResourceStateKey) bool {
1351 if rsk == nil || other == nil {
1352 return false
1353 }
1354 if rsk.Mode != other.Mode {
1355 return false
1356 }
1357 if rsk.Type != other.Type {
1358 return false
1359 }
1360 if rsk.Name != other.Name {
1361 return false
1362 }
1363 if rsk.Index != other.Index {
1364 return false
1365 }
1366 return true
1367}
1368
1369func (rsk *ResourceStateKey) String() string {
1370 if rsk == nil {
1371 return ""
1372 }
1373 var prefix string
1374 switch rsk.Mode {
1375 case config.ManagedResourceMode:
1376 prefix = ""
1377 case config.DataResourceMode:
1378 prefix = "data."
1379 default:
1380 panic(fmt.Errorf("unknown resource mode %s", rsk.Mode))
1381 }
1382 if rsk.Index == -1 {
1383 return fmt.Sprintf("%s%s.%s", prefix, rsk.Type, rsk.Name)
1384 }
1385 return fmt.Sprintf("%s%s.%s.%d", prefix, rsk.Type, rsk.Name, rsk.Index)
1386}
1387
1388// ParseResourceStateKey accepts a key in the format used by
1389// ModuleState.Resources and returns a resource name and resource index. In the
1390// state, a resource has the format "type.name.index" or "type.name". In the
1391// latter case, the index is returned as -1.
1392func ParseResourceStateKey(k string) (*ResourceStateKey, error) {
1393 parts := strings.Split(k, ".")
1394 mode := config.ManagedResourceMode
1395 if len(parts) > 0 && parts[0] == "data" {
1396 mode = config.DataResourceMode
1397 // Don't need the constant "data" prefix for parsing
1398 // now that we've figured out the mode.
1399 parts = parts[1:]
1400 }
1401 if len(parts) < 2 || len(parts) > 3 {
1402 return nil, fmt.Errorf("Malformed resource state key: %s", k)
1403 }
1404 rsk := &ResourceStateKey{
1405 Mode: mode,
1406 Type: parts[0],
1407 Name: parts[1],
1408 Index: -1,
1409 }
1410 if len(parts) == 3 {
1411 index, err := strconv.Atoi(parts[2])
1412 if err != nil {
1413 return nil, fmt.Errorf("Malformed resource state key index: %s", k)
1414 }
1415 rsk.Index = index
1416 }
1417 return rsk, nil
1418}
1419
1420// ResourceState holds the state of a resource that is used so that
1421// a provider can find and manage an existing resource as well as for
1422// storing attributes that are used to populate variables of child
1423// resources.
1424//
1425// Attributes has attributes about the created resource that are
1426// queryable in interpolation: "${type.id.attr}"
1427//
1428// Extra is just extra data that a provider can return that we store
1429// for later, but is not exposed in any way to the user.
1430//
1431type ResourceState struct {
1432 // This is filled in and managed by Terraform, and is the resource
1433 // type itself such as "mycloud_instance". If a resource provider sets
1434 // this value, it won't be persisted.
1435 Type string `json:"type"`
1436
1437 // Dependencies are a list of things that this resource relies on
1438 // existing to remain intact. For example: an AWS instance might
1439 // depend on a subnet (which itself might depend on a VPC, and so
1440 // on).
1441 //
1442 // Terraform uses this information to build valid destruction
1443 // orders and to warn the user if they're destroying a resource that
1444 // another resource depends on.
1445 //
1446 // Things can be put into this list that may not be managed by
1447 // Terraform. If Terraform doesn't find a matching ID in the
1448 // overall state, then it assumes it isn't managed and doesn't
1449 // worry about it.
1450 Dependencies []string `json:"depends_on"`
1451
1452 // Primary is the current active instance for this resource.
1453 // It can be replaced but only after a successful creation.
1454 // This is the instances on which providers will act.
1455 Primary *InstanceState `json:"primary"`
1456
1457 // Deposed is used in the mechanics of CreateBeforeDestroy: the existing
1458 // Primary is Deposed to get it out of the way for the replacement Primary to
1459 // be created by Apply. If the replacement Primary creates successfully, the
1460 // Deposed instance is cleaned up.
1461 //
1462 // If there were problems creating the replacement Primary, the Deposed
1463 // instance and the (now tainted) replacement Primary will be swapped so the
1464 // tainted replacement will be cleaned up instead.
1465 //
1466 // An instance will remain in the Deposed list until it is successfully
1467 // destroyed and purged.
1468 Deposed []*InstanceState `json:"deposed"`
1469
1470 // Provider is used when a resource is connected to a provider with an alias.
1471 // If this string is empty, the resource is connected to the default provider,
1472 // e.g. "aws_instance" goes with the "aws" provider.
1473 // If the resource block contained a "provider" key, that value will be set here.
1474 Provider string `json:"provider"`
1475
1476 mu sync.Mutex
1477}
1478
1479func (s *ResourceState) Lock() { s.mu.Lock() }
1480func (s *ResourceState) Unlock() { s.mu.Unlock() }
1481
1482// Equal tests whether two ResourceStates are equal.
1483func (s *ResourceState) Equal(other *ResourceState) bool {
1484 s.Lock()
1485 defer s.Unlock()
1486
1487 if s.Type != other.Type {
1488 return false
1489 }
1490
1491 if s.Provider != other.Provider {
1492 return false
1493 }
1494
1495 // Dependencies must be equal
1496 sort.Strings(s.Dependencies)
1497 sort.Strings(other.Dependencies)
1498 if len(s.Dependencies) != len(other.Dependencies) {
1499 return false
1500 }
1501 for i, d := range s.Dependencies {
1502 if other.Dependencies[i] != d {
1503 return false
1504 }
1505 }
1506
1507 // States must be equal
1508 if !s.Primary.Equal(other.Primary) {
1509 return false
1510 }
1511
1512 return true
1513}
1514
1515// Taint marks a resource as tainted.
1516func (s *ResourceState) Taint() {
1517 s.Lock()
1518 defer s.Unlock()
1519
1520 if s.Primary != nil {
1521 s.Primary.Tainted = true
1522 }
1523}
1524
1525// Untaint unmarks a resource as tainted.
1526func (s *ResourceState) Untaint() {
1527 s.Lock()
1528 defer s.Unlock()
1529
1530 if s.Primary != nil {
1531 s.Primary.Tainted = false
1532 }
1533}
1534
107c1cdb
ND
1535// ProviderAddr returns the provider address for the receiver, by parsing the
1536// string representation saved in state. An error can be returned if the
1537// value in state is corrupt.
1538func (s *ResourceState) ProviderAddr() (addrs.AbsProviderConfig, error) {
1539 var diags tfdiags.Diagnostics
1540
1541 str := s.Provider
1542 traversal, travDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
1543 diags = diags.Append(travDiags)
1544 if travDiags.HasErrors() {
1545 return addrs.AbsProviderConfig{}, diags.Err()
1546 }
1547
1548 addr, addrDiags := addrs.ParseAbsProviderConfig(traversal)
1549 diags = diags.Append(addrDiags)
1550 return addr, diags.Err()
1551}
1552
bae9f6d2
JC
1553func (s *ResourceState) init() {
1554 s.Lock()
1555 defer s.Unlock()
1556
1557 if s.Primary == nil {
1558 s.Primary = &InstanceState{}
1559 }
1560 s.Primary.init()
1561
1562 if s.Dependencies == nil {
1563 s.Dependencies = []string{}
1564 }
1565
1566 if s.Deposed == nil {
1567 s.Deposed = make([]*InstanceState, 0)
1568 }
1569}
1570
1571func (s *ResourceState) deepcopy() *ResourceState {
1572 copy, err := copystructure.Config{Lock: true}.Copy(s)
1573 if err != nil {
1574 panic(err)
1575 }
1576
1577 return copy.(*ResourceState)
1578}
1579
1580// prune is used to remove any instances that are no longer required
1581func (s *ResourceState) prune() {
1582 s.Lock()
1583 defer s.Unlock()
1584
1585 n := len(s.Deposed)
1586 for i := 0; i < n; i++ {
1587 inst := s.Deposed[i]
1588 if inst == nil || inst.ID == "" {
1589 copy(s.Deposed[i:], s.Deposed[i+1:])
1590 s.Deposed[n-1] = nil
1591 n--
1592 i--
1593 }
1594 }
1595 s.Deposed = s.Deposed[:n]
1596
1597 s.Dependencies = uniqueStrings(s.Dependencies)
1598}
1599
1600func (s *ResourceState) sort() {
1601 s.Lock()
1602 defer s.Unlock()
1603
1604 sort.Strings(s.Dependencies)
1605}
1606
1607func (s *ResourceState) String() string {
1608 s.Lock()
1609 defer s.Unlock()
1610
1611 var buf bytes.Buffer
1612 buf.WriteString(fmt.Sprintf("Type = %s", s.Type))
1613 return buf.String()
1614}
1615
1616// InstanceState is used to track the unique state information belonging
1617// to a given instance.
1618type InstanceState struct {
1619 // A unique ID for this resource. This is opaque to Terraform
1620 // and is only meant as a lookup mechanism for the providers.
1621 ID string `json:"id"`
1622
1623 // Attributes are basic information about the resource. Any keys here
1624 // are accessible in variable format within Terraform configurations:
1625 // ${resourcetype.name.attribute}.
1626 Attributes map[string]string `json:"attributes"`
1627
1628 // Ephemeral is used to store any state associated with this instance
1629 // that is necessary for the Terraform run to complete, but is not
1630 // persisted to a state file.
1631 Ephemeral EphemeralState `json:"-"`
1632
1633 // Meta is a simple K/V map that is persisted to the State but otherwise
1634 // ignored by Terraform core. It's meant to be used for accounting by
1635 // external client code. The value here must only contain Go primitives
1636 // and collections.
1637 Meta map[string]interface{} `json:"meta"`
1638
1639 // Tainted is used to mark a resource for recreation.
1640 Tainted bool `json:"tainted"`
1641
1642 mu sync.Mutex
1643}
1644
1645func (s *InstanceState) Lock() { s.mu.Lock() }
1646func (s *InstanceState) Unlock() { s.mu.Unlock() }
1647
1648func (s *InstanceState) init() {
1649 s.Lock()
1650 defer s.Unlock()
1651
1652 if s.Attributes == nil {
1653 s.Attributes = make(map[string]string)
1654 }
1655 if s.Meta == nil {
1656 s.Meta = make(map[string]interface{})
1657 }
1658 s.Ephemeral.init()
1659}
1660
107c1cdb
ND
1661// NewInstanceStateShimmedFromValue is a shim method to lower a new-style
1662// object value representing the attributes of an instance object into the
1663// legacy InstanceState representation.
1664//
1665// This is for shimming to old components only and should not be used in new code.
1666func NewInstanceStateShimmedFromValue(state cty.Value, schemaVersion int) *InstanceState {
1667 attrs := hcl2shim.FlatmapValueFromHCL2(state)
1668 return &InstanceState{
1669 ID: attrs["id"],
1670 Attributes: attrs,
1671 Meta: map[string]interface{}{
1672 "schema_version": schemaVersion,
1673 },
1674 }
1675}
1676
1677// AttrsAsObjectValue shims from the legacy InstanceState representation to
1678// a new-style cty object value representation of the state attributes, using
1679// the given type for guidance.
1680//
1681// The given type must be the implied type of the schema of the resource type
1682// of the object whose state is being converted, or the result is undefined.
1683//
1684// This is for shimming from old components only and should not be used in
1685// new code.
1686func (s *InstanceState) AttrsAsObjectValue(ty cty.Type) (cty.Value, error) {
1687 if s == nil {
1688 // if the state is nil, we need to construct a complete cty.Value with
1689 // null attributes, rather than a single cty.NullVal(ty)
1690 s = &InstanceState{}
1691 }
1692
1693 if s.Attributes == nil {
1694 s.Attributes = map[string]string{}
1695 }
1696
1697 // make sure ID is included in the attributes. The InstanceState.ID value
1698 // takes precedence.
1699 if s.ID != "" {
1700 s.Attributes["id"] = s.ID
1701 }
1702
1703 return hcl2shim.HCL2ValueFromFlatmap(s.Attributes, ty)
1704}
1705
bae9f6d2
JC
1706// Copy all the Fields from another InstanceState
1707func (s *InstanceState) Set(from *InstanceState) {
1708 s.Lock()
1709 defer s.Unlock()
1710
1711 from.Lock()
1712 defer from.Unlock()
1713
1714 s.ID = from.ID
1715 s.Attributes = from.Attributes
1716 s.Ephemeral = from.Ephemeral
1717 s.Meta = from.Meta
1718 s.Tainted = from.Tainted
1719}
1720
1721func (s *InstanceState) DeepCopy() *InstanceState {
1722 copy, err := copystructure.Config{Lock: true}.Copy(s)
1723 if err != nil {
1724 panic(err)
1725 }
1726
1727 return copy.(*InstanceState)
1728}
1729
1730func (s *InstanceState) Empty() bool {
1731 if s == nil {
1732 return true
1733 }
1734 s.Lock()
1735 defer s.Unlock()
1736
1737 return s.ID == ""
1738}
1739
1740func (s *InstanceState) Equal(other *InstanceState) bool {
1741 // Short circuit some nil checks
1742 if s == nil || other == nil {
1743 return s == other
1744 }
1745 s.Lock()
1746 defer s.Unlock()
1747
1748 // IDs must be equal
1749 if s.ID != other.ID {
1750 return false
1751 }
1752
1753 // Attributes must be equal
1754 if len(s.Attributes) != len(other.Attributes) {
1755 return false
1756 }
1757 for k, v := range s.Attributes {
1758 otherV, ok := other.Attributes[k]
1759 if !ok {
1760 return false
1761 }
1762
1763 if v != otherV {
1764 return false
1765 }
1766 }
1767
1768 // Meta must be equal
1769 if len(s.Meta) != len(other.Meta) {
1770 return false
1771 }
1772 if s.Meta != nil && other.Meta != nil {
1773 // We only do the deep check if both are non-nil. If one is nil
1774 // we treat it as equal since their lengths are both zero (check
1775 // above).
15c0b25d
AP
1776 //
1777 // Since this can contain numeric values that may change types during
1778 // serialization, let's compare the serialized values.
1779 sMeta, err := json.Marshal(s.Meta)
1780 if err != nil {
1781 // marshaling primitives shouldn't ever error out
1782 panic(err)
1783 }
1784 otherMeta, err := json.Marshal(other.Meta)
1785 if err != nil {
1786 panic(err)
1787 }
1788
1789 if !bytes.Equal(sMeta, otherMeta) {
bae9f6d2
JC
1790 return false
1791 }
1792 }
1793
1794 if s.Tainted != other.Tainted {
1795 return false
1796 }
1797
1798 return true
1799}
1800
1801// MergeDiff takes a ResourceDiff and merges the attributes into
1802// this resource state in order to generate a new state. This new
1803// state can be used to provide updated attribute lookups for
1804// variable interpolation.
1805//
1806// If the diff attribute requires computing the value, and hence
1807// won't be available until apply, the value is replaced with the
1808// computeID.
1809func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState {
1810 result := s.DeepCopy()
1811 if result == nil {
1812 result = new(InstanceState)
1813 }
1814 result.init()
1815
1816 if s != nil {
1817 s.Lock()
1818 defer s.Unlock()
1819 for k, v := range s.Attributes {
1820 result.Attributes[k] = v
1821 }
1822 }
1823 if d != nil {
1824 for k, diff := range d.CopyAttributes() {
1825 if diff.NewRemoved {
1826 delete(result.Attributes, k)
1827 continue
1828 }
1829 if diff.NewComputed {
1830 result.Attributes[k] = config.UnknownVariableValue
1831 continue
1832 }
1833
1834 result.Attributes[k] = diff.New
1835 }
1836 }
1837
1838 return result
1839}
1840
1841func (s *InstanceState) String() string {
107c1cdb
ND
1842 notCreated := "<not created>"
1843
1844 if s == nil {
1845 return notCreated
1846 }
1847
bae9f6d2
JC
1848 s.Lock()
1849 defer s.Unlock()
1850
1851 var buf bytes.Buffer
1852
107c1cdb
ND
1853 if s.ID == "" {
1854 return notCreated
bae9f6d2
JC
1855 }
1856
1857 buf.WriteString(fmt.Sprintf("ID = %s\n", s.ID))
1858
1859 attributes := s.Attributes
1860 attrKeys := make([]string, 0, len(attributes))
1861 for ak, _ := range attributes {
1862 if ak == "id" {
1863 continue
1864 }
1865
1866 attrKeys = append(attrKeys, ak)
1867 }
1868 sort.Strings(attrKeys)
1869
1870 for _, ak := range attrKeys {
1871 av := attributes[ak]
1872 buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av))
1873 }
1874
1875 buf.WriteString(fmt.Sprintf("Tainted = %t\n", s.Tainted))
1876
1877 return buf.String()
1878}
1879
1880// EphemeralState is used for transient state that is only kept in-memory
1881type EphemeralState struct {
1882 // ConnInfo is used for the providers to export information which is
1883 // used to connect to the resource for provisioning. For example,
1884 // this could contain SSH or WinRM credentials.
1885 ConnInfo map[string]string `json:"-"`
1886
1887 // Type is used to specify the resource type for this instance. This is only
1888 // required for import operations (as documented). If the documentation
1889 // doesn't state that you need to set this, then don't worry about
1890 // setting it.
1891 Type string `json:"-"`
1892}
1893
1894func (e *EphemeralState) init() {
1895 if e.ConnInfo == nil {
1896 e.ConnInfo = make(map[string]string)
1897 }
1898}
1899
1900func (e *EphemeralState) DeepCopy() *EphemeralState {
1901 copy, err := copystructure.Config{Lock: true}.Copy(e)
1902 if err != nil {
1903 panic(err)
1904 }
1905
1906 return copy.(*EphemeralState)
1907}
1908
1909type jsonStateVersionIdentifier struct {
1910 Version int `json:"version"`
1911}
1912
1913// Check if this is a V0 format - the magic bytes at the start of the file
1914// should be "tfstate" if so. We no longer support upgrading this type of
1915// state but return an error message explaining to a user how they can
1916// upgrade via the 0.6.x series.
1917func testForV0State(buf *bufio.Reader) error {
1918 start, err := buf.Peek(len("tfstate"))
1919 if err != nil {
1920 return fmt.Errorf("Failed to check for magic bytes: %v", err)
1921 }
1922 if string(start) == "tfstate" {
1923 return fmt.Errorf("Terraform 0.7 no longer supports upgrading the binary state\n" +
1924 "format which was used prior to Terraform 0.3. Please upgrade\n" +
1925 "this state file using Terraform 0.6.16 prior to using it with\n" +
1926 "Terraform 0.7.")
1927 }
1928
1929 return nil
1930}
1931
1932// ErrNoState is returned by ReadState when the io.Reader contains no data
1933var ErrNoState = errors.New("no state")
1934
1935// ReadState reads a state structure out of a reader in the format that
1936// was written by WriteState.
1937func ReadState(src io.Reader) (*State, error) {
15c0b25d
AP
1938 // check for a nil file specifically, since that produces a platform
1939 // specific error if we try to use it in a bufio.Reader.
1940 if f, ok := src.(*os.File); ok && f == nil {
1941 return nil, ErrNoState
1942 }
1943
bae9f6d2 1944 buf := bufio.NewReader(src)
15c0b25d 1945
bae9f6d2 1946 if _, err := buf.Peek(1); err != nil {
15c0b25d
AP
1947 if err == io.EOF {
1948 return nil, ErrNoState
1949 }
1950 return nil, err
bae9f6d2
JC
1951 }
1952
1953 if err := testForV0State(buf); err != nil {
1954 return nil, err
1955 }
1956
1957 // If we are JSON we buffer the whole thing in memory so we can read it twice.
1958 // This is suboptimal, but will work for now.
1959 jsonBytes, err := ioutil.ReadAll(buf)
1960 if err != nil {
1961 return nil, fmt.Errorf("Reading state file failed: %v", err)
1962 }
1963
1964 versionIdentifier := &jsonStateVersionIdentifier{}
1965 if err := json.Unmarshal(jsonBytes, versionIdentifier); err != nil {
1966 return nil, fmt.Errorf("Decoding state file version failed: %v", err)
1967 }
1968
1969 var result *State
1970 switch versionIdentifier.Version {
1971 case 0:
1972 return nil, fmt.Errorf("State version 0 is not supported as JSON.")
1973 case 1:
1974 v1State, err := ReadStateV1(jsonBytes)
1975 if err != nil {
1976 return nil, err
1977 }
1978
1979 v2State, err := upgradeStateV1ToV2(v1State)
1980 if err != nil {
1981 return nil, err
1982 }
1983
1984 v3State, err := upgradeStateV2ToV3(v2State)
1985 if err != nil {
1986 return nil, err
1987 }
1988
1989 // increment the Serial whenever we upgrade state
1990 v3State.Serial++
1991 result = v3State
1992 case 2:
1993 v2State, err := ReadStateV2(jsonBytes)
1994 if err != nil {
1995 return nil, err
1996 }
1997 v3State, err := upgradeStateV2ToV3(v2State)
1998 if err != nil {
1999 return nil, err
2000 }
2001
2002 v3State.Serial++
2003 result = v3State
2004 case 3:
2005 v3State, err := ReadStateV3(jsonBytes)
2006 if err != nil {
2007 return nil, err
2008 }
2009
2010 result = v3State
2011 default:
2012 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.",
15c0b25d 2013 tfversion.SemVer.String(), versionIdentifier.Version)
bae9f6d2
JC
2014 }
2015
2016 // If we reached this place we must have a result set
2017 if result == nil {
2018 panic("resulting state in load not set, assertion failed")
2019 }
2020
2021 // Prune the state when read it. Its possible to write unpruned states or
2022 // for a user to make a state unpruned (nil-ing a module state for example).
2023 result.prune()
2024
2025 // Validate the state file is valid
2026 if err := result.Validate(); err != nil {
2027 return nil, err
2028 }
2029
2030 return result, nil
2031}
2032
2033func ReadStateV1(jsonBytes []byte) (*stateV1, error) {
2034 v1State := &stateV1{}
2035 if err := json.Unmarshal(jsonBytes, v1State); err != nil {
2036 return nil, fmt.Errorf("Decoding state file failed: %v", err)
2037 }
2038
2039 if v1State.Version != 1 {
2040 return nil, fmt.Errorf("Decoded state version did not match the decoder selection: "+
2041 "read %d, expected 1", v1State.Version)
2042 }
2043
2044 return v1State, nil
2045}
2046
2047func ReadStateV2(jsonBytes []byte) (*State, error) {
2048 state := &State{}
2049 if err := json.Unmarshal(jsonBytes, state); err != nil {
2050 return nil, fmt.Errorf("Decoding state file failed: %v", err)
2051 }
2052
2053 // Check the version, this to ensure we don't read a future
2054 // version that we don't understand
2055 if state.Version > StateVersion {
2056 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.",
15c0b25d 2057 tfversion.SemVer.String(), state.Version)
bae9f6d2
JC
2058 }
2059
2060 // Make sure the version is semantic
2061 if state.TFVersion != "" {
2062 if _, err := version.NewVersion(state.TFVersion); err != nil {
2063 return nil, fmt.Errorf(
2064 "State contains invalid version: %s\n\n"+
2065 "Terraform validates the version format prior to writing it. This\n"+
2066 "means that this is invalid of the state becoming corrupted through\n"+
2067 "some external means. Please manually modify the Terraform version\n"+
2068 "field to be a proper semantic version.",
2069 state.TFVersion)
2070 }
2071 }
2072
2073 // catch any unitialized fields in the state
2074 state.init()
2075
2076 // Sort it
2077 state.sort()
2078
2079 return state, nil
2080}
2081
2082func ReadStateV3(jsonBytes []byte) (*State, error) {
2083 state := &State{}
2084 if err := json.Unmarshal(jsonBytes, state); err != nil {
2085 return nil, fmt.Errorf("Decoding state file failed: %v", err)
2086 }
2087
2088 // Check the version, this to ensure we don't read a future
2089 // version that we don't understand
2090 if state.Version > StateVersion {
2091 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.",
15c0b25d 2092 tfversion.SemVer.String(), state.Version)
bae9f6d2
JC
2093 }
2094
2095 // Make sure the version is semantic
2096 if state.TFVersion != "" {
2097 if _, err := version.NewVersion(state.TFVersion); err != nil {
2098 return nil, fmt.Errorf(
2099 "State contains invalid version: %s\n\n"+
2100 "Terraform validates the version format prior to writing it. This\n"+
2101 "means that this is invalid of the state becoming corrupted through\n"+
2102 "some external means. Please manually modify the Terraform version\n"+
2103 "field to be a proper semantic version.",
2104 state.TFVersion)
2105 }
2106 }
2107
2108 // catch any unitialized fields in the state
2109 state.init()
2110
2111 // Sort it
2112 state.sort()
2113
2114 // Now we write the state back out to detect any changes in normaliztion.
2115 // If our state is now written out differently, bump the serial number to
2116 // prevent conflicts.
2117 var buf bytes.Buffer
2118 err := WriteState(state, &buf)
2119 if err != nil {
2120 return nil, err
2121 }
2122
2123 if !bytes.Equal(jsonBytes, buf.Bytes()) {
2124 log.Println("[INFO] state modified during read or write. incrementing serial number")
2125 state.Serial++
2126 }
2127
2128 return state, nil
2129}
2130
2131// WriteState writes a state somewhere in a binary format.
2132func WriteState(d *State, dst io.Writer) error {
2133 // writing a nil state is a noop.
2134 if d == nil {
2135 return nil
2136 }
2137
2138 // make sure we have no uninitialized fields
2139 d.init()
2140
2141 // Make sure it is sorted
2142 d.sort()
2143
2144 // Ensure the version is set
2145 d.Version = StateVersion
2146
2147 // If the TFVersion is set, verify it. We used to just set the version
2148 // here, but this isn't safe since it changes the MD5 sum on some remote
2149 // state storage backends such as Atlas. We now leave it be if needed.
2150 if d.TFVersion != "" {
2151 if _, err := version.NewVersion(d.TFVersion); err != nil {
2152 return fmt.Errorf(
2153 "Error writing state, invalid version: %s\n\n"+
2154 "The Terraform version when writing the state must be a semantic\n"+
2155 "version.",
2156 d.TFVersion)
2157 }
2158 }
2159
2160 // Encode the data in a human-friendly way
2161 data, err := json.MarshalIndent(d, "", " ")
2162 if err != nil {
2163 return fmt.Errorf("Failed to encode state: %s", err)
2164 }
2165
2166 // We append a newline to the data because MarshalIndent doesn't
2167 data = append(data, '\n')
2168
2169 // Write the data out to the dst
2170 if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil {
2171 return fmt.Errorf("Failed to write state: %v", err)
2172 }
2173
2174 return nil
2175}
2176
2177// resourceNameSort implements the sort.Interface to sort name parts lexically for
2178// strings and numerically for integer indexes.
2179type resourceNameSort []string
2180
2181func (r resourceNameSort) Len() int { return len(r) }
2182func (r resourceNameSort) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
2183
2184func (r resourceNameSort) Less(i, j int) bool {
2185 iParts := strings.Split(r[i], ".")
2186 jParts := strings.Split(r[j], ".")
2187
2188 end := len(iParts)
2189 if len(jParts) < end {
2190 end = len(jParts)
2191 }
2192
2193 for idx := 0; idx < end; idx++ {
2194 if iParts[idx] == jParts[idx] {
2195 continue
2196 }
2197
2198 // sort on the first non-matching part
2199 iInt, iIntErr := strconv.Atoi(iParts[idx])
2200 jInt, jIntErr := strconv.Atoi(jParts[idx])
2201
2202 switch {
2203 case iIntErr == nil && jIntErr == nil:
2204 // sort numerically if both parts are integers
2205 return iInt < jInt
2206 case iIntErr == nil:
2207 // numbers sort before strings
2208 return true
2209 case jIntErr == nil:
2210 return false
2211 default:
2212 return iParts[idx] < jParts[idx]
2213 }
2214 }
2215
2216 return r[i] < r[j]
2217}
2218
2219// moduleStateSort implements sort.Interface to sort module states
2220type moduleStateSort []*ModuleState
2221
2222func (s moduleStateSort) Len() int {
2223 return len(s)
2224}
2225
2226func (s moduleStateSort) Less(i, j int) bool {
2227 a := s[i]
2228 b := s[j]
2229
2230 // If either is nil, then the nil one is "less" than
2231 if a == nil || b == nil {
2232 return a == nil
2233 }
2234
2235 // If the lengths are different, then the shorter one always wins
2236 if len(a.Path) != len(b.Path) {
2237 return len(a.Path) < len(b.Path)
2238 }
2239
2240 // Otherwise, compare lexically
2241 return strings.Join(a.Path, ".") < strings.Join(b.Path, ".")
2242}
2243
2244func (s moduleStateSort) Swap(i, j int) {
2245 s[i], s[j] = s[j], s[i]
2246}
2247
2248const stateValidateErrMultiModule = `
2249Multiple modules with the same path: %s
2250
2251This means that there are multiple entries in the "modules" field
2252in your state file that point to the same module. This will cause Terraform
2253to behave in unexpected and error prone ways and is invalid. Please back up
2254and modify your state file manually to resolve this.
2255`