terraform: hooks around provisioners

This commit is contained in:
Mitchell Hashimoto 2014-07-27 09:00:34 -07:00
parent 9759606989
commit 78c32ac196
6 changed files with 117 additions and 3 deletions

View File

@ -574,6 +574,11 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
delete(c.state.Tainted, r.Id) delete(c.state.Tainted, r.Id)
} else { } else {
c.state.Resources[r.Id] = rs c.state.Resources[r.Id] = rs
// We always mark the resource as tainted here in case a
// hook below during provisioning does HookActionStop. This
// way, we keep the resource tainted.
c.state.Tainted[r.Id] = struct{}{}
} }
c.sl.Unlock() c.sl.Unlock()
@ -585,19 +590,28 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
// was an error during the provider apply. // was an error during the provider apply.
tainted := false tainted := false
if applyerr == nil && r.State.ID == "" && len(r.Provisioners) > 0 { if applyerr == nil && r.State.ID == "" && len(r.Provisioners) > 0 {
for _, h := range c.hooks {
handleHook(h.PreProvisionResource(r.Id, r.State))
}
if err := c.applyProvisioners(r, rs); err != nil { if err := c.applyProvisioners(r, rs); err != nil {
errs = append(errs, err) errs = append(errs, err)
tainted = true tainted = true
} }
}
if tainted { for _, h := range c.hooks {
log.Printf("[DEBUG] %s: Marking as tainted", r.Id) handleHook(h.PostProvisionResource(r.Id, r.State))
}
}
c.sl.Lock() c.sl.Lock()
if tainted {
log.Printf("[DEBUG] %s: Marking as tainted", r.Id)
c.state.Tainted[r.Id] = struct{}{} c.state.Tainted[r.Id] = struct{}{}
c.sl.Unlock() } else {
delete(c.state.Tainted, r.Id)
} }
c.sl.Unlock()
// Update the state for the resource itself // Update the state for the resource itself
r.State = rs r.State = rs
@ -671,9 +685,17 @@ func (c *Context) applyProvisioners(r *Resource, rs *ResourceState) error {
rs.ConnInfo = overlay rs.ConnInfo = overlay
// Invoke the Provisioner // Invoke the Provisioner
for _, h := range c.hooks {
handleHook(h.PreProvision(r.Id, prov.Type))
}
if err := prov.Provisioner.Apply(rs, prov.Config); err != nil { if err := prov.Provisioner.Apply(rs, prov.Config); err != nil {
return err return err
} }
for _, h := range c.hooks {
handleHook(h.PostProvision(r.Id, prov.Type))
}
} }
return nil return nil

View File

@ -864,6 +864,7 @@ func graphMapResourceProvisioners(g *depgraph.Graph,
// Save the provisioner // Save the provisioner
rn.Resource.Provisioners = append(rn.Resource.Provisioners, &ResourceProvisionerConfig{ rn.Resource.Provisioners = append(rn.Resource.Provisioners, &ResourceProvisionerConfig{
Type: p.Type,
Provisioner: provisioner, Provisioner: provisioner,
Config: NewResourceConfig(p.RawConfig), Config: NewResourceConfig(p.RawConfig),
RawConfig: p.RawConfig, RawConfig: p.RawConfig,

View File

@ -32,6 +32,12 @@ type Hook interface {
PreDiff(string, *ResourceState) (HookAction, error) PreDiff(string, *ResourceState) (HookAction, error)
PostDiff(string, *ResourceDiff) (HookAction, error) PostDiff(string, *ResourceDiff) (HookAction, error)
// Provisioning hooks
PreProvisionResource(string, *ResourceState) (HookAction, error)
PostProvisionResource(string, *ResourceState) (HookAction, error)
PreProvision(string, string) (HookAction, error)
PostProvision(string, string) (HookAction, error)
// PreRefresh and PostRefresh are called before and after a single // PreRefresh and PostRefresh are called before and after a single
// resource state is refreshed, respectively. // resource state is refreshed, respectively.
PreRefresh(string, *ResourceState) (HookAction, error) PreRefresh(string, *ResourceState) (HookAction, error)
@ -59,6 +65,22 @@ func (*NilHook) PostDiff(string, *ResourceDiff) (HookAction, error) {
return HookActionContinue, nil return HookActionContinue, nil
} }
func (*NilHook) PreProvisionResource(string, *ResourceState) (HookAction, error) {
return HookActionContinue, nil
}
func (*NilHook) PostProvisionResource(string, *ResourceState) (HookAction, error) {
return HookActionContinue, nil
}
func (*NilHook) PreProvision(string, string) (HookAction, error) {
return HookActionContinue, nil
}
func (*NilHook) PostProvision(string, string) (HookAction, error) {
return HookActionContinue, nil
}
func (*NilHook) PreRefresh(string, *ResourceState) (HookAction, error) { func (*NilHook) PreRefresh(string, *ResourceState) (HookAction, error) {
return HookActionContinue, nil return HookActionContinue, nil
} }

View File

@ -29,6 +29,30 @@ type MockHook struct {
PostDiffReturn HookAction PostDiffReturn HookAction
PostDiffError error PostDiffError error
PreProvisionResourceCalled bool
PreProvisionResourceId string
PreProvisionResourceState *ResourceState
PreProvisionResourceReturn HookAction
PreProvisionResourceError error
PostProvisionResourceCalled bool
PostProvisionResourceId string
PostProvisionResourceState *ResourceState
PostProvisionResourceReturn HookAction
PostProvisionResourceError error
PreProvisionCalled bool
PreProvisionId string
PreProvisionProvisionerId string
PreProvisionReturn HookAction
PreProvisionError error
PostProvisionCalled bool
PostProvisionId string
PostProvisionProvisionerId string
PostProvisionReturn HookAction
PostProvisionError error
PostRefreshCalled bool PostRefreshCalled bool
PostRefreshId string PostRefreshId string
PostRefreshState *ResourceState PostRefreshState *ResourceState
@ -72,6 +96,34 @@ func (h *MockHook) PostDiff(n string, d *ResourceDiff) (HookAction, error) {
return h.PostDiffReturn, h.PostDiffError return h.PostDiffReturn, h.PostDiffError
} }
func (h *MockHook) PreProvisionResource(id string, s *ResourceState) (HookAction, error) {
h.PreProvisionResourceCalled = true
h.PreProvisionResourceId = id
h.PreProvisionResourceState = s
return h.PreProvisionResourceReturn, h.PreProvisionResourceError
}
func (h *MockHook) PostProvisionResource(id string, s *ResourceState) (HookAction, error) {
h.PostProvisionResourceCalled = true
h.PostProvisionResourceId = id
h.PostProvisionResourceState = s
return h.PostProvisionResourceReturn, h.PostProvisionResourceError
}
func (h *MockHook) PreProvision(id, provId string) (HookAction, error) {
h.PreProvisionCalled = true
h.PreProvisionId = id
h.PreProvisionProvisionerId = provId
return h.PreProvisionReturn, h.PreProvisionError
}
func (h *MockHook) PostProvision(id, provId string) (HookAction, error) {
h.PostProvisionCalled = true
h.PostProvisionId = id
h.PostProvisionProvisionerId = provId
return h.PostProvisionReturn, h.PostProvisionError
}
func (h *MockHook) PreRefresh(n string, s *ResourceState) (HookAction, error) { func (h *MockHook) PreRefresh(n string, s *ResourceState) (HookAction, error) {
h.PreRefreshCalled = true h.PreRefreshCalled = true
h.PreRefreshId = n h.PreRefreshId = n

View File

@ -26,6 +26,22 @@ func (h *stopHook) PostDiff(string, *ResourceDiff) (HookAction, error) {
return h.hook() return h.hook()
} }
func (h *stopHook) PreProvisionResource(string, *ResourceState) (HookAction, error) {
return h.hook()
}
func (h *stopHook) PostProvisionResource(string, *ResourceState) (HookAction, error) {
return h.hook()
}
func (h *stopHook) PreProvision(string, string) (HookAction, error) {
return h.hook()
}
func (h *stopHook) PostProvision(string, string) (HookAction, error) {
return h.hook()
}
func (h *stopHook) PreRefresh(string, *ResourceState) (HookAction, error) { func (h *stopHook) PreRefresh(string, *ResourceState) (HookAction, error) {
return h.hook() return h.hook()
} }

View File

@ -15,6 +15,7 @@ import (
// configuration instead of instantiating a new Provisioner for each // configuration instead of instantiating a new Provisioner for each
// resource. // resource.
type ResourceProvisionerConfig struct { type ResourceProvisionerConfig struct {
Type string
Provisioner ResourceProvisioner Provisioner ResourceProvisioner
Config *ResourceConfig Config *ResourceConfig
RawConfig *config.RawConfig RawConfig *config.RawConfig