github.com/cycloidio/terraform@v1.1.10-0.20220513142504-76d5c768dc63/command/views/json/hook.go (about)

     1  package json
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/cycloidio/terraform/addrs"
     8  	"github.com/cycloidio/terraform/plans"
     9  )
    10  
    11  type Hook interface {
    12  	HookType() MessageType
    13  	String() string
    14  }
    15  
    16  // ApplyStart: triggered by PreApply hook
    17  type applyStart struct {
    18  	Resource   ResourceAddr `json:"resource"`
    19  	Action     ChangeAction `json:"action"`
    20  	IDKey      string       `json:"id_key,omitempty"`
    21  	IDValue    string       `json:"id_value,omitempty"`
    22  	actionVerb string
    23  }
    24  
    25  var _ Hook = (*applyStart)(nil)
    26  
    27  func (h *applyStart) HookType() MessageType {
    28  	return MessageApplyStart
    29  }
    30  
    31  func (h *applyStart) String() string {
    32  	var id string
    33  	if h.IDKey != "" && h.IDValue != "" {
    34  		id = fmt.Sprintf(" [%s=%s]", h.IDKey, h.IDValue)
    35  	}
    36  	return fmt.Sprintf("%s: %s...%s", h.Resource.Addr, h.actionVerb, id)
    37  }
    38  
    39  func NewApplyStart(addr addrs.AbsResourceInstance, action plans.Action, idKey string, idValue string) Hook {
    40  	hook := &applyStart{
    41  		Resource:   newResourceAddr(addr),
    42  		Action:     changeAction(action),
    43  		IDKey:      idKey,
    44  		IDValue:    idValue,
    45  		actionVerb: startActionVerb(action),
    46  	}
    47  
    48  	return hook
    49  }
    50  
    51  // ApplyProgress: currently triggered by a timer started on PreApply. In
    52  // future, this might also be triggered by provider progress reporting.
    53  type applyProgress struct {
    54  	Resource   ResourceAddr `json:"resource"`
    55  	Action     ChangeAction `json:"action"`
    56  	Elapsed    float64      `json:"elapsed_seconds"`
    57  	actionVerb string
    58  	elapsed    time.Duration
    59  }
    60  
    61  var _ Hook = (*applyProgress)(nil)
    62  
    63  func (h *applyProgress) HookType() MessageType {
    64  	return MessageApplyProgress
    65  }
    66  
    67  func (h *applyProgress) String() string {
    68  	return fmt.Sprintf("%s: Still %s... [%s elapsed]", h.Resource.Addr, h.actionVerb, h.elapsed)
    69  }
    70  
    71  func NewApplyProgress(addr addrs.AbsResourceInstance, action plans.Action, elapsed time.Duration) Hook {
    72  	return &applyProgress{
    73  		Resource:   newResourceAddr(addr),
    74  		Action:     changeAction(action),
    75  		Elapsed:    elapsed.Seconds(),
    76  		actionVerb: progressActionVerb(action),
    77  		elapsed:    elapsed,
    78  	}
    79  }
    80  
    81  // ApplyComplete: triggered by PostApply hook
    82  type applyComplete struct {
    83  	Resource   ResourceAddr `json:"resource"`
    84  	Action     ChangeAction `json:"action"`
    85  	IDKey      string       `json:"id_key,omitempty"`
    86  	IDValue    string       `json:"id_value,omitempty"`
    87  	Elapsed    float64      `json:"elapsed_seconds"`
    88  	actionNoun string
    89  	elapsed    time.Duration
    90  }
    91  
    92  var _ Hook = (*applyComplete)(nil)
    93  
    94  func (h *applyComplete) HookType() MessageType {
    95  	return MessageApplyComplete
    96  }
    97  
    98  func (h *applyComplete) String() string {
    99  	var id string
   100  	if h.IDKey != "" && h.IDValue != "" {
   101  		id = fmt.Sprintf(" [%s=%s]", h.IDKey, h.IDValue)
   102  	}
   103  	return fmt.Sprintf("%s: %s complete after %s%s", h.Resource.Addr, h.actionNoun, h.elapsed, id)
   104  }
   105  
   106  func NewApplyComplete(addr addrs.AbsResourceInstance, action plans.Action, idKey, idValue string, elapsed time.Duration) Hook {
   107  	return &applyComplete{
   108  		Resource:   newResourceAddr(addr),
   109  		Action:     changeAction(action),
   110  		IDKey:      idKey,
   111  		IDValue:    idValue,
   112  		Elapsed:    elapsed.Seconds(),
   113  		actionNoun: actionNoun(action),
   114  		elapsed:    elapsed,
   115  	}
   116  }
   117  
   118  // ApplyErrored: triggered by PostApply hook on failure. This will be followed
   119  // by diagnostics when the apply finishes.
   120  type applyErrored struct {
   121  	Resource   ResourceAddr `json:"resource"`
   122  	Action     ChangeAction `json:"action"`
   123  	Elapsed    float64      `json:"elapsed_seconds"`
   124  	actionNoun string
   125  	elapsed    time.Duration
   126  }
   127  
   128  var _ Hook = (*applyErrored)(nil)
   129  
   130  func (h *applyErrored) HookType() MessageType {
   131  	return MessageApplyErrored
   132  }
   133  
   134  func (h *applyErrored) String() string {
   135  	return fmt.Sprintf("%s: %s errored after %s", h.Resource.Addr, h.actionNoun, h.elapsed)
   136  }
   137  
   138  func NewApplyErrored(addr addrs.AbsResourceInstance, action plans.Action, elapsed time.Duration) Hook {
   139  	return &applyErrored{
   140  		Resource:   newResourceAddr(addr),
   141  		Action:     changeAction(action),
   142  		Elapsed:    elapsed.Seconds(),
   143  		actionNoun: actionNoun(action),
   144  		elapsed:    elapsed,
   145  	}
   146  }
   147  
   148  // ProvisionStart: triggered by PreProvisionInstanceStep hook
   149  type provisionStart struct {
   150  	Resource    ResourceAddr `json:"resource"`
   151  	Provisioner string       `json:"provisioner"`
   152  }
   153  
   154  var _ Hook = (*provisionStart)(nil)
   155  
   156  func (h *provisionStart) HookType() MessageType {
   157  	return MessageProvisionStart
   158  }
   159  
   160  func (h *provisionStart) String() string {
   161  	return fmt.Sprintf("%s: Provisioning with '%s'...", h.Resource.Addr, h.Provisioner)
   162  }
   163  
   164  func NewProvisionStart(addr addrs.AbsResourceInstance, provisioner string) Hook {
   165  	return &provisionStart{
   166  		Resource:    newResourceAddr(addr),
   167  		Provisioner: provisioner,
   168  	}
   169  }
   170  
   171  // ProvisionProgress: triggered by ProvisionOutput hook
   172  type provisionProgress struct {
   173  	Resource    ResourceAddr `json:"resource"`
   174  	Provisioner string       `json:"provisioner"`
   175  	Output      string       `json:"output"`
   176  }
   177  
   178  var _ Hook = (*provisionProgress)(nil)
   179  
   180  func (h *provisionProgress) HookType() MessageType {
   181  	return MessageProvisionProgress
   182  }
   183  
   184  func (h *provisionProgress) String() string {
   185  	return fmt.Sprintf("%s: (%s): %s", h.Resource.Addr, h.Provisioner, h.Output)
   186  }
   187  
   188  func NewProvisionProgress(addr addrs.AbsResourceInstance, provisioner string, output string) Hook {
   189  	return &provisionProgress{
   190  		Resource:    newResourceAddr(addr),
   191  		Provisioner: provisioner,
   192  		Output:      output,
   193  	}
   194  }
   195  
   196  // ProvisionComplete: triggered by PostProvisionInstanceStep hook
   197  type provisionComplete struct {
   198  	Resource    ResourceAddr `json:"resource"`
   199  	Provisioner string       `json:"provisioner"`
   200  }
   201  
   202  var _ Hook = (*provisionComplete)(nil)
   203  
   204  func (h *provisionComplete) HookType() MessageType {
   205  	return MessageProvisionComplete
   206  }
   207  
   208  func (h *provisionComplete) String() string {
   209  	return fmt.Sprintf("%s: (%s) Provisioning complete", h.Resource.Addr, h.Provisioner)
   210  }
   211  
   212  func NewProvisionComplete(addr addrs.AbsResourceInstance, provisioner string) Hook {
   213  	return &provisionComplete{
   214  		Resource:    newResourceAddr(addr),
   215  		Provisioner: provisioner,
   216  	}
   217  }
   218  
   219  // ProvisionErrored: triggered by PostProvisionInstanceStep hook on failure.
   220  // This will be followed by diagnostics when the apply finishes.
   221  type provisionErrored struct {
   222  	Resource    ResourceAddr `json:"resource"`
   223  	Provisioner string       `json:"provisioner"`
   224  }
   225  
   226  var _ Hook = (*provisionErrored)(nil)
   227  
   228  func (h *provisionErrored) HookType() MessageType {
   229  	return MessageProvisionErrored
   230  }
   231  
   232  func (h *provisionErrored) String() string {
   233  	return fmt.Sprintf("%s: (%s) Provisioning errored", h.Resource.Addr, h.Provisioner)
   234  }
   235  
   236  func NewProvisionErrored(addr addrs.AbsResourceInstance, provisioner string) Hook {
   237  	return &provisionErrored{
   238  		Resource:    newResourceAddr(addr),
   239  		Provisioner: provisioner,
   240  	}
   241  }
   242  
   243  // RefreshStart: triggered by PreRefresh hook
   244  type refreshStart struct {
   245  	Resource ResourceAddr `json:"resource"`
   246  	IDKey    string       `json:"id_key,omitempty"`
   247  	IDValue  string       `json:"id_value,omitempty"`
   248  }
   249  
   250  var _ Hook = (*refreshStart)(nil)
   251  
   252  func (h *refreshStart) HookType() MessageType {
   253  	return MessageRefreshStart
   254  }
   255  
   256  func (h *refreshStart) String() string {
   257  	var id string
   258  	if h.IDKey != "" && h.IDValue != "" {
   259  		id = fmt.Sprintf(" [%s=%s]", h.IDKey, h.IDValue)
   260  	}
   261  	return fmt.Sprintf("%s: Refreshing state...%s", h.Resource.Addr, id)
   262  }
   263  
   264  func NewRefreshStart(addr addrs.AbsResourceInstance, idKey, idValue string) Hook {
   265  	return &refreshStart{
   266  		Resource: newResourceAddr(addr),
   267  		IDKey:    idKey,
   268  		IDValue:  idValue,
   269  	}
   270  }
   271  
   272  // RefreshComplete: triggered by PostRefresh hook
   273  type refreshComplete struct {
   274  	Resource ResourceAddr `json:"resource"`
   275  	IDKey    string       `json:"id_key,omitempty"`
   276  	IDValue  string       `json:"id_value,omitempty"`
   277  }
   278  
   279  var _ Hook = (*refreshComplete)(nil)
   280  
   281  func (h *refreshComplete) HookType() MessageType {
   282  	return MessageRefreshComplete
   283  }
   284  
   285  func (h *refreshComplete) String() string {
   286  	var id string
   287  	if h.IDKey != "" && h.IDValue != "" {
   288  		id = fmt.Sprintf(" [%s=%s]", h.IDKey, h.IDValue)
   289  	}
   290  	return fmt.Sprintf("%s: Refresh complete%s", h.Resource.Addr, id)
   291  }
   292  
   293  func NewRefreshComplete(addr addrs.AbsResourceInstance, idKey, idValue string) Hook {
   294  	return &refreshComplete{
   295  		Resource: newResourceAddr(addr),
   296  		IDKey:    idKey,
   297  		IDValue:  idValue,
   298  	}
   299  }
   300  
   301  // Convert the subset of plans.Action values we expect to receive into a
   302  // present-tense verb for the applyStart hook message.
   303  func startActionVerb(action plans.Action) string {
   304  	switch action {
   305  	case plans.Create:
   306  		return "Creating"
   307  	case plans.Update:
   308  		return "Modifying"
   309  	case plans.Delete:
   310  		return "Destroying"
   311  	case plans.Read:
   312  		return "Refreshing"
   313  	case plans.CreateThenDelete, plans.DeleteThenCreate:
   314  		// This is not currently possible to reach, as we receive separate
   315  		// passes for create and delete
   316  		return "Replacing"
   317  	case plans.NoOp:
   318  		// This should never be possible: a no-op planned change should not
   319  		// be applied. We'll fall back to "Applying".
   320  		fallthrough
   321  	default:
   322  		return "Applying"
   323  	}
   324  }
   325  
   326  // Convert the subset of plans.Action values we expect to receive into a
   327  // present-tense verb for the applyProgress hook message. This will be
   328  // prefixed with "Still ", so it is lower-case.
   329  func progressActionVerb(action plans.Action) string {
   330  	switch action {
   331  	case plans.Create:
   332  		return "creating"
   333  	case plans.Update:
   334  		return "modifying"
   335  	case plans.Delete:
   336  		return "destroying"
   337  	case plans.Read:
   338  		return "refreshing"
   339  	case plans.CreateThenDelete, plans.DeleteThenCreate:
   340  		// This is not currently possible to reach, as we receive separate
   341  		// passes for create and delete
   342  		return "replacing"
   343  	case plans.NoOp:
   344  		// This should never be possible: a no-op planned change should not
   345  		// be applied. We'll fall back to "applying".
   346  		fallthrough
   347  	default:
   348  		return "applying"
   349  	}
   350  }
   351  
   352  // Convert the subset of plans.Action values we expect to receive into a
   353  // noun for the applyComplete and applyErrored hook messages. This will be
   354  // combined into a phrase like "Creation complete after 1m4s".
   355  func actionNoun(action plans.Action) string {
   356  	switch action {
   357  	case plans.Create:
   358  		return "Creation"
   359  	case plans.Update:
   360  		return "Modifications"
   361  	case plans.Delete:
   362  		return "Destruction"
   363  	case plans.Read:
   364  		return "Refresh"
   365  	case plans.CreateThenDelete, plans.DeleteThenCreate:
   366  		// This is not currently possible to reach, as we receive separate
   367  		// passes for create and delete
   368  		return "Replacement"
   369  	case plans.NoOp:
   370  		// This should never be possible: a no-op planned change should not
   371  		// be applied. We'll fall back to "Apply".
   372  		fallthrough
   373  	default:
   374  		return "Apply"
   375  	}
   376  }