mirror of
https://github.com/opentffoundation/opentf.git
synced 2026-02-17 19:00:37 -05:00
We have two different reasons why a data resource might be read only during apply, rather than during planning as usual: the configuration contains unknown values, or the data resource as a whole depends on a managed resource which itself has a change pending. However, we didn't previously distinguish these two in a way that allowed the UI to describe the difference, and so we confusingly reported both as "config refers to values not yet known", which in turn led to a number of reasonable questions about why Terraform was claiming that but then immediately below showing the configuration entirely known. Now we'll use our existing "ActionReason" mechanism to tell the UI layer which of the two reasons applies to a particular data resource instance. The "dependency pending" situation tends to happen in conjunction with "config unknown", so we'll prefer to refer that the configuration is unknown if both are true.
120 lines
3.8 KiB
Go
120 lines
3.8 KiB
Go
package json
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform/internal/plans"
|
|
)
|
|
|
|
func NewResourceInstanceChange(change *plans.ResourceInstanceChangeSrc) *ResourceInstanceChange {
|
|
c := &ResourceInstanceChange{
|
|
Resource: newResourceAddr(change.Addr),
|
|
Action: changeAction(change.Action),
|
|
Reason: changeReason(change.ActionReason),
|
|
}
|
|
if !change.Addr.Equal(change.PrevRunAddr) {
|
|
if c.Action == ActionNoOp {
|
|
c.Action = ActionMove
|
|
}
|
|
pr := newResourceAddr(change.PrevRunAddr)
|
|
c.PreviousResource = &pr
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
type ResourceInstanceChange struct {
|
|
Resource ResourceAddr `json:"resource"`
|
|
PreviousResource *ResourceAddr `json:"previous_resource,omitempty"`
|
|
Action ChangeAction `json:"action"`
|
|
Reason ChangeReason `json:"reason,omitempty"`
|
|
}
|
|
|
|
func (c *ResourceInstanceChange) String() string {
|
|
return fmt.Sprintf("%s: Plan to %s", c.Resource.Addr, c.Action)
|
|
}
|
|
|
|
type ChangeAction string
|
|
|
|
const (
|
|
ActionNoOp ChangeAction = "noop"
|
|
ActionMove ChangeAction = "move"
|
|
ActionCreate ChangeAction = "create"
|
|
ActionRead ChangeAction = "read"
|
|
ActionUpdate ChangeAction = "update"
|
|
ActionReplace ChangeAction = "replace"
|
|
ActionDelete ChangeAction = "delete"
|
|
)
|
|
|
|
func changeAction(action plans.Action) ChangeAction {
|
|
switch action {
|
|
case plans.NoOp:
|
|
return ActionNoOp
|
|
case plans.Create:
|
|
return ActionCreate
|
|
case plans.Read:
|
|
return ActionRead
|
|
case plans.Update:
|
|
return ActionUpdate
|
|
case plans.DeleteThenCreate, plans.CreateThenDelete:
|
|
return ActionReplace
|
|
case plans.Delete:
|
|
return ActionDelete
|
|
default:
|
|
return ActionNoOp
|
|
}
|
|
}
|
|
|
|
type ChangeReason string
|
|
|
|
const (
|
|
ReasonNone ChangeReason = ""
|
|
ReasonTainted ChangeReason = "tainted"
|
|
ReasonRequested ChangeReason = "requested"
|
|
ReasonReplaceTriggeredBy ChangeReason = "replace_triggered_by"
|
|
ReasonCannotUpdate ChangeReason = "cannot_update"
|
|
ReasonUnknown ChangeReason = "unknown"
|
|
|
|
ReasonDeleteBecauseNoResourceConfig ChangeReason = "delete_because_no_resource_config"
|
|
ReasonDeleteBecauseWrongRepetition ChangeReason = "delete_because_wrong_repetition"
|
|
ReasonDeleteBecauseCountIndex ChangeReason = "delete_because_count_index"
|
|
ReasonDeleteBecauseEachKey ChangeReason = "delete_because_each_key"
|
|
ReasonDeleteBecauseNoModule ChangeReason = "delete_because_no_module"
|
|
ReasonReadBecauseConfigUnknown ChangeReason = "read_because_config_unknown"
|
|
ReasonReadBecauseDependencyPending ChangeReason = "read_because_dependency_pending"
|
|
)
|
|
|
|
func changeReason(reason plans.ResourceInstanceChangeActionReason) ChangeReason {
|
|
switch reason {
|
|
case plans.ResourceInstanceChangeNoReason:
|
|
return ReasonNone
|
|
case plans.ResourceInstanceReplaceBecauseTainted:
|
|
return ReasonTainted
|
|
case plans.ResourceInstanceReplaceByRequest:
|
|
return ReasonRequested
|
|
case plans.ResourceInstanceReplaceBecauseCannotUpdate:
|
|
return ReasonCannotUpdate
|
|
case plans.ResourceInstanceReplaceByTriggers:
|
|
return ReasonReplaceTriggeredBy
|
|
case plans.ResourceInstanceDeleteBecauseNoResourceConfig:
|
|
return ReasonDeleteBecauseNoResourceConfig
|
|
case plans.ResourceInstanceDeleteBecauseWrongRepetition:
|
|
return ReasonDeleteBecauseWrongRepetition
|
|
case plans.ResourceInstanceDeleteBecauseCountIndex:
|
|
return ReasonDeleteBecauseCountIndex
|
|
case plans.ResourceInstanceDeleteBecauseEachKey:
|
|
return ReasonDeleteBecauseEachKey
|
|
case plans.ResourceInstanceDeleteBecauseNoModule:
|
|
return ReasonDeleteBecauseNoModule
|
|
case plans.ResourceInstanceReadBecauseConfigUnknown:
|
|
return ReasonReadBecauseConfigUnknown
|
|
case plans.ResourceInstanceReadBecauseDependencyPending:
|
|
return ReasonReadBecauseDependencyPending
|
|
default:
|
|
// This should never happen, but there's no good way to guarantee
|
|
// exhaustive handling of the enum, so a generic fall back is better
|
|
// than a misleading result or a panic
|
|
return ReasonUnknown
|
|
}
|
|
}
|