2024-02-08 03:48:59 -06:00
|
|
|
// Copyright (c) The OpenTofu Authors
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
2023-05-02 10:33:06 -05:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2023-09-20 07:16:53 -05:00
|
|
|
package tofu
|
2015-03-24 11:18:15 -05:00
|
|
|
|
2015-05-01 11:01:49 -05:00
|
|
|
import (
|
|
|
|
"log"
|
|
|
|
|
2023-09-20 06:35:35 -05:00
|
|
|
"github.com/opentofu/opentofu/internal/addrs"
|
|
|
|
"github.com/opentofu/opentofu/internal/dag"
|
2015-05-01 11:01:49 -05:00
|
|
|
)
|
2015-03-24 11:18:15 -05:00
|
|
|
|
2017-01-26 22:16:06 -06:00
|
|
|
// GraphNodeTargetable is an interface for graph nodes to implement when they
|
2024-11-05 09:16:00 -06:00
|
|
|
// need to be told about incoming targets or excluded targets. This is useful for
|
|
|
|
// nodes that need to respect targets and excludes as they dynamically expand.
|
|
|
|
// Note that the lists of targets and excludes provided will contain every target
|
|
|
|
// or every exclude provided, and each implementing graph node must filter this
|
|
|
|
// list to targets considered relevant.
|
2017-01-26 22:16:06 -06:00
|
|
|
type GraphNodeTargetable interface {
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
|
|
|
SetTargets([]addrs.Targetable)
|
2024-11-05 09:16:00 -06:00
|
|
|
SetExcludes([]addrs.Targetable)
|
2017-01-26 22:16:06 -06:00
|
|
|
}
|
|
|
|
|
2024-11-05 09:16:00 -06:00
|
|
|
// TargetingTransformer is a GraphTransformer that, when the user specifies a
|
|
|
|
// list of resources to target, or a list of resources to exclude, limits the
|
|
|
|
// graph to only those resources and their dependencies (or in the case of
|
|
|
|
// excludes - limits the graph to all resources that are not excluded or not
|
|
|
|
// dependent on excluded resources).
|
|
|
|
type TargetingTransformer struct {
|
2015-03-24 11:18:15 -05:00
|
|
|
// List of targeted resource names specified by the user
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
|
|
|
Targets []addrs.Targetable
|
2024-11-05 09:16:00 -06:00
|
|
|
// List of excluded resource names specified by the user
|
|
|
|
Excludes []addrs.Targetable
|
2015-03-24 11:18:15 -05:00
|
|
|
}
|
|
|
|
|
2024-11-05 09:16:00 -06:00
|
|
|
func (t *TargetingTransformer) Transform(g *Graph) error {
|
|
|
|
var targetedNodes dag.Set
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
|
|
|
if len(t.Targets) > 0 {
|
2024-11-05 09:16:00 -06:00
|
|
|
targetedNodes = t.selectTargetedNodes(g, t.Targets)
|
|
|
|
} else if len(t.Excludes) > 0 {
|
|
|
|
targetedNodes = t.removeExcludedNodes(g, t.Excludes)
|
|
|
|
} else {
|
|
|
|
return nil
|
|
|
|
}
|
2015-03-24 11:18:15 -05:00
|
|
|
|
2024-11-05 09:16:00 -06:00
|
|
|
for _, v := range g.Vertices() {
|
|
|
|
if !targetedNodes.Include(v) {
|
|
|
|
log.Printf("[DEBUG] Removing %q, filtered by targeting.", dag.VertexName(v))
|
|
|
|
g.Remove(v)
|
2015-03-24 11:18:15 -05:00
|
|
|
}
|
|
|
|
}
|
2016-10-20 20:59:02 -05:00
|
|
|
|
2015-03-24 11:18:15 -05:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-11-05 09:16:00 -06:00
|
|
|
// selectTargetedNodes goes over a list of resource and modules targeted with a -target flag, and returns a set of
|
|
|
|
// targeted nodes. A targeted node is either addressed directly, address indirectly via its container, or it's a
|
|
|
|
// dependency of a targeted node.
|
|
|
|
func (t *TargetingTransformer) selectTargetedNodes(g *Graph, addrs []addrs.Targetable) dag.Set {
|
2020-01-07 16:49:34 -06:00
|
|
|
targetedNodes := make(dag.Set)
|
2017-05-10 20:27:49 -05:00
|
|
|
|
|
|
|
vertices := g.Vertices()
|
|
|
|
|
|
|
|
for _, v := range vertices {
|
2015-04-15 13:53:32 -05:00
|
|
|
if t.nodeIsTarget(v, addrs) {
|
|
|
|
targetedNodes.Add(v)
|
2015-03-24 11:18:15 -05:00
|
|
|
|
2015-04-15 13:53:32 -05:00
|
|
|
// We inform nodes that ask about the list of targets - helps for nodes
|
|
|
|
// that need to dynamically expand. Note that this only occurs for nodes
|
|
|
|
// that are already directly targeted.
|
|
|
|
if tn, ok := v.(GraphNodeTargetable); ok {
|
|
|
|
tn.SetTargets(addrs)
|
2015-03-30 19:02:36 -05:00
|
|
|
}
|
2015-03-24 11:18:15 -05:00
|
|
|
|
2020-06-24 09:27:52 -05:00
|
|
|
deps, _ := g.Ancestors(v)
|
2020-01-07 16:49:34 -06:00
|
|
|
for _, d := range deps {
|
2015-03-24 11:18:15 -05:00
|
|
|
targetedNodes.Add(d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-20 20:59:02 -05:00
|
|
|
|
2024-11-05 09:16:00 -06:00
|
|
|
targetedOutputNodes := t.getTargetedOutputNodes(targetedNodes, g)
|
|
|
|
for _, outputNode := range targetedOutputNodes {
|
|
|
|
targetedNodes.Add(outputNode)
|
|
|
|
}
|
|
|
|
|
|
|
|
return targetedNodes
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TargetingTransformer) getTargetableNodeResourceAddr(v dag.Vertex) addrs.Targetable {
|
|
|
|
switch r := v.(type) {
|
|
|
|
case GraphNodeResourceInstance:
|
|
|
|
return r.ResourceInstanceAddr()
|
|
|
|
case GraphNodeConfigResource:
|
|
|
|
return r.ResourceAddr()
|
|
|
|
default:
|
|
|
|
// Only resource and resource instance nodes can be targeted.
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// removeExcludedNodes goes over a list of excluded resources and modules, and returns a set of targeted nodes to be
|
|
|
|
// used for resource targeting. An excluded resource is either addressed directly, addressed indirectly via its
|
|
|
|
// container, or it's dependent on an excluded node. The rest are the targeted nodes used for resource targeting
|
|
|
|
func (t *TargetingTransformer) removeExcludedNodes(g *Graph, excludes []addrs.Targetable) dag.Set {
|
|
|
|
targetedNodes := make(dag.Set)
|
|
|
|
excludedNodes := make(dag.Set)
|
|
|
|
targetableNodes := make(dag.Set)
|
|
|
|
|
|
|
|
vertices := g.Vertices()
|
|
|
|
|
|
|
|
// Step 1: Find all excluded targetable nodes, and their descendants
|
|
|
|
for _, v := range vertices {
|
|
|
|
vertexAddr := t.getTargetableNodeResourceAddr(v)
|
|
|
|
if vertexAddr == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
targetableNodes.Add(v)
|
|
|
|
|
|
|
|
nodeExcluded := t.nodeIsExcluded(vertexAddr, excludes)
|
|
|
|
if nodeExcluded {
|
|
|
|
excludedNodes.Add(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
if nodeExcluded || t.nodeDescendantsExcluded(vertexAddr, excludes) {
|
|
|
|
deps, _ := g.Descendents(v)
|
|
|
|
for _, d := range deps {
|
|
|
|
// In general, we'd like to exclude any descendant targetable node of the current node.
|
|
|
|
// We exclude any resource dependent on this resource (which is more general than resources dependent
|
|
|
|
// on the resource instance, but is in-line with how -target works).
|
|
|
|
//
|
|
|
|
// The exception to this is when excluding a specific instance of a resource that has multiple instances.
|
|
|
|
// During apply, the specific instance tofu.NodeApplyableResourceInstance would be dependent on the
|
|
|
|
// resource tofu.nodeExpandApplyableResource.
|
|
|
|
// Since we do not want to exclude all resource instances (other than the ones that we've explicitly
|
|
|
|
// excluded), we should only exclude dependents whose target is not contained in the current node.
|
|
|
|
depVertexAddr := t.getTargetableNodeResourceAddr(d)
|
|
|
|
if depVertexAddr != nil && !vertexAddr.TargetContains(depVertexAddr) {
|
|
|
|
excludedNodes.Add(d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Step 2: Of the targetable nodes that were not excluded, build the graph similarly to -target
|
|
|
|
for _, v := range targetableNodes {
|
|
|
|
if !excludedNodes.Include(v) {
|
|
|
|
targetedNodes.Add(v)
|
|
|
|
|
|
|
|
// We inform nodes that ask about the list of excludes - helps for nodes
|
|
|
|
// that need to dynamically expand. Note that this only occurs for nodes
|
|
|
|
// that are targetable and we didn't exclude
|
|
|
|
if tn, ok := v.(GraphNodeTargetable); ok {
|
|
|
|
tn.SetExcludes(excludes)
|
|
|
|
}
|
|
|
|
|
|
|
|
deps, _ := g.Ancestors(v)
|
|
|
|
for _, d := range deps {
|
|
|
|
targetedNodes.Add(d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Step 3: Add outputs
|
|
|
|
targetedOutputNodes := t.getTargetedOutputNodes(targetedNodes, g)
|
|
|
|
for _, outputNode := range targetedOutputNodes {
|
|
|
|
targetedNodes.Add(outputNode)
|
|
|
|
}
|
|
|
|
|
|
|
|
return targetedNodes
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TargetingTransformer) getTargetedOutputNodes(targetedNodes dag.Set, graph *Graph) dag.Set {
|
2020-06-24 09:27:52 -05:00
|
|
|
// It is expected that outputs which are only derived from targeted
|
|
|
|
// resources are also updated. While we don't include any other possible
|
|
|
|
// side effects from the targeted nodes, these are added because outputs
|
|
|
|
// cannot be targeted on their own.
|
2024-11-05 09:16:00 -06:00
|
|
|
//
|
|
|
|
// Note: This behaviour has some quirks, as there are specific cases where
|
|
|
|
// you would think an output should not be updated, but it is
|
|
|
|
// For example, when there's a module call with an input that is dependent
|
|
|
|
// on a root resource, and only the root resource is targeted, any output
|
|
|
|
// that depends on a module output might be updated, if said module output
|
|
|
|
// does not depend on any resource of the module itself.
|
|
|
|
// Right now, we will not change this behaviour, as this has been the
|
|
|
|
// behaviour for quite a while. A possible fix could be a more detailed
|
|
|
|
// analysis of the outputs, and making sure that module outputs are only
|
|
|
|
// referenced if any of the targeted nodes is in said module
|
|
|
|
|
|
|
|
targetedOutputNodes := make(dag.Set)
|
|
|
|
vertices := graph.Vertices()
|
|
|
|
|
2020-06-24 09:27:52 -05:00
|
|
|
// Start by finding the root module output nodes themselves
|
|
|
|
for _, v := range vertices {
|
|
|
|
// outputs are all temporary value types
|
|
|
|
tv, ok := v.(graphNodeTemporaryValue)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
2017-05-10 20:27:49 -05:00
|
|
|
|
2020-06-24 09:27:52 -05:00
|
|
|
// root module outputs indicate that while they are an output type,
|
|
|
|
// they not temporary and will return false here.
|
|
|
|
if tv.temporaryValue() {
|
|
|
|
continue
|
|
|
|
}
|
2017-05-10 20:27:49 -05:00
|
|
|
|
2020-06-24 09:27:52 -05:00
|
|
|
// If this output is descended only from targeted resources, then we
|
|
|
|
// will keep it
|
2024-11-05 09:16:00 -06:00
|
|
|
deps, _ := graph.Ancestors(v)
|
2020-06-24 09:27:52 -05:00
|
|
|
found := 0
|
|
|
|
for _, d := range deps {
|
|
|
|
switch d.(type) {
|
|
|
|
case GraphNodeResourceInstance:
|
|
|
|
case GraphNodeConfigResource:
|
|
|
|
default:
|
2017-05-10 20:27:49 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-06-24 09:27:52 -05:00
|
|
|
if !targetedNodes.Include(d) {
|
|
|
|
// this dependency isn't being targeted, so we can't process this
|
|
|
|
// output
|
|
|
|
found = 0
|
|
|
|
break
|
2017-05-10 20:27:49 -05:00
|
|
|
}
|
2017-09-27 17:59:48 -05:00
|
|
|
|
2020-06-24 09:27:52 -05:00
|
|
|
found++
|
2017-09-27 17:59:48 -05:00
|
|
|
}
|
2018-03-19 20:20:06 -05:00
|
|
|
|
2020-06-24 09:27:52 -05:00
|
|
|
if found > 0 {
|
|
|
|
// we found an output we can keep; add it, and all it's dependencies
|
2024-11-05 09:16:00 -06:00
|
|
|
targetedOutputNodes.Add(v)
|
2020-06-24 09:27:52 -05:00
|
|
|
for _, d := range deps {
|
2024-11-05 09:16:00 -06:00
|
|
|
targetedOutputNodes.Add(d)
|
2020-06-24 09:27:52 -05:00
|
|
|
}
|
2018-03-19 20:20:06 -05:00
|
|
|
}
|
2017-09-27 17:59:48 -05:00
|
|
|
}
|
|
|
|
|
2024-11-05 09:16:00 -06:00
|
|
|
return targetedOutputNodes
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TargetingTransformer) nodeIsExcluded(vertexAddr addrs.Targetable, excludes []addrs.Targetable) bool {
|
|
|
|
for _, excludeAddr := range excludes {
|
|
|
|
if excludeAddr.TargetContains(vertexAddr) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TargetingTransformer) nodeDescendantsExcluded(vertexAddr addrs.Targetable, excludes []addrs.Targetable) bool {
|
|
|
|
for _, excludeAddr := range excludes {
|
|
|
|
// The behaviour here is a bit different from targets.
|
|
|
|
// Before expansion - We'd like to only exclude resources that were excluded by module or resource.
|
|
|
|
// If the excluded target is an AbsResourceInstance, then we'd want to skip exclude until we expand the resource
|
|
|
|
// After expansion - We'd like to exclude any vertex that contains the exclude address
|
|
|
|
// Since before expansion the vertexAddr is without an index, then if the excludeAddr is an instance, it will
|
|
|
|
// only contain vertexAddr if its key is NoKey
|
|
|
|
// So - a simple TargetContains here should be enough, both before and after expansion
|
|
|
|
|
|
|
|
if _, ok := vertexAddr.(addrs.ConfigResource); ok {
|
|
|
|
// Before expansion happens, we only have nodes that know their
|
|
|
|
// ConfigResource address. We need to take the more specific
|
|
|
|
// target addresses and generalize them in order to compare with a
|
|
|
|
// ConfigResource.
|
|
|
|
//
|
|
|
|
// If the excluded target, in is generalized form, contains the vertex address, then we know that we could remove the descendants
|
|
|
|
// even if we don't remove the node itself from the graph. However, this could cause cases where too many resources are excluded.
|
|
|
|
// For example, with -exclude=null_resource.a[1], and a null_resource.b[*] for which each instance depends on a single null_resource.a instance,
|
|
|
|
// all null_resource.b instances will be excluded. This is not accurate, but is in line with -target today, which over-targets dependencies
|
|
|
|
switch target := excludeAddr.(type) {
|
|
|
|
case addrs.AbsResourceInstance:
|
|
|
|
excludeAddr = target.ContainingResource().Config()
|
|
|
|
case addrs.AbsResource:
|
|
|
|
excludeAddr = target.Config()
|
|
|
|
case addrs.ModuleInstance:
|
|
|
|
excludeAddr = target.Module()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if excludeAddr.TargetContains(vertexAddr) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
2015-03-24 11:18:15 -05:00
|
|
|
}
|
|
|
|
|
2024-11-05 09:16:00 -06:00
|
|
|
func (t *TargetingTransformer) nodeIsTarget(v dag.Vertex, targets []addrs.Targetable) bool {
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
|
|
|
var vertexAddr addrs.Targetable
|
|
|
|
switch r := v.(type) {
|
|
|
|
case GraphNodeResourceInstance:
|
|
|
|
vertexAddr = r.ResourceInstanceAddr()
|
2020-03-15 10:32:06 -05:00
|
|
|
case GraphNodeConfigResource:
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
|
|
|
vertexAddr = r.ResourceAddr()
|
2020-08-05 16:50:23 -05:00
|
|
|
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
|
|
|
default:
|
|
|
|
// Only resource and resource instance nodes can be targeted.
|
|
|
|
return false
|
|
|
|
}
|
2016-10-20 20:59:02 -05:00
|
|
|
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
|
|
|
for _, targetAddr := range targets {
|
2020-08-05 16:50:23 -05:00
|
|
|
switch vertexAddr.(type) {
|
|
|
|
case addrs.ConfigResource:
|
|
|
|
// Before expansion happens, we only have nodes that know their
|
|
|
|
// ConfigResource address. We need to take the more specific
|
|
|
|
// target addresses and generalize them in order to compare with a
|
|
|
|
// ConfigResource.
|
|
|
|
switch target := targetAddr.(type) {
|
2020-06-10 14:39:29 -05:00
|
|
|
case addrs.AbsResourceInstance:
|
2020-08-05 16:50:23 -05:00
|
|
|
targetAddr = target.ContainingResource().Config()
|
|
|
|
case addrs.AbsResource:
|
|
|
|
targetAddr = target.Config()
|
2020-08-10 11:16:20 -05:00
|
|
|
case addrs.ModuleInstance:
|
|
|
|
targetAddr = target.Module()
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
|
|
|
}
|
core: -target option to also select resources in descendant modules
Previously the behavior for -target when given a module address was to
target only resources directly within that module, ignoring any resources
defined in child modules.
This behavior turned out to be counter-intuitive, since users expected
the -target address to be interpreted hierarchically.
We'll now use the new "Contains" function for addresses, which provides
a hierarchical "containment" concept that is more consistent with user
expectations. In particular, it allows module.foo to match
module.foo.module.bar.aws_instance.baz, where before that would not have
been true.
Since Contains isn't commutative (unlike Equals) this requires some
special handling for targeting specific indices. When given an argument
like -target=aws_instance.foo[0], the initial graph construction (for
both plan and refresh) is for the resource nodes from configuration, which
have not yet been expanded to separate indexed instances. Thus we need
to do the first pass of TargetsTransformer in mode where indices are
ignored, with the work then completed by the DynamicExpand method which
re-applies the TargetsTransformer in index-sensitive mode.
This is a breaking change for anyone depending on the previous behavior
of -target, since it will now select more resources than before. There is
no way provided to obtain the previous behavior. Eventually we may support
negative targeting, which could then combine with positive targets to
regain the previous behavior as an explicit choice.
2017-06-15 20:15:41 -05:00
|
|
|
}
|
2020-08-05 16:50:23 -05:00
|
|
|
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
|
|
|
if targetAddr.TargetContains(vertexAddr) {
|
2015-03-24 11:18:15 -05:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2016-10-20 20:59:02 -05:00
|
|
|
|
2015-03-24 11:18:15 -05:00
|
|
|
return false
|
|
|
|
}
|