-
Notifications
You must be signed in to change notification settings - Fork 9.4k
/
component.go
143 lines (122 loc) · 5.59 KB
/
component.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package stackplan
import (
"fmt"
"time"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/collections"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/stacks/stackaddrs"
"github.com/hashicorp/terraform/internal/states"
)
// Component is a container for a set of changes that all belong to the same
// component instance as declared in a stack configuration.
//
// Each instance of component essentially maps to one call into the main
// Terraform language runtime to apply all of the described changes together as
// a single operation.
type Component struct {
PlannedAction plans.Action
// These fields echo the [plans.Plan.Applyable] and [plans.Plan.Complete]
// field respectively. See the docs for those fields for more information.
PlanApplyable, PlanComplete bool
// ResourceInstancePlanned describes the changes that Terraform is proposing
// to make to try to converge the real system state with the desired state
// as described by the configuration.
ResourceInstancePlanned addrs.Map[addrs.AbsResourceInstanceObject, *plans.ResourceInstanceChangeSrc]
// ResourceInstancePriorState describes the state as it was when making
// the proposals described in [Component.ResourceInstancePlanned].
//
// Elements of this map have nil values if the planned action is "create",
// since in that case there is no prior object.
ResourceInstancePriorState addrs.Map[addrs.AbsResourceInstanceObject, *states.ResourceInstanceObjectSrc]
// ResourceInstanceProviderConfig is a lookup table from resource instance
// object address to the address of the provider configuration that
// will handle any apply-time actions for that object.
ResourceInstanceProviderConfig addrs.Map[addrs.AbsResourceInstanceObject, addrs.AbsProviderConfig]
// DeferredResourceInstanceChanges is a set of resource instance objects
// that have changes that are deferred to a later plan and apply cycle.
DeferredResourceInstanceChanges addrs.Map[addrs.AbsResourceInstanceObject, *plans.DeferredResourceInstanceChangeSrc]
// PlanTimestamp is the time Terraform Core recorded as the single "plan
// timestamp", which is used only for the result of the "plantimestamp"
// function during apply and must not be used for any other purpose.
PlanTimestamp time.Time
// Dependencies is a set of addresses of other components that this one
// expects to exist for as long as this one exists.
Dependencies collections.Set[stackaddrs.AbsComponent]
// Dependents is the reverse of [Component.Dependencies], describing
// the other components that must be destroyed before this one could
// be destroyed.
Dependents collections.Set[stackaddrs.AbsComponent]
PlannedOutputValues map[addrs.OutputValue]cty.Value
PlannedChecks *states.CheckResults
}
// ForModulesRuntime translates the component instance plan into the form
// expected by the modules runtime, which is what would ultimately be used
// to apply the plan.
//
// The stack component planning model preserves only the most crucial details
// of a component plan produced by the modules runtime, and so the result
// will not exactly match the [plans.Plan] that the component plan was produced
// from, but should be complete enough to successfully apply the plan.
//
// Conversion with this method should always succeed if the given previous
// run state is truly the one that the plan was created from. If this method
// returns an error then that suggests that the recieving plan is inconsistent
// with the given previous run state, which should not happen if the caller
// is using Terraform Core correctly.
func (c *Component) ForModulesRuntime() (*plans.Plan, error) {
changes := plans.NewChanges()
plan := &plans.Plan{
Changes: changes,
Timestamp: c.PlanTimestamp,
Applyable: c.PlanApplyable,
Complete: c.PlanComplete,
Checks: c.PlannedChecks,
}
sc := changes.SyncWrapper()
for _, elem := range c.ResourceInstancePlanned.Elems {
changeSrc := elem.Value
if changeSrc != nil {
sc.AppendResourceInstanceChange(changeSrc)
}
}
priorState := states.NewState()
ss := priorState.SyncWrapper()
for _, elem := range c.ResourceInstancePriorState.Elems {
addr := elem.Key
providerConfigAddr, ok := c.ResourceInstanceProviderConfig.GetOk(addr)
if !ok {
return nil, fmt.Errorf("no provider config address for %s", addr)
}
stateSrc := elem.Value
if addr.IsCurrent() {
ss.SetResourceInstanceCurrent(addr.ResourceInstance, stateSrc, providerConfigAddr)
} else {
ss.SetResourceInstanceDeposed(addr.ResourceInstance, addr.DeposedKey, stateSrc, providerConfigAddr)
}
}
plan.PriorState = priorState
plan.PrevRunState = priorState.DeepCopy() // This is just here to complete the data structure; we don't really do anything with it
return plan, nil
}
// RequiredProviderInstances returns a description of all the provider instance
// slots that are required to satisfy the resource instances planned for this
// component.
//
// See also stackstate.State.RequiredProviderInstances and
// stackeval.ComponentConfig.RequiredProviderInstances for similar functions
// that retrieve the provider instances for a components in the config and in
// the state.
func (c *Component) RequiredProviderInstances() addrs.Set[addrs.RootProviderConfig] {
providerInstances := addrs.MakeSet[addrs.RootProviderConfig]()
for _, elem := range c.ResourceInstanceProviderConfig.Elems {
providerInstances.Add(addrs.RootProviderConfig{
Provider: elem.Value.Provider,
Alias: elem.Value.Alias,
})
}
return providerInstances
}