terraform: pre/post apply hook

This commit is contained in:
Mitchell Hashimoto 2014-06-26 22:09:16 -07:00
parent d3f2547f86
commit 5a84a24d12
4 changed files with 75 additions and 0 deletions

View File

@ -21,6 +21,11 @@ const (
// NilHook into your struct, which implements all of the interface but does // NilHook into your struct, which implements all of the interface but does
// nothing. Then, override only the functions you want to implement. // nothing. Then, override only the functions you want to implement.
type Hook interface { 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 // PreDiff and PostDiff are called before and after a single resource
// resource is diffed. // resource is diffed.
PreDiff(string, *ResourceState) (HookAction, error) PreDiff(string, *ResourceState) (HookAction, error)
@ -37,6 +42,14 @@ type Hook interface {
// and only implement the functions you are interested in. // and only implement the functions you are interested in.
type NilHook struct{} 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) { func (*NilHook) PreDiff(string, *ResourceState) (HookAction, error) {
return HookActionContinue, nil return HookActionContinue, nil
} }

View File

@ -3,6 +3,19 @@ package terraform
// MockHook is an implementation of Hook that can be used for tests. // MockHook is an implementation of Hook that can be used for tests.
// It records all of its function calls. // It records all of its function calls.
type MockHook struct { 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 PreDiffCalled bool
PreDiffId string PreDiffId string
PreDiffState *ResourceState PreDiffState *ResourceState
@ -28,6 +41,21 @@ type MockHook struct {
PreRefreshError error 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) { func (h *MockHook) PreDiff(n string, s *ResourceState) (HookAction, error) {
h.PreDiffCalled = true h.PreDiffCalled = true
h.PreDiffId = n h.PreDiffId = n

View File

@ -180,6 +180,11 @@ func (t *Terraform) applyWalkFn(
// TODO(mitchellh): we need to verify the diff doesn't change // TODO(mitchellh): we need to verify the diff doesn't change
// anything and that the diff has no computed values (pre-computed) // 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! // With the completed diff, apply!
rs, err := r.Provider.Apply(r.State, diff) rs, err := r.Provider.Apply(r.State, diff)
if err != nil { if err != nil {
@ -216,6 +221,11 @@ func (t *Terraform) applyWalkFn(
result.Resources[r.Id] = rs result.Resources[r.Id] = rs
l.Unlock() l.Unlock()
for _, h := range t.hooks {
// TODO: return value
h.PostApply(r.Id, r.State)
}
// Determine the new state and update variables // Determine the new state and update variables
vars := make(map[string]string) vars := make(map[string]string)
for ak, av := range rs.Attributes { for ak, av := range rs.Attributes {

View File

@ -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) { func TestTerraformApply_unknownAttribute(t *testing.T) {
c := testConfig(t, "apply-unknown") c := testConfig(t, "apply-unknown")
tf := testTerraform2(t, nil) tf := testTerraform2(t, nil)