From 2cfad3fa71c32f7e93c81c705ec9725b754d2304 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 16 Jul 2014 15:58:47 -0700 Subject: [PATCH] helper/diff: can specify PreProcess functions --- helper/diff/resource_builder.go | 25 ++++++++- helper/diff/resource_builder_test.go | 82 ++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/helper/diff/resource_builder.go b/helper/diff/resource_builder.go index 62575f689..00a172f43 100644 --- a/helper/diff/resource_builder.go +++ b/helper/diff/resource_builder.go @@ -44,8 +44,16 @@ type ResourceBuilder struct { // ComputedAttrs are the attributes that are computed at // resource creation time. ComputedAttrs []string + + // PreProcess is a mapping of exact keys that are sent through + // a pre-processor before comparing values. The original value will + // be put in the "NewExtra" field of the diff. + PreProcess map[string]PreProcessFunc } +// PreProcessFunc is used with the PreProcess field in a ResourceBuilder +type PreProcessFunc func(string) string + // Diff returns the ResourceDiff for a resource given its state and // configuration. func (b *ResourceBuilder) Diff( @@ -76,10 +84,20 @@ func (b *ResourceBuilder) Diff( // Track that we saw this key seenKeys = append(seenKeys, k) + // We keep track of this in case we have a pre-processor + // so that we can store the original value still. + originalV := v + // If this key is in the cleaned config, then use that value // because it'll have its variables properly interpolated if cleanV, ok := flatConfig[k]; ok { v = cleanV + originalV = v + + // If we have a pre-processor for this, run it. + if pp, ok := b.PreProcess[k]; ok { + v = pp(k) + } } oldV, ok := s.Attributes[k] @@ -91,9 +109,10 @@ func (b *ResourceBuilder) Diff( // Record the change attrs[k] = &terraform.ResourceAttrDiff{ - Old: oldV, - New: v, - Type: terraform.DiffAttrInput, + Old: oldV, + New: v, + NewExtra: originalV, + Type: terraform.DiffAttrInput, } // If this requires a new resource, record that and flag our diff --git a/helper/diff/resource_builder_test.go b/helper/diff/resource_builder_test.go index d7e220a4f..dac74ff85 100644 --- a/helper/diff/resource_builder_test.go +++ b/helper/diff/resource_builder_test.go @@ -199,6 +199,80 @@ func TestResourceBuilder_new(t *testing.T) { } } +func TestResourceBuilder_preProcess(t *testing.T) { + rb := &ResourceBuilder{ + Attrs: map[string]AttrType{ + "foo": AttrTypeCreate, + }, + + PreProcess: map[string]PreProcessFunc{ + "foo": func(string) string { + return "bar" + }, + }, + } + + state := &terraform.ResourceState{} + c := testConfig(t, map[string]interface{}{ + "foo": "foo", + }, nil) + + diff, err := rb.Diff(state, c) + if err != nil { + t.Fatalf("err: %s", err) + } + if diff == nil { + t.Fatal("diff shold not be nil") + } + + actual := testResourceDiffStr(diff) + expected := testRBPreProcessDiff + if actual != expected { + t.Fatalf("bad: %s", actual) + } + + actual = diff.Attributes["foo"].NewExtra.(string) + expected = "foo" + if actual != expected { + t.Fatalf("bad: %#v", actual) + } +} + +func TestResourceBuilder_preProcessUnknown(t *testing.T) { + rb := &ResourceBuilder{ + Attrs: map[string]AttrType{ + "foo": AttrTypeCreate, + }, + + PreProcess: map[string]PreProcessFunc{ + "foo": func(string) string { + return "bar" + }, + }, + } + + state := &terraform.ResourceState{} + c := testConfig(t, map[string]interface{}{ + "foo": "${var.unknown}", + }, map[string]string{ + "var.unknown": config.UnknownVariableValue, + }) + + diff, err := rb.Diff(state, c) + if err != nil { + t.Fatalf("err: %s", err) + } + if diff == nil { + t.Fatal("diff shold not be nil") + } + + actual := testResourceDiffStr(diff) + expected := testRBPreProcessUnknownDiff + if actual != expected { + t.Fatalf("bad: %s", actual) + } +} + func TestResourceBuilder_requiresNew(t *testing.T) { rb := &ResourceBuilder{ ComputedAttrs: []string{"private_ip"}, @@ -338,6 +412,14 @@ const testRBNewDiff = `UPDATE OUT private_ip: "" => "" ` +const testRBPreProcessDiff = `CREATE + IN foo: "" => "bar" (forces new resource) +` + +const testRBPreProcessUnknownDiff = `CREATE + IN foo: "" => "${var.unknown}" (forces new resource) +` + const testRBRequiresNewDiff = `CREATE IN ami: "foo" => "bar" (forces new resource) OUT private_ip: "127.0.0.1" => ""