2014-05-28 15:56:43 -05:00
|
|
|
package terraform
|
|
|
|
|
2014-06-05 04:32:10 -05:00
|
|
|
import (
|
2014-06-10 13:22:32 -05:00
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"sort"
|
2014-06-10 13:30:54 -05:00
|
|
|
"strings"
|
2014-06-05 04:32:10 -05:00
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
2014-05-28 15:56:43 -05:00
|
|
|
// Diff tracks the differences between resources to apply.
|
|
|
|
type Diff struct {
|
2014-06-10 13:22:32 -05:00
|
|
|
Resources map[string]*ResourceDiff
|
2014-06-05 04:32:10 -05:00
|
|
|
once sync.Once
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Diff) init() {
|
|
|
|
d.once.Do(func() {
|
2014-06-10 13:22:32 -05:00
|
|
|
if d.Resources == nil {
|
|
|
|
d.Resources = make(map[string]*ResourceDiff)
|
|
|
|
}
|
2014-06-05 04:32:10 -05:00
|
|
|
})
|
2014-05-28 15:56:43 -05:00
|
|
|
}
|
|
|
|
|
2014-06-10 13:22:32 -05:00
|
|
|
// String outputs the diff in a long but command-line friendly output
|
|
|
|
// format that users can read to quickly inspect a diff.
|
|
|
|
func (d *Diff) String() string {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
|
|
|
names := make([]string, 0, len(d.Resources))
|
|
|
|
for name, _ := range d.Resources {
|
|
|
|
names = append(names, name)
|
|
|
|
}
|
|
|
|
sort.Strings(names)
|
|
|
|
|
|
|
|
for _, name := range names {
|
2014-06-10 13:27:17 -05:00
|
|
|
rdiff := d.Resources[name]
|
|
|
|
|
2014-06-10 13:37:04 -05:00
|
|
|
crud := "UPDATE"
|
|
|
|
if rdiff.RequiresNew() {
|
|
|
|
crud = "CREATE"
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.WriteString(fmt.Sprintf(
|
|
|
|
"%s: %s\n",
|
|
|
|
crud,
|
|
|
|
name))
|
2014-06-10 13:22:32 -05:00
|
|
|
|
2014-06-10 13:30:54 -05:00
|
|
|
keyLen := 0
|
2014-06-10 13:27:17 -05:00
|
|
|
keys := make([]string, 0, len(rdiff.Attributes))
|
|
|
|
for key, _ := range rdiff.Attributes {
|
|
|
|
keys = append(keys, key)
|
2014-06-10 13:30:54 -05:00
|
|
|
if len(key) > keyLen {
|
|
|
|
keyLen = len(key)
|
|
|
|
}
|
2014-06-10 13:27:17 -05:00
|
|
|
}
|
|
|
|
sort.Strings(keys)
|
|
|
|
|
|
|
|
for _, attrK := range keys {
|
|
|
|
attrDiff := rdiff.Attributes[attrK]
|
|
|
|
|
2014-06-10 13:22:32 -05:00
|
|
|
v := attrDiff.New
|
|
|
|
if attrDiff.NewComputed {
|
|
|
|
v = "<computed>"
|
|
|
|
}
|
|
|
|
|
2014-06-10 13:33:59 -05:00
|
|
|
newResource := ""
|
|
|
|
if attrDiff.RequiresNew {
|
|
|
|
newResource = " (forces new resource)"
|
|
|
|
}
|
|
|
|
|
2014-06-10 13:22:32 -05:00
|
|
|
buf.WriteString(fmt.Sprintf(
|
2014-06-10 13:33:59 -05:00
|
|
|
" %s:%s %#v => %#v%s\n",
|
2014-06-10 13:22:32 -05:00
|
|
|
attrK,
|
2014-06-10 13:30:54 -05:00
|
|
|
strings.Repeat(" ", keyLen-len(attrK)),
|
2014-06-10 13:22:32 -05:00
|
|
|
attrDiff.Old,
|
2014-06-10 13:33:59 -05:00
|
|
|
v,
|
|
|
|
newResource))
|
2014-06-10 13:22:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf.String()
|
|
|
|
}
|
2014-06-10 13:37:04 -05:00
|
|
|
|
|
|
|
// ResourceDiff is the diff of a resource from some state to another.
|
|
|
|
type ResourceDiff struct {
|
|
|
|
Attributes map[string]*ResourceAttrDiff
|
|
|
|
}
|
|
|
|
|
|
|
|
// ResourceAttrDiff is the diff of a single attribute of a resource.
|
|
|
|
type ResourceAttrDiff struct {
|
|
|
|
Old string // Old Value
|
|
|
|
New string // New Value
|
|
|
|
NewComputed bool // True if new value is computed (unknown currently)
|
|
|
|
RequiresNew bool // True if change requires new resource
|
|
|
|
}
|
|
|
|
|
|
|
|
// RequiresNew returns true if the diff requires the creation of a new
|
|
|
|
// resource (implying the destruction of the old).
|
|
|
|
func (d *ResourceDiff) RequiresNew() bool {
|
|
|
|
for _, rd := range d.Attributes {
|
|
|
|
if rd.RequiresNew {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|