terraform/internal/command/views/hook_count.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

134 lines
3 KiB
Go
Raw Permalink Normal View History

// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1
2021-02-18 17:23:34 -05:00
package views
import (
"sync"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/terraform"
)
2021-02-18 17:23:34 -05:00
// countHook is a hook that counts the number of resources
// added, removed, changed during the course of an apply.
2021-02-18 17:23:34 -05:00
type countHook struct {
Added int
Changed int
Removed int
Imported int
ActionInvocation int
ToAdd int
ToChange int
ToRemove int
ToRemoveAndAdd int
pending map[string]plans.Action
sync.Mutex
terraform.NilHook
}
2021-02-18 17:23:34 -05:00
var _ terraform.Hook = (*countHook)(nil)
2021-02-18 17:23:34 -05:00
func (h *countHook) Reset() {
h.Lock()
defer h.Unlock()
h.pending = nil
h.Added = 0
h.Changed = 0
h.Removed = 0
h.Imported = 0
h.ActionInvocation = 0
}
Refactor terraform.Hook to use a resource-identifying wrapper struct The terraform.Hook interface lets other areas of code perform streaming reactions to various events, generally in the service of some UI somewhere. Nearly all of the methods on this interface take an `addrs.AbsResourceInstance` as their first argument, to identify the resource that's being operated on. However, that addrs struct doesn't necessarily contain everything you might want in order to uniquely and usefully identify a resource. It has the module instance and resource instance addresses, but it lacks the provider source address, which can affect how the consuming UI should display the resource's events. (For example, Terraform Cloud wants reliable info about who maintains a given provider, what cloud provider it operates on, and where to find its documentation.) Instead of polluting `addrs.AbsResourceInstance` with extra information that isn't relevant to other call sites, let's change the first argument of each Hook method to be a wrapper struct defined in the package that owns the Hook interface, and add the provider address to that wrapper as a sibling of the resource address. This causes a big noisy commit today, but should streamline future updates to the UI-facing "identity" of a resource; existing callers can ignore any new fields they're uninterested in, or exploit new info as needed. Other than making new information available for future edits to Hook implementing types, this commit should have no effect on existing behavior.
2024-02-27 20:42:17 -05:00
func (h *countHook) PreApply(id terraform.HookResourceIdentity, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()
if h.pending == nil {
h.pending = make(map[string]plans.Action)
}
Refactor terraform.Hook to use a resource-identifying wrapper struct The terraform.Hook interface lets other areas of code perform streaming reactions to various events, generally in the service of some UI somewhere. Nearly all of the methods on this interface take an `addrs.AbsResourceInstance` as their first argument, to identify the resource that's being operated on. However, that addrs struct doesn't necessarily contain everything you might want in order to uniquely and usefully identify a resource. It has the module instance and resource instance addresses, but it lacks the provider source address, which can affect how the consuming UI should display the resource's events. (For example, Terraform Cloud wants reliable info about who maintains a given provider, what cloud provider it operates on, and where to find its documentation.) Instead of polluting `addrs.AbsResourceInstance` with extra information that isn't relevant to other call sites, let's change the first argument of each Hook method to be a wrapper struct defined in the package that owns the Hook interface, and add the provider address to that wrapper as a sibling of the resource address. This causes a big noisy commit today, but should streamline future updates to the UI-facing "identity" of a resource; existing callers can ignore any new fields they're uninterested in, or exploit new info as needed. Other than making new information available for future edits to Hook implementing types, this commit should have no effect on existing behavior.
2024-02-27 20:42:17 -05:00
h.pending[id.Addr.String()] = action
return terraform.HookActionContinue, nil
}
Refactor terraform.Hook to use a resource-identifying wrapper struct The terraform.Hook interface lets other areas of code perform streaming reactions to various events, generally in the service of some UI somewhere. Nearly all of the methods on this interface take an `addrs.AbsResourceInstance` as their first argument, to identify the resource that's being operated on. However, that addrs struct doesn't necessarily contain everything you might want in order to uniquely and usefully identify a resource. It has the module instance and resource instance addresses, but it lacks the provider source address, which can affect how the consuming UI should display the resource's events. (For example, Terraform Cloud wants reliable info about who maintains a given provider, what cloud provider it operates on, and where to find its documentation.) Instead of polluting `addrs.AbsResourceInstance` with extra information that isn't relevant to other call sites, let's change the first argument of each Hook method to be a wrapper struct defined in the package that owns the Hook interface, and add the provider address to that wrapper as a sibling of the resource address. This causes a big noisy commit today, but should streamline future updates to the UI-facing "identity" of a resource; existing callers can ignore any new fields they're uninterested in, or exploit new info as needed. Other than making new information available for future edits to Hook implementing types, this commit should have no effect on existing behavior.
2024-02-27 20:42:17 -05:00
func (h *countHook) PostApply(id terraform.HookResourceIdentity, dk addrs.DeposedKey, newState cty.Value, err error) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()
if h.pending != nil {
Refactor terraform.Hook to use a resource-identifying wrapper struct The terraform.Hook interface lets other areas of code perform streaming reactions to various events, generally in the service of some UI somewhere. Nearly all of the methods on this interface take an `addrs.AbsResourceInstance` as their first argument, to identify the resource that's being operated on. However, that addrs struct doesn't necessarily contain everything you might want in order to uniquely and usefully identify a resource. It has the module instance and resource instance addresses, but it lacks the provider source address, which can affect how the consuming UI should display the resource's events. (For example, Terraform Cloud wants reliable info about who maintains a given provider, what cloud provider it operates on, and where to find its documentation.) Instead of polluting `addrs.AbsResourceInstance` with extra information that isn't relevant to other call sites, let's change the first argument of each Hook method to be a wrapper struct defined in the package that owns the Hook interface, and add the provider address to that wrapper as a sibling of the resource address. This causes a big noisy commit today, but should streamline future updates to the UI-facing "identity" of a resource; existing callers can ignore any new fields they're uninterested in, or exploit new info as needed. Other than making new information available for future edits to Hook implementing types, this commit should have no effect on existing behavior.
2024-02-27 20:42:17 -05:00
pendingKey := id.Addr.String()
if action, ok := h.pending[pendingKey]; ok {
delete(h.pending, pendingKey)
if err == nil {
switch action {
case plans.CreateThenDelete, plans.DeleteThenCreate:
h.Added++
h.Removed++
case plans.Create:
h.Added++
case plans.Delete:
h.Removed++
case plans.Update:
h.Changed++
}
}
}
}
return terraform.HookActionContinue, nil
}
func (h *countHook) PostDiff(id terraform.HookResourceIdentity, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value, err error) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()
// Skip counting if there was an error
if err != nil {
return terraform.HookActionContinue, nil
}
// We don't count anything for data resources
Refactor terraform.Hook to use a resource-identifying wrapper struct The terraform.Hook interface lets other areas of code perform streaming reactions to various events, generally in the service of some UI somewhere. Nearly all of the methods on this interface take an `addrs.AbsResourceInstance` as their first argument, to identify the resource that's being operated on. However, that addrs struct doesn't necessarily contain everything you might want in order to uniquely and usefully identify a resource. It has the module instance and resource instance addresses, but it lacks the provider source address, which can affect how the consuming UI should display the resource's events. (For example, Terraform Cloud wants reliable info about who maintains a given provider, what cloud provider it operates on, and where to find its documentation.) Instead of polluting `addrs.AbsResourceInstance` with extra information that isn't relevant to other call sites, let's change the first argument of each Hook method to be a wrapper struct defined in the package that owns the Hook interface, and add the provider address to that wrapper as a sibling of the resource address. This causes a big noisy commit today, but should streamline future updates to the UI-facing "identity" of a resource; existing callers can ignore any new fields they're uninterested in, or exploit new info as needed. Other than making new information available for future edits to Hook implementing types, this commit should have no effect on existing behavior.
2024-02-27 20:42:17 -05:00
if id.Addr.Resource.Resource.Mode == addrs.DataResourceMode {
return terraform.HookActionContinue, nil
}
switch action {
case plans.CreateThenDelete, plans.DeleteThenCreate:
h.ToRemoveAndAdd += 1
case plans.Create:
h.ToAdd += 1
case plans.Delete:
h.ToRemove += 1
case plans.Update:
h.ToChange += 1
}
return terraform.HookActionContinue, nil
}
Refactor terraform.Hook to use a resource-identifying wrapper struct The terraform.Hook interface lets other areas of code perform streaming reactions to various events, generally in the service of some UI somewhere. Nearly all of the methods on this interface take an `addrs.AbsResourceInstance` as their first argument, to identify the resource that's being operated on. However, that addrs struct doesn't necessarily contain everything you might want in order to uniquely and usefully identify a resource. It has the module instance and resource instance addresses, but it lacks the provider source address, which can affect how the consuming UI should display the resource's events. (For example, Terraform Cloud wants reliable info about who maintains a given provider, what cloud provider it operates on, and where to find its documentation.) Instead of polluting `addrs.AbsResourceInstance` with extra information that isn't relevant to other call sites, let's change the first argument of each Hook method to be a wrapper struct defined in the package that owns the Hook interface, and add the provider address to that wrapper as a sibling of the resource address. This causes a big noisy commit today, but should streamline future updates to the UI-facing "identity" of a resource; existing callers can ignore any new fields they're uninterested in, or exploit new info as needed. Other than making new information available for future edits to Hook implementing types, this commit should have no effect on existing behavior.
2024-02-27 20:42:17 -05:00
func (h *countHook) PostApplyImport(id terraform.HookResourceIdentity, importing plans.ImportingSrc) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()
h.Imported++
return terraform.HookActionContinue, nil
}
func (h *countHook) CompleteAction(id terraform.HookActionIdentity, err error) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()
h.ActionInvocation++
return terraform.HookActionContinue, nil
}