terraform: PostProvision hook gets the error from the provision step

This commit is contained in:
Mitchell Hashimoto 2017-01-20 20:21:12 -08:00
parent b56ee1a169
commit f40fdde708
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
5 changed files with 56 additions and 12 deletions

View File

@ -4043,6 +4043,46 @@ aws_instance.foo:
}
}
// Verify that a normal provisioner with on_failure "continue" records
// the error with the hook.
func TestContext2Apply_provisionerFailContinueHook(t *testing.T) {
h := new(MockHook)
m := testModule(t, "apply-provisioner-fail-continue")
p := testProvider("aws")
pr := testProvisioner()
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
return fmt.Errorf("provisioner error")
}
ctx := testContext2(t, &ContextOpts{
Module: m,
Hooks: []Hook{h},
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
Provisioners: map[string]ResourceProvisionerFactory{
"shell": testProvisionerFuncFixed(pr),
},
})
if _, err := ctx.Plan(); err != nil {
t.Fatalf("err: %s", err)
}
if _, err := ctx.Apply(); err != nil {
t.Fatalf("err: %s", err)
}
if !h.PostProvisionCalled {
t.Fatal("PostProvision not called")
}
if h.PostProvisionErrorArg == nil {
t.Fatal("should have error")
}
}
func TestContext2Apply_provisionerDestroy(t *testing.T) {
m := testModule(t, "apply-provisioner-destroy")
p := testProvider("aws")

View File

@ -307,6 +307,13 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*config.Provision
// Invoke the Provisioner
output := CallbackUIOutput{OutputFn: outputFn}
applyErr := provisioner.Apply(&output, state, provConfig)
// Call post hook
hookErr := ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostProvision(n.Info, prov.Type, applyErr)
})
// Handle the error before we deal with the hook
if applyErr != nil {
// Determine failure behavior
switch prov.OnFailure {
@ -320,14 +327,9 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*config.Provision
}
}
{
// Call post hook
err := ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostProvision(n.Info, prov.Type)
})
if err != nil {
return err
}
// Deal with the hook
if hookErr != nil {
return hookErr
}
}

View File

@ -42,7 +42,7 @@ type Hook interface {
PreProvisionResource(*InstanceInfo, *InstanceState) (HookAction, error)
PostProvisionResource(*InstanceInfo, *InstanceState) (HookAction, error)
PreProvision(*InstanceInfo, string) (HookAction, error)
PostProvision(*InstanceInfo, string) (HookAction, error)
PostProvision(*InstanceInfo, string, error) (HookAction, error)
ProvisionOutput(*InstanceInfo, string, string)
// PreRefresh and PostRefresh are called before and after a single
@ -92,7 +92,7 @@ func (*NilHook) PreProvision(*InstanceInfo, string) (HookAction, error) {
return HookActionContinue, nil
}
func (*NilHook) PostProvision(*InstanceInfo, string) (HookAction, error) {
func (*NilHook) PostProvision(*InstanceInfo, string, error) (HookAction, error) {
return HookActionContinue, nil
}

View File

@ -55,6 +55,7 @@ type MockHook struct {
PostProvisionCalled bool
PostProvisionInfo *InstanceInfo
PostProvisionProvisionerId string
PostProvisionErrorArg error
PostProvisionReturn HookAction
PostProvisionError error
@ -170,13 +171,14 @@ func (h *MockHook) PreProvision(n *InstanceInfo, provId string) (HookAction, err
return h.PreProvisionReturn, h.PreProvisionError
}
func (h *MockHook) PostProvision(n *InstanceInfo, provId string) (HookAction, error) {
func (h *MockHook) PostProvision(n *InstanceInfo, provId string, err error) (HookAction, error) {
h.Lock()
defer h.Unlock()
h.PostProvisionCalled = true
h.PostProvisionInfo = n
h.PostProvisionProvisionerId = provId
h.PostProvisionErrorArg = err
return h.PostProvisionReturn, h.PostProvisionError
}

View File

@ -38,7 +38,7 @@ func (h *stopHook) PreProvision(*InstanceInfo, string) (HookAction, error) {
return h.hook()
}
func (h *stopHook) PostProvision(*InstanceInfo, string) (HookAction, error) {
func (h *stopHook) PostProvision(*InstanceInfo, string, error) (HookAction, error) {
return h.hook()
}