From 5a84a24d12b1b2f9b99fbaa3e6e0233de2a42f58 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 26 Jun 2014 22:09:16 -0700 Subject: [PATCH] terraform: pre/post apply hook --- terraform/hook.go | 13 +++++++++++++ terraform/hook_mock.go | 28 ++++++++++++++++++++++++++++ terraform/terraform.go | 10 ++++++++++ terraform/terraform_test.go | 24 ++++++++++++++++++++++++ 4 files changed, 75 insertions(+) diff --git a/terraform/hook.go b/terraform/hook.go index 33411c84a..5aad18887 100644 --- a/terraform/hook.go +++ b/terraform/hook.go @@ -21,6 +21,11 @@ const ( // NilHook into your struct, which implements all of the interface but does // nothing. Then, override only the functions you want to implement. type Hook interface { + // PreApply and PostApply are called before and after a single + // resource is applied. + PreApply(string, *ResourceState, *ResourceDiff) (HookAction, error) + PostApply(string, *ResourceState) (HookAction, error) + // PreDiff and PostDiff are called before and after a single resource // resource is diffed. PreDiff(string, *ResourceState) (HookAction, error) @@ -37,6 +42,14 @@ type Hook interface { // and only implement the functions you are interested in. type NilHook struct{} +func (*NilHook) PreApply(string, *ResourceState, *ResourceDiff) (HookAction, error) { + return HookActionContinue, nil +} + +func (*NilHook) PostApply(string, *ResourceState) (HookAction, error) { + return HookActionContinue, nil +} + func (*NilHook) PreDiff(string, *ResourceState) (HookAction, error) { return HookActionContinue, nil } diff --git a/terraform/hook_mock.go b/terraform/hook_mock.go index f78ebe05a..9baed1d34 100644 --- a/terraform/hook_mock.go +++ b/terraform/hook_mock.go @@ -3,6 +3,19 @@ package terraform // MockHook is an implementation of Hook that can be used for tests. // It records all of its function calls. type MockHook struct { + PreApplyCalled bool + PreApplyId string + PreApplyDiff *ResourceDiff + PreApplyState *ResourceState + PreApplyReturn HookAction + PreApplyError error + + PostApplyCalled bool + PostApplyId string + PostApplyState *ResourceState + PostApplyReturn HookAction + PostApplyError error + PreDiffCalled bool PreDiffId string PreDiffState *ResourceState @@ -28,6 +41,21 @@ type MockHook struct { PreRefreshError error } +func (h *MockHook) PreApply(n string, s *ResourceState, d *ResourceDiff) (HookAction, error) { + h.PreApplyCalled = true + h.PreApplyId = n + h.PreApplyDiff = d + h.PreApplyState = s + return h.PreApplyReturn, h.PreApplyError +} + +func (h *MockHook) PostApply(n string, s *ResourceState) (HookAction, error) { + h.PostApplyCalled = true + h.PostApplyId = n + h.PostApplyState = s + return h.PostApplyReturn, h.PostApplyError +} + func (h *MockHook) PreDiff(n string, s *ResourceState) (HookAction, error) { h.PreDiffCalled = true h.PreDiffId = n diff --git a/terraform/terraform.go b/terraform/terraform.go index 9be29dec8..c6e426881 100644 --- a/terraform/terraform.go +++ b/terraform/terraform.go @@ -180,6 +180,11 @@ func (t *Terraform) applyWalkFn( // TODO(mitchellh): we need to verify the diff doesn't change // anything and that the diff has no computed values (pre-computed) + for _, h := range t.hooks { + // TODO: return value + h.PreApply(r.Id, r.State, diff) + } + // With the completed diff, apply! rs, err := r.Provider.Apply(r.State, diff) if err != nil { @@ -216,6 +221,11 @@ func (t *Terraform) applyWalkFn( result.Resources[r.Id] = rs l.Unlock() + for _, h := range t.hooks { + // TODO: return value + h.PostApply(r.Id, r.State) + } + // Determine the new state and update variables vars := make(map[string]string) for ak, av := range rs.Attributes { diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index d067f1d66..43bf84e0b 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -63,6 +63,30 @@ func TestTerraformApply_compute(t *testing.T) { } } +func TestTerraformApply_hook(t *testing.T) { + c := testConfig(t, "apply-good") + h := new(MockHook) + tf := testTerraform2(t, &Config{ + Hooks: []Hook{h}, + }) + + p, err := tf.Plan(c, nil, nil) + if err != nil { + t.Fatalf("err: %s", err) + } + + if _, err := tf.Apply(p); err != nil { + t.Fatalf("err: %s", err) + } + + if !h.PreApplyCalled { + t.Fatal("should be called") + } + if !h.PostApplyCalled { + t.Fatal("should be called") + } +} + func TestTerraformApply_unknownAttribute(t *testing.T) { c := testConfig(t, "apply-unknown") tf := testTerraform2(t, nil)