Repository: opentofu/opentofu
File: internal/tofu/hook.go (Go)

Code before:
	// to renew an ephemeral resource.
	PreRenew(addr addrs.AbsResourceInstance) (HookAction, error)
	PostRenew(addr addrs.AbsResourceInstance, err error) (HookAction, error)
	// PreClose and PostClose are called before and after the request to a provider
	// to close an ephemeral resource.
	PreClose(addr addrs.AbsResourceInstance) (HookAction, error)
	PostClose(addr addrs.AbsResourceInstance, err error) (HookAction, error)
	// Stopping is called if an external signal requests that OpenTofu
	// gracefully abort an operation in progress.
	//
	// This notification might suggest that the user wants OpenTofu to exit
	// ASAP and in that case it's possible that if OpenTofu runs for too much
	// longer then it'll get killed un-gracefully, and so this hook could be
	// an opportunity to persist any transient data that would be lost under
	// a subsequent kill signal. However, implementations must take care to do
	// so in a way that won't cause corruption if the process _is_ killed while
	// this hook is still running.
	//
	// This hook cannot control whether OpenTofu continues, because the
	// graceful shutdown process is typically already running by the time this
	// function is called.
	Stopping()

	// PostStateUpdate is called each time a portion of the state is updated. It receives
	// a function that mutates the syncronized state object.
	PostStateUpdate(func(*states.SyncState)) (HookAction, error)
}

// NilHook is a Hook implementation that does nothing. It exists only to
// simplify implementing hooks. You can embed this into your Hook implementation
// and only implement the functions you are interested in.
type NilHook struct{}

var _ Hook = (*NilHook)(nil)

func (*NilHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
	return HookActionContinue, nil
}

func (*NilHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (HookAction, error) {
	return HookActionContinue, nil
}

func (*NilHook) PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (HookAction, error) {
	return HookActionContinue, nil
}

func (*NilHook) PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
	return HookActionContinue, nil
}


Review comment (bug):
```suggestion
	// PostStateUpdate is called each time a portion of the state is updated. It receives
	// a function that mutates the syncronized state object.
	//
	// This should return an error only if the hook tried to persist the updated state
	// to the primary state storage location and failed to do so, because this method
	// is called as a side-effect of updating resource instances in the state and any
	// error returned will be treated as a failure to update the state, returned to the
	// end-user.
	PostStateUpdate(func(*states.SyncState)) (HookAction, error)
```

Code after:
	// to renew an ephemeral resource.
	PreRenew(addr addrs.AbsResourceInstance) (HookAction, error)
	PostRenew(addr addrs.AbsResourceInstance, err error) (HookAction, error)
	// PreClose and PostClose are called before and after the request to a provider
	// to close an ephemeral resource.
	PreClose(addr addrs.AbsResourceInstance) (HookAction, error)
	PostClose(addr addrs.AbsResourceInstance, err error) (HookAction, error)
	// Stopping is called if an external signal requests that OpenTofu
	// gracefully abort an operation in progress.
	//
	// This notification might suggest that the user wants OpenTofu to exit
	// ASAP and in that case it's possible that if OpenTofu runs for too much
	// longer then it'll get killed un-gracefully, and so this hook could be
	// an opportunity to persist any transient data that would be lost under
	// a subsequent kill signal. However, implementations must take care to do
	// so in a way that won't cause corruption if the process _is_ killed while
	// this hook is still running.
	//
	// This hook cannot control whether OpenTofu continues, because the
	// graceful shutdown process is typically already running by the time this
	// function is called.
	Stopping()

	// PostStateUpdate is called each time a portion of the state is updated. It receives
	// a function that mutates the syncronized state object.
	//
	// This should return an error only if the hook tried to persist the updated state
	// to the primary state storage location and failed to do so, because this method
	// is called as a side-effect of updating resource instances in the state and any
	// error returned will be treated as a failure to update the state, returned to the
	// end-user.
	PostStateUpdate(func(*states.SyncState)) (HookAction, error)
}

// NilHook is a Hook implementation that does nothing. It exists only to
// simplify implementing hooks. You can embed this into your Hook implementation
// and only implement the functions you are interested in.
type NilHook struct{}

var _ Hook = (*NilHook)(nil)

func (*NilHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
	return HookActionContinue, nil
}

func (*NilHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (HookAction, error) {
	return HookActionContinue, nil
}

func (*NilHook) PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (HookAction, error) {
	return HookActionContinue, nil