github.com/federicobaldo/terraform@v0.6.15-0.20160323222747-b20f680cbf05/terraform/eval_ignore_changes.go (about) 1 package terraform 2 3 import ( 4 "log" 5 "strings" 6 7 "github.com/hashicorp/terraform/config" 8 ) 9 10 // EvalIgnoreChanges is an EvalNode implementation that removes diff 11 // attributes if their name matches names provided by the resource's 12 // IgnoreChanges lifecycle. 13 type EvalIgnoreChanges struct { 14 Resource *config.Resource 15 Diff **InstanceDiff 16 WasChangeType *DiffChangeType 17 } 18 19 func (n *EvalIgnoreChanges) Eval(ctx EvalContext) (interface{}, error) { 20 if n.Diff == nil || *n.Diff == nil || n.Resource == nil || n.Resource.Id() == "" { 21 return nil, nil 22 } 23 24 diff := *n.Diff 25 ignoreChanges := n.Resource.Lifecycle.IgnoreChanges 26 27 if len(ignoreChanges) == 0 { 28 return nil, nil 29 } 30 31 changeType := diff.ChangeType() 32 // Let the passed in change type pointer override what the diff currently has. 33 if n.WasChangeType != nil && *n.WasChangeType != DiffInvalid { 34 changeType = *n.WasChangeType 35 } 36 37 // If we're just creating the resource, we shouldn't alter the 38 // Diff at all 39 if changeType == DiffCreate { 40 return nil, nil 41 } 42 43 for _, ignoredName := range ignoreChanges { 44 for name := range diff.Attributes { 45 if strings.HasPrefix(name, ignoredName) { 46 delete(diff.Attributes, name) 47 } 48 } 49 } 50 51 // If we are replacing the resource, then we expect there to be a bunch of 52 // extraneous attribute diffs we need to filter out for the other 53 // non-requires-new attributes going from "" -> "configval" or "" -> 54 // "<computed>". Filtering these out allows us to see if we might be able to 55 // skip this diff altogether. 56 if changeType == DiffDestroyCreate { 57 for k, v := range diff.Attributes { 58 if v.Empty() || v.NewComputed { 59 delete(diff.Attributes, k) 60 } 61 } 62 63 // Here we emulate the implementation of diff.RequiresNew() with one small 64 // tweak, we ignore the "id" attribute diff that gets added by EvalDiff, 65 // since that was added in reaction to RequiresNew being true. 66 requiresNewAfterIgnores := false 67 for k, v := range diff.Attributes { 68 if k == "id" { 69 continue 70 } 71 if v.RequiresNew == true { 72 requiresNewAfterIgnores = true 73 } 74 } 75 76 // Here we undo the two reactions to RequireNew in EvalDiff - the "id" 77 // attribute diff and the Destroy boolean field 78 if !requiresNewAfterIgnores { 79 log.Printf("[DEBUG] Removing 'id' diff and setting Destroy to false " + 80 "because after ignore_changes, this diff no longer requires replacement") 81 delete(diff.Attributes, "id") 82 diff.Destroy = false 83 } 84 } 85 86 return nil, nil 87 }