opentofu/terraform/diff.go

109 lines
2.2 KiB
Go
Raw Normal View History

package terraform
2014-06-05 04:32:10 -05:00
import (
2014-06-10 13:22:32 -05:00
"bytes"
"fmt"
"sort"
"strings"
2014-06-05 04:32:10 -05:00
"sync"
)
// 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-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 {
rdiff := d.Resources[name]
crud := "UPDATE"
if rdiff.RequiresNew() {
crud = "CREATE"
}
buf.WriteString(fmt.Sprintf(
"%s: %s\n",
crud,
name))
2014-06-10 13:22:32 -05:00
keyLen := 0
keys := make([]string, 0, len(rdiff.Attributes))
for key, _ := range rdiff.Attributes {
keys = append(keys, key)
if len(key) > keyLen {
keyLen = len(key)
}
}
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>"
}
newResource := ""
if attrDiff.RequiresNew {
newResource = " (forces new resource)"
}
2014-06-10 13:22:32 -05:00
buf.WriteString(fmt.Sprintf(
" %s:%s %#v => %#v%s\n",
2014-06-10 13:22:32 -05:00
attrK,
strings.Repeat(" ", keyLen-len(attrK)),
2014-06-10 13:22:32 -05:00
attrDiff.Old,
v,
newResource))
2014-06-10 13:22:32 -05:00
}
}
return buf.String()
}
// 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
}