Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions internal/terraform/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,11 @@ type Hook interface {
// function is called.
Stopping()

// PostStateUpdate is called each time the state is updated. It receives
// a deep copy of the state, which it may therefore access freely without
// any need for locks to protect from concurrent writes from the caller.
// PostStateUpdate is called each time the state is updated. The caller must
// coordinate a lock for the state if necessary, such that the Hook may
// access it freely without any need for additional locks to protect from
// concurrent writes. Implementations which modify or retain the state after
// the call has returned must copy the state.
PostStateUpdate(new *states.State) (HookAction, error)
}

Expand Down
9 changes: 3 additions & 6 deletions internal/terraform/update_state_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@ package terraform

// updateStateHook calls the PostStateUpdate hook with the current state.
func updateStateHook(ctx EvalContext) error {
// In principle we could grab the lock here just long enough to take a
// deep copy and then pass that to our hooks below, but we'll instead
// hold the hook for the duration to avoid the potential confusing
// situation of us racing to call PostStateUpdate concurrently with
// different state snapshots.
// PostStateUpdate requires that the state be locked and safe to read for
// the duration of the call.
stateSync := ctx.State()
state := stateSync.Lock().DeepCopy()
state := stateSync.Lock()
defer stateSync.Unlock()

// Call the hook
Expand Down