mirror of
https://github.com/hashicorp/terraform.git
synced 2026-02-03 20:50:59 -05:00
184 lines
5.1 KiB
Go
184 lines
5.1 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package plans
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
"github.com/hashicorp/terraform/internal/addrs"
|
|
"github.com/hashicorp/terraform/internal/configs"
|
|
"github.com/hashicorp/terraform/internal/lang/marks"
|
|
"github.com/hashicorp/terraform/internal/providers"
|
|
"github.com/hashicorp/terraform/internal/tfdiags"
|
|
)
|
|
|
|
type ActionInvocationInstance struct {
|
|
Addr addrs.AbsActionInstance
|
|
|
|
ActionTrigger ActionTrigger
|
|
|
|
// Provider is the address of the provider configuration that was used
|
|
// to plan this action, and thus the configuration that must also be
|
|
// used to apply it.
|
|
ProviderAddr addrs.AbsProviderConfig
|
|
|
|
ConfigValue cty.Value
|
|
}
|
|
|
|
func (ai *ActionInvocationInstance) Equals(other *ActionInvocationInstance) bool {
|
|
// Since the trigger can be the same if it's a CLI invocation we also compare the action addr
|
|
return ai.Addr.Equal(other.Addr) && ai.ActionTrigger.Equals(other.ActionTrigger)
|
|
}
|
|
|
|
type ActionTrigger interface {
|
|
actionTriggerSigil()
|
|
|
|
TriggerEvent() configs.ActionTriggerEvent
|
|
|
|
String() string
|
|
|
|
Equals(to ActionTrigger) bool
|
|
|
|
Less(other ActionTrigger) bool
|
|
}
|
|
|
|
var (
|
|
_ ActionTrigger = (*LifecycleActionTrigger)(nil)
|
|
_ ActionTrigger = (*InvokeActionTrigger)(nil)
|
|
)
|
|
|
|
type LifecycleActionTrigger struct {
|
|
TriggeringResourceAddr addrs.AbsResourceInstance
|
|
// Information about the trigger
|
|
// The event that triggered this action invocation.
|
|
ActionTriggerEvent configs.ActionTriggerEvent
|
|
// The index of the action_trigger block that triggered this invocation.
|
|
ActionTriggerBlockIndex int
|
|
// The index of the action in the events list of the action_trigger block
|
|
ActionsListIndex int
|
|
}
|
|
|
|
func (t *LifecycleActionTrigger) TriggerEvent() configs.ActionTriggerEvent {
|
|
return t.ActionTriggerEvent
|
|
}
|
|
|
|
func (t *LifecycleActionTrigger) actionTriggerSigil() {}
|
|
|
|
func (t *LifecycleActionTrigger) String() string {
|
|
return t.TriggeringResourceAddr.String()
|
|
}
|
|
|
|
func (t *LifecycleActionTrigger) Equals(other ActionTrigger) bool {
|
|
o, ok := other.(*LifecycleActionTrigger)
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
return t.TriggeringResourceAddr.Equal(o.TriggeringResourceAddr) &&
|
|
t.ActionTriggerBlockIndex == o.ActionTriggerBlockIndex &&
|
|
t.ActionsListIndex == o.ActionsListIndex &&
|
|
t.ActionTriggerEvent == o.ActionTriggerEvent
|
|
}
|
|
|
|
func (t *LifecycleActionTrigger) Less(other ActionTrigger) bool {
|
|
o, ok := other.(*LifecycleActionTrigger)
|
|
if !ok {
|
|
return false // We always want to show non-lifecycle actions first
|
|
}
|
|
|
|
return t.TriggeringResourceAddr.Less(o.TriggeringResourceAddr) ||
|
|
(t.TriggeringResourceAddr.Equal(o.TriggeringResourceAddr) &&
|
|
t.ActionTriggerBlockIndex < o.ActionTriggerBlockIndex) ||
|
|
(t.TriggeringResourceAddr.Equal(o.TriggeringResourceAddr) &&
|
|
t.ActionTriggerBlockIndex == o.ActionTriggerBlockIndex &&
|
|
t.ActionsListIndex < o.ActionsListIndex &&
|
|
t.ActionTriggerEvent < o.ActionTriggerEvent)
|
|
}
|
|
|
|
type InvokeActionTrigger struct{}
|
|
|
|
func (t *InvokeActionTrigger) actionTriggerSigil() {}
|
|
|
|
func (t *InvokeActionTrigger) String() string {
|
|
return "CLI"
|
|
}
|
|
|
|
func (t *InvokeActionTrigger) TriggerEvent() configs.ActionTriggerEvent {
|
|
return configs.Invoke
|
|
}
|
|
|
|
func (t *InvokeActionTrigger) Equals(other ActionTrigger) bool {
|
|
_, ok := other.(*InvokeActionTrigger)
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
return true // InvokeActionTriggers are always considered equal
|
|
}
|
|
|
|
func (t *InvokeActionTrigger) Less(other ActionTrigger) bool {
|
|
// always return true, actions that are equal are already ordered by
|
|
// address externally. these actions should go first anyway.
|
|
return true
|
|
}
|
|
|
|
// Encode produces a variant of the receiver that has its change values
|
|
// serialized so it can be written to a plan file. Pass the implied type of the
|
|
// corresponding resource type schema for correct operation.
|
|
func (ai *ActionInvocationInstance) Encode(schema *providers.ActionSchema) (*ActionInvocationInstanceSrc, error) {
|
|
|
|
ret := &ActionInvocationInstanceSrc{
|
|
Addr: ai.Addr,
|
|
ActionTrigger: ai.ActionTrigger,
|
|
ProviderAddr: ai.ProviderAddr,
|
|
}
|
|
|
|
if ai.ConfigValue != cty.NilVal {
|
|
ty := cty.DynamicPseudoType
|
|
if schema != nil {
|
|
ty = schema.ConfigSchema.ImpliedType()
|
|
}
|
|
|
|
unmarkedConfigValue, pvms := ai.ConfigValue.UnmarkDeepWithPaths()
|
|
sensitivePaths, otherMarks := marks.PathsWithMark(pvms, marks.Sensitive)
|
|
if len(otherMarks) > 0 {
|
|
return nil, fmt.Errorf("%s: error serializing action invocation with unexpected marks on config value: %#v. This is a bug in Terraform.", tfdiags.FormatCtyPath(otherMarks[0].Path), otherMarks[0].Marks)
|
|
}
|
|
|
|
var err error
|
|
ret.ConfigValue, err = NewDynamicValue(unmarkedConfigValue, ty)
|
|
ret.SensitiveConfigPaths = sensitivePaths
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return ret, nil
|
|
|
|
}
|
|
|
|
type ActionInvocationInstances []*ActionInvocationInstance
|
|
|
|
func (ais ActionInvocationInstances) DeepCopy() ActionInvocationInstances {
|
|
if ais == nil {
|
|
return ais
|
|
}
|
|
|
|
ret := make(ActionInvocationInstances, len(ais))
|
|
for i, ai := range ais {
|
|
ret[i] = ai.DeepCopy()
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (ai *ActionInvocationInstance) DeepCopy() *ActionInvocationInstance {
|
|
if ai == nil {
|
|
return ai
|
|
}
|
|
|
|
ret := *ai
|
|
return &ret
|
|
}
|