github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/command/views/hook_count.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package views
     5  
     6  import (
     7  	"sync"
     8  
     9  	"github.com/zclconf/go-cty/cty"
    10  
    11  	"github.com/terramate-io/tf/addrs"
    12  	"github.com/terramate-io/tf/plans"
    13  	"github.com/terramate-io/tf/states"
    14  	"github.com/terramate-io/tf/terraform"
    15  )
    16  
    17  // countHook is a hook that counts the number of resources
    18  // added, removed, changed during the course of an apply.
    19  type countHook struct {
    20  	Added    int
    21  	Changed  int
    22  	Removed  int
    23  	Imported int
    24  
    25  	ToAdd          int
    26  	ToChange       int
    27  	ToRemove       int
    28  	ToRemoveAndAdd int
    29  
    30  	pending map[string]plans.Action
    31  
    32  	sync.Mutex
    33  	terraform.NilHook
    34  }
    35  
    36  var _ terraform.Hook = (*countHook)(nil)
    37  
    38  func (h *countHook) Reset() {
    39  	h.Lock()
    40  	defer h.Unlock()
    41  
    42  	h.pending = nil
    43  	h.Added = 0
    44  	h.Changed = 0
    45  	h.Removed = 0
    46  	h.Imported = 0
    47  }
    48  
    49  func (h *countHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
    50  	h.Lock()
    51  	defer h.Unlock()
    52  
    53  	if h.pending == nil {
    54  		h.pending = make(map[string]plans.Action)
    55  	}
    56  
    57  	h.pending[addr.String()] = action
    58  
    59  	return terraform.HookActionContinue, nil
    60  }
    61  
    62  func (h *countHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (terraform.HookAction, error) {
    63  	h.Lock()
    64  	defer h.Unlock()
    65  
    66  	if h.pending != nil {
    67  		pendingKey := addr.String()
    68  		if action, ok := h.pending[pendingKey]; ok {
    69  			delete(h.pending, pendingKey)
    70  
    71  			if err == nil {
    72  				switch action {
    73  				case plans.CreateThenDelete, plans.DeleteThenCreate:
    74  					h.Added++
    75  					h.Removed++
    76  				case plans.Create:
    77  					h.Added++
    78  				case plans.Delete:
    79  					h.Removed++
    80  				case plans.Update:
    81  					h.Changed++
    82  				}
    83  			}
    84  		}
    85  	}
    86  
    87  	return terraform.HookActionContinue, nil
    88  }
    89  
    90  func (h *countHook) PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
    91  	h.Lock()
    92  	defer h.Unlock()
    93  
    94  	// We don't count anything for data resources
    95  	if addr.Resource.Resource.Mode == addrs.DataResourceMode {
    96  		return terraform.HookActionContinue, nil
    97  	}
    98  
    99  	switch action {
   100  	case plans.CreateThenDelete, plans.DeleteThenCreate:
   101  		h.ToRemoveAndAdd += 1
   102  	case plans.Create:
   103  		h.ToAdd += 1
   104  	case plans.Delete:
   105  		h.ToRemove += 1
   106  	case plans.Update:
   107  		h.ToChange += 1
   108  	}
   109  
   110  	return terraform.HookActionContinue, nil
   111  }
   112  
   113  func (h *countHook) PostApplyImport(addr addrs.AbsResourceInstance, importing plans.ImportingSrc) (terraform.HookAction, error) {
   114  	h.Lock()
   115  	defer h.Unlock()
   116  
   117  	h.Imported++
   118  	return terraform.HookActionContinue, nil
   119  }