mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Merge pull request #1037 from hashicorp/f-continuous-state
Continuous state persistance
This commit is contained in:
commit
1fcbfcd19d
@ -68,7 +68,8 @@ func (c *ApplyCommand) Run(args []string) int {
|
|||||||
|
|
||||||
// Prepare the extra hooks to count resources
|
// Prepare the extra hooks to count resources
|
||||||
countHook := new(CountHook)
|
countHook := new(CountHook)
|
||||||
c.Meta.extraHooks = []terraform.Hook{countHook}
|
stateHook := new(StateHook)
|
||||||
|
c.Meta.extraHooks = []terraform.Hook{countHook, stateHook}
|
||||||
|
|
||||||
if !c.Destroy && maybeInit {
|
if !c.Destroy && maybeInit {
|
||||||
// Do a detect to determine if we need to do an init + apply.
|
// Do a detect to determine if we need to do an init + apply.
|
||||||
@ -151,6 +152,18 @@ func (c *ApplyCommand) Run(args []string) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup the state hook for continous state updates
|
||||||
|
{
|
||||||
|
state, err := c.State()
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf(
|
||||||
|
"Error reading state: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
stateHook.State = state
|
||||||
|
}
|
||||||
|
|
||||||
// Start the apply in a goroutine so that we can be interrupted.
|
// Start the apply in a goroutine so that we can be interrupted.
|
||||||
var state *terraform.State
|
var state *terraform.State
|
||||||
var applyErr error
|
var applyErr error
|
||||||
|
33
command/hook_state.go
Normal file
33
command/hook_state.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/state"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StateHook is a hook that continuously updates the state by calling
|
||||||
|
// WriteState on a state.State.
|
||||||
|
type StateHook struct {
|
||||||
|
terraform.NilHook
|
||||||
|
sync.Mutex
|
||||||
|
|
||||||
|
State state.State
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *StateHook) PostStateUpdate(
|
||||||
|
s *terraform.State) (terraform.HookAction, error) {
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
|
|
||||||
|
if h.State != nil {
|
||||||
|
// Write the new state
|
||||||
|
if err := h.State.WriteState(s); err != nil {
|
||||||
|
return terraform.HookActionHalt, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue forth
|
||||||
|
return terraform.HookActionContinue, nil
|
||||||
|
}
|
29
command/hook_state_test.go
Normal file
29
command/hook_state_test.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/state"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStateHook_impl(t *testing.T) {
|
||||||
|
var _ terraform.Hook = new(StateHook)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStateHook(t *testing.T) {
|
||||||
|
is := &state.InmemState{}
|
||||||
|
var hook terraform.Hook = &StateHook{State: is}
|
||||||
|
|
||||||
|
s := state.TestStateInitial()
|
||||||
|
action, err := hook.PostStateUpdate(s)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if action != terraform.HookActionContinue {
|
||||||
|
t.Fatalf("bad: %v", action)
|
||||||
|
}
|
||||||
|
if !is.State().Equal(s) {
|
||||||
|
t.Fatalf("bad state: %#v", is.State())
|
||||||
|
}
|
||||||
|
}
|
@ -4454,6 +4454,9 @@ func TestContext2Apply_hook(t *testing.T) {
|
|||||||
if !h.PostApplyCalled {
|
if !h.PostApplyCalled {
|
||||||
t.Fatal("should be called")
|
t.Fatal("should be called")
|
||||||
}
|
}
|
||||||
|
if !h.PostStateUpdateCalled {
|
||||||
|
t.Fatalf("should call post state update")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContext2Apply_idAttr(t *testing.T) {
|
func TestContext2Apply_idAttr(t *testing.T) {
|
||||||
|
@ -70,155 +70,3 @@ type EvalContext interface {
|
|||||||
// be used to modify that state.
|
// be used to modify that state.
|
||||||
State() (*State, *sync.RWMutex)
|
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
|
|
||||||
}
|
|
||||||
|
166
terraform/eval_context_mock.go
Normal file
166
terraform/eval_context_mock.go
Normal file
@ -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
|
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
|
// EvalWriteState is an EvalNode implementation that reads the
|
||||||
// InstanceState for a specific resource out of the state.
|
// InstanceState for a specific resource out of the state.
|
||||||
type EvalWriteState struct {
|
type EvalWriteState struct {
|
||||||
@ -111,7 +133,6 @@ func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) {
|
|||||||
// Set the primary state
|
// Set the primary state
|
||||||
rs.Primary = *n.State
|
rs.Primary = *n.State
|
||||||
}
|
}
|
||||||
println(fmt.Sprintf("%#v", rs))
|
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
27
terraform/eval_state_test.go
Normal file
27
terraform/eval_state_test.go
Normal file
@ -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.
|
// resource state is refreshed, respectively.
|
||||||
PreRefresh(*InstanceInfo, *InstanceState) (HookAction, error)
|
PreRefresh(*InstanceInfo, *InstanceState) (HookAction, error)
|
||||||
PostRefresh(*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
|
// 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
|
return HookActionContinue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*NilHook) PostStateUpdate(*State) (HookAction, error) {
|
||||||
|
return HookActionContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
// handleHook turns hook actions into panics. This lets you use the
|
// handleHook turns hook actions into panics. This lets you use the
|
||||||
// panic/recover mechanism in Go as a flow control mechanism for hook
|
// panic/recover mechanism in Go as a flow control mechanism for hook
|
||||||
// actions.
|
// actions.
|
||||||
|
@ -69,6 +69,11 @@ type MockHook struct {
|
|||||||
PreRefreshState *InstanceState
|
PreRefreshState *InstanceState
|
||||||
PreRefreshReturn HookAction
|
PreRefreshReturn HookAction
|
||||||
PreRefreshError error
|
PreRefreshError error
|
||||||
|
|
||||||
|
PostStateUpdateCalled bool
|
||||||
|
PostStateUpdateState *State
|
||||||
|
PostStateUpdateReturn HookAction
|
||||||
|
PostStateUpdateError error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *MockHook) PreApply(n *InstanceInfo, s *InstanceState, d *InstanceDiff) (HookAction, 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
|
h.PostRefreshState = s
|
||||||
return h.PostRefreshReturn, h.PostRefreshError
|
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()
|
return h.hook()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *stopHook) PostStateUpdate(*State) (HookAction, error) {
|
||||||
|
return h.hook()
|
||||||
|
}
|
||||||
|
|
||||||
func (h *stopHook) hook() (HookAction, error) {
|
func (h *stopHook) hook() (HookAction, error) {
|
||||||
if h.Stopped() {
|
if h.Stopped() {
|
||||||
return HookActionHalt, nil
|
return HookActionHalt, nil
|
||||||
|
@ -262,6 +262,7 @@ func (n *graphNodeOrphanResource) EvalTree() EvalNode {
|
|||||||
Dependencies: n.DependentOn(),
|
Dependencies: n.DependentOn(),
|
||||||
State: &state,
|
State: &state,
|
||||||
},
|
},
|
||||||
|
&EvalUpdateStateHook{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -400,6 +400,7 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode {
|
|||||||
State: &state,
|
State: &state,
|
||||||
Error: &err,
|
Error: &err,
|
||||||
},
|
},
|
||||||
|
&EvalUpdateStateHook{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -163,6 +163,7 @@ func (n *graphNodeTaintedResource) EvalTree() EvalNode {
|
|||||||
Tainted: &tainted,
|
Tainted: &tainted,
|
||||||
TaintedIndex: n.Index,
|
TaintedIndex: n.Index,
|
||||||
},
|
},
|
||||||
|
&EvalUpdateStateHook{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user