terraform: PostStateUpdate hook and EvalUpdateStateHook
This commit is contained in:
parent
bfe0edef51
commit
429711b938
|
@ -70,155 +70,3 @@ type EvalContext interface {
|
|||
// be used to modify that state.
|
||||
State() (*State, *sync.RWMutex)
|
||||
}
|
||||
|
||||
// MockEvalContext is a mock version of EvalContext that can be used
|
||||
// for tests.
|
||||
type MockEvalContext struct {
|
||||
HookCalled bool
|
||||
HookError error
|
||||
|
||||
InputCalled bool
|
||||
InputInput UIInput
|
||||
|
||||
InitProviderCalled bool
|
||||
InitProviderName string
|
||||
InitProviderProvider ResourceProvider
|
||||
InitProviderError error
|
||||
|
||||
ProviderCalled bool
|
||||
ProviderName string
|
||||
ProviderProvider ResourceProvider
|
||||
|
||||
ProviderInputCalled bool
|
||||
ProviderInputName string
|
||||
ProviderInputConfig map[string]interface{}
|
||||
|
||||
SetProviderInputCalled bool
|
||||
SetProviderInputName string
|
||||
SetProviderInputConfig map[string]interface{}
|
||||
|
||||
ConfigureProviderCalled bool
|
||||
ConfigureProviderName string
|
||||
ConfigureProviderConfig *ResourceConfig
|
||||
ConfigureProviderError error
|
||||
|
||||
ParentProviderConfigCalled bool
|
||||
ParentProviderConfigName string
|
||||
ParentProviderConfigConfig *ResourceConfig
|
||||
|
||||
InitProvisionerCalled bool
|
||||
InitProvisionerName string
|
||||
InitProvisionerProvisioner ResourceProvisioner
|
||||
InitProvisionerError error
|
||||
|
||||
ProvisionerCalled bool
|
||||
ProvisionerName string
|
||||
ProvisionerProvisioner ResourceProvisioner
|
||||
|
||||
InterpolateCalled bool
|
||||
InterpolateConfig *config.RawConfig
|
||||
InterpolateResource *Resource
|
||||
InterpolateConfigResult *ResourceConfig
|
||||
InterpolateError error
|
||||
|
||||
PathCalled bool
|
||||
PathPath []string
|
||||
|
||||
SetVariablesCalled bool
|
||||
SetVariablesVariables map[string]string
|
||||
|
||||
DiffCalled bool
|
||||
DiffDiff *Diff
|
||||
DiffLock *sync.RWMutex
|
||||
|
||||
StateCalled bool
|
||||
StateState *State
|
||||
StateLock *sync.RWMutex
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Hook(fn func(Hook) (HookAction, error)) error {
|
||||
c.HookCalled = true
|
||||
return c.HookError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Input() UIInput {
|
||||
c.InputCalled = true
|
||||
return c.InputInput
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) InitProvider(n string) (ResourceProvider, error) {
|
||||
c.InitProviderCalled = true
|
||||
c.InitProviderName = n
|
||||
return c.InitProviderProvider, c.InitProviderError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Provider(n string) ResourceProvider {
|
||||
c.ProviderCalled = true
|
||||
c.ProviderName = n
|
||||
return c.ProviderProvider
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) ConfigureProvider(n string, cfg *ResourceConfig) error {
|
||||
c.ConfigureProviderCalled = true
|
||||
c.ConfigureProviderName = n
|
||||
c.ConfigureProviderConfig = cfg
|
||||
return c.ConfigureProviderError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) ParentProviderConfig(n string) *ResourceConfig {
|
||||
c.ParentProviderConfigCalled = true
|
||||
c.ParentProviderConfigName = n
|
||||
return c.ParentProviderConfigConfig
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) ProviderInput(n string) map[string]interface{} {
|
||||
c.ProviderInputCalled = true
|
||||
c.ProviderInputName = n
|
||||
return c.ProviderInputConfig
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) SetProviderInput(n string, cfg map[string]interface{}) {
|
||||
c.SetProviderInputCalled = true
|
||||
c.SetProviderInputName = n
|
||||
c.SetProviderInputConfig = cfg
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) InitProvisioner(n string) (ResourceProvisioner, error) {
|
||||
c.InitProvisionerCalled = true
|
||||
c.InitProvisionerName = n
|
||||
return c.InitProvisionerProvisioner, c.InitProvisionerError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Provisioner(n string) ResourceProvisioner {
|
||||
c.ProvisionerCalled = true
|
||||
c.ProvisionerName = n
|
||||
return c.ProvisionerProvisioner
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Interpolate(
|
||||
config *config.RawConfig, resource *Resource) (*ResourceConfig, error) {
|
||||
c.InterpolateCalled = true
|
||||
c.InterpolateConfig = config
|
||||
c.InterpolateResource = resource
|
||||
return c.InterpolateConfigResult, c.InterpolateError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Path() []string {
|
||||
c.PathCalled = true
|
||||
return c.PathPath
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) SetVariables(vs map[string]string) {
|
||||
c.SetVariablesCalled = true
|
||||
c.SetVariablesVariables = vs
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Diff() (*Diff, *sync.RWMutex) {
|
||||
c.DiffCalled = true
|
||||
return c.DiffDiff, c.DiffLock
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) State() (*State, *sync.RWMutex) {
|
||||
c.StateCalled = true
|
||||
return c.StateState, c.StateLock
|
||||
}
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
)
|
||||
|
||||
// MockEvalContext is a mock version of EvalContext that can be used
|
||||
// for tests.
|
||||
type MockEvalContext struct {
|
||||
HookCalled bool
|
||||
HookHook Hook
|
||||
HookError error
|
||||
|
||||
InputCalled bool
|
||||
InputInput UIInput
|
||||
|
||||
InitProviderCalled bool
|
||||
InitProviderName string
|
||||
InitProviderProvider ResourceProvider
|
||||
InitProviderError error
|
||||
|
||||
ProviderCalled bool
|
||||
ProviderName string
|
||||
ProviderProvider ResourceProvider
|
||||
|
||||
ProviderInputCalled bool
|
||||
ProviderInputName string
|
||||
ProviderInputConfig map[string]interface{}
|
||||
|
||||
SetProviderInputCalled bool
|
||||
SetProviderInputName string
|
||||
SetProviderInputConfig map[string]interface{}
|
||||
|
||||
ConfigureProviderCalled bool
|
||||
ConfigureProviderName string
|
||||
ConfigureProviderConfig *ResourceConfig
|
||||
ConfigureProviderError error
|
||||
|
||||
ParentProviderConfigCalled bool
|
||||
ParentProviderConfigName string
|
||||
ParentProviderConfigConfig *ResourceConfig
|
||||
|
||||
InitProvisionerCalled bool
|
||||
InitProvisionerName string
|
||||
InitProvisionerProvisioner ResourceProvisioner
|
||||
InitProvisionerError error
|
||||
|
||||
ProvisionerCalled bool
|
||||
ProvisionerName string
|
||||
ProvisionerProvisioner ResourceProvisioner
|
||||
|
||||
InterpolateCalled bool
|
||||
InterpolateConfig *config.RawConfig
|
||||
InterpolateResource *Resource
|
||||
InterpolateConfigResult *ResourceConfig
|
||||
InterpolateError error
|
||||
|
||||
PathCalled bool
|
||||
PathPath []string
|
||||
|
||||
SetVariablesCalled bool
|
||||
SetVariablesVariables map[string]string
|
||||
|
||||
DiffCalled bool
|
||||
DiffDiff *Diff
|
||||
DiffLock *sync.RWMutex
|
||||
|
||||
StateCalled bool
|
||||
StateState *State
|
||||
StateLock *sync.RWMutex
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Hook(fn func(Hook) (HookAction, error)) error {
|
||||
c.HookCalled = true
|
||||
if c.HookHook != nil {
|
||||
if _, err := fn(c.HookHook); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return c.HookError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Input() UIInput {
|
||||
c.InputCalled = true
|
||||
return c.InputInput
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) InitProvider(n string) (ResourceProvider, error) {
|
||||
c.InitProviderCalled = true
|
||||
c.InitProviderName = n
|
||||
return c.InitProviderProvider, c.InitProviderError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Provider(n string) ResourceProvider {
|
||||
c.ProviderCalled = true
|
||||
c.ProviderName = n
|
||||
return c.ProviderProvider
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) ConfigureProvider(n string, cfg *ResourceConfig) error {
|
||||
c.ConfigureProviderCalled = true
|
||||
c.ConfigureProviderName = n
|
||||
c.ConfigureProviderConfig = cfg
|
||||
return c.ConfigureProviderError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) ParentProviderConfig(n string) *ResourceConfig {
|
||||
c.ParentProviderConfigCalled = true
|
||||
c.ParentProviderConfigName = n
|
||||
return c.ParentProviderConfigConfig
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) ProviderInput(n string) map[string]interface{} {
|
||||
c.ProviderInputCalled = true
|
||||
c.ProviderInputName = n
|
||||
return c.ProviderInputConfig
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) SetProviderInput(n string, cfg map[string]interface{}) {
|
||||
c.SetProviderInputCalled = true
|
||||
c.SetProviderInputName = n
|
||||
c.SetProviderInputConfig = cfg
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) InitProvisioner(n string) (ResourceProvisioner, error) {
|
||||
c.InitProvisionerCalled = true
|
||||
c.InitProvisionerName = n
|
||||
return c.InitProvisionerProvisioner, c.InitProvisionerError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Provisioner(n string) ResourceProvisioner {
|
||||
c.ProvisionerCalled = true
|
||||
c.ProvisionerName = n
|
||||
return c.ProvisionerProvisioner
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Interpolate(
|
||||
config *config.RawConfig, resource *Resource) (*ResourceConfig, error) {
|
||||
c.InterpolateCalled = true
|
||||
c.InterpolateConfig = config
|
||||
c.InterpolateResource = resource
|
||||
return c.InterpolateConfigResult, c.InterpolateError
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Path() []string {
|
||||
c.PathCalled = true
|
||||
return c.PathPath
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) SetVariables(vs map[string]string) {
|
||||
c.SetVariablesCalled = true
|
||||
c.SetVariablesVariables = vs
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Diff() (*Diff, *sync.RWMutex) {
|
||||
c.DiffCalled = true
|
||||
return c.DiffDiff, c.DiffLock
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) State() (*State, *sync.RWMutex) {
|
||||
c.StateCalled = true
|
||||
return c.StateState, c.StateLock
|
||||
}
|
|
@ -58,6 +58,28 @@ func (n *EvalReadState) Eval(ctx EvalContext) (interface{}, error) {
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// EvalUpdateStateHook is an EvalNode implementation that calls the
|
||||
// PostStateUpdate hook with the current state.
|
||||
type EvalUpdateStateHook struct{}
|
||||
|
||||
func (n *EvalUpdateStateHook) Eval(ctx EvalContext) (interface{}, error) {
|
||||
state, lock := ctx.State()
|
||||
|
||||
// Get a read lock so it doesn't change while we're calling this
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
|
||||
// Call the hook
|
||||
err := ctx.Hook(func(h Hook) (HookAction, error) {
|
||||
return h.PostStateUpdate(state)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// EvalWriteState is an EvalNode implementation that reads the
|
||||
// InstanceState for a specific resource out of the state.
|
||||
type EvalWriteState struct {
|
||||
|
@ -111,7 +133,6 @@ func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) {
|
|||
// Set the primary state
|
||||
rs.Primary = *n.State
|
||||
}
|
||||
println(fmt.Sprintf("%#v", rs))
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEvalUpdateStateHook(t *testing.T) {
|
||||
mockHook := new(MockHook)
|
||||
|
||||
ctx := new(MockEvalContext)
|
||||
ctx.HookHook = mockHook
|
||||
ctx.StateState = &State{Serial: 42}
|
||||
ctx.StateLock = new(sync.RWMutex)
|
||||
|
||||
node := &EvalUpdateStateHook{}
|
||||
if _, err := node.Eval(ctx); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if !mockHook.PostStateUpdateCalled {
|
||||
t.Fatal("should call PostStateUpdate")
|
||||
}
|
||||
if mockHook.PostStateUpdateState.Serial != 42 {
|
||||
t.Fatalf("bad: %#v", mockHook.PostStateUpdateState)
|
||||
}
|
||||
}
|
|
@ -49,6 +49,9 @@ type Hook interface {
|
|||
// resource state is refreshed, respectively.
|
||||
PreRefresh(*InstanceInfo, *InstanceState) (HookAction, error)
|
||||
PostRefresh(*InstanceInfo, *InstanceState) (HookAction, error)
|
||||
|
||||
// PostStateUpdate is called after the state is updated.
|
||||
PostStateUpdate(*State) (HookAction, error)
|
||||
}
|
||||
|
||||
// NilHook is a Hook implementation that does nothing. It exists only to
|
||||
|
@ -100,6 +103,10 @@ func (*NilHook) PostRefresh(*InstanceInfo, *InstanceState) (HookAction, error) {
|
|||
return HookActionContinue, nil
|
||||
}
|
||||
|
||||
func (*NilHook) PostStateUpdate(*State) (HookAction, error) {
|
||||
return HookActionContinue, nil
|
||||
}
|
||||
|
||||
// handleHook turns hook actions into panics. This lets you use the
|
||||
// panic/recover mechanism in Go as a flow control mechanism for hook
|
||||
// actions.
|
||||
|
|
|
@ -69,6 +69,11 @@ type MockHook struct {
|
|||
PreRefreshState *InstanceState
|
||||
PreRefreshReturn HookAction
|
||||
PreRefreshError error
|
||||
|
||||
PostStateUpdateCalled bool
|
||||
PostStateUpdateState *State
|
||||
PostStateUpdateReturn HookAction
|
||||
PostStateUpdateError error
|
||||
}
|
||||
|
||||
func (h *MockHook) PreApply(n *InstanceInfo, s *InstanceState, d *InstanceDiff) (HookAction, error) {
|
||||
|
@ -152,3 +157,9 @@ func (h *MockHook) PostRefresh(n *InstanceInfo, s *InstanceState) (HookAction, e
|
|||
h.PostRefreshState = s
|
||||
return h.PostRefreshReturn, h.PostRefreshError
|
||||
}
|
||||
|
||||
func (h *MockHook) PostStateUpdate(s *State) (HookAction, error) {
|
||||
h.PostStateUpdateCalled = true
|
||||
h.PostStateUpdateState = s
|
||||
return h.PostStateUpdateReturn, h.PostStateUpdateError
|
||||
}
|
||||
|
|
|
@ -53,6 +53,10 @@ func (h *stopHook) PostRefresh(*InstanceInfo, *InstanceState) (HookAction, error
|
|||
return h.hook()
|
||||
}
|
||||
|
||||
func (h *stopHook) PostStateUpdate(*State) (HookAction, error) {
|
||||
return h.hook()
|
||||
}
|
||||
|
||||
func (h *stopHook) hook() (HookAction, error) {
|
||||
if h.Stopped() {
|
||||
return HookActionHalt, nil
|
||||
|
|
Loading…
Reference in New Issue