terraform: outputs should not be included if not targeted
Fixes #10911 Outputs that aren't targeted shouldn't be included in the graph. This requires passing targets to the apply graph. This is unfortunate but long term should be removable since I'd like to move output changes to the diff as well.
This commit is contained in:
parent
911717c9d5
commit
4d6085b46a
|
@ -215,6 +215,7 @@ func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, error) {
|
||||||
State: c.state,
|
State: c.state,
|
||||||
Providers: c.components.ResourceProviders(),
|
Providers: c.components.ResourceProviders(),
|
||||||
Provisioners: c.components.ResourceProvisioners(),
|
Provisioners: c.components.ResourceProvisioners(),
|
||||||
|
Targets: c.targets,
|
||||||
Destroy: c.destroy,
|
Destroy: c.destroy,
|
||||||
Validate: opts.Validate,
|
Validate: opts.Validate,
|
||||||
}).Build(RootModulePath)
|
}).Build(RootModulePath)
|
||||||
|
|
|
@ -6977,6 +6977,38 @@ module.child:
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GH-10911 untargeted outputs should not be in the graph, and therefore
|
||||||
|
// not execute.
|
||||||
|
func TestContext2Apply_targetedModuleUnrelatedOutputs(t *testing.T) {
|
||||||
|
m := testModule(t, "apply-targeted-module-unrelated-outputs")
|
||||||
|
p := testProvider("aws")
|
||||||
|
p.ApplyFn = testApplyFn
|
||||||
|
p.DiffFn = testDiffFn
|
||||||
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
Module: m,
|
||||||
|
Providers: map[string]ResourceProviderFactory{
|
||||||
|
"aws": testProviderFuncFixed(p),
|
||||||
|
},
|
||||||
|
Targets: []string{"module.child2"},
|
||||||
|
})
|
||||||
|
|
||||||
|
if _, err := ctx.Plan(); err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
state, err := ctx.Apply()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkStateString(t, state, `
|
||||||
|
<no state>
|
||||||
|
module.child2:
|
||||||
|
aws_instance.foo:
|
||||||
|
ID = foo
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestContext2Apply_targetedModuleResource(t *testing.T) {
|
func TestContext2Apply_targetedModuleResource(t *testing.T) {
|
||||||
m := testModule(t, "apply-targeted-module-resource")
|
m := testModule(t, "apply-targeted-module-resource")
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
|
|
|
@ -28,6 +28,12 @@ type ApplyGraphBuilder struct {
|
||||||
// Provisioners is the list of provisioners supported.
|
// Provisioners is the list of provisioners supported.
|
||||||
Provisioners []string
|
Provisioners []string
|
||||||
|
|
||||||
|
// Targets are resources to target. This is only required to make sure
|
||||||
|
// unnecessary outputs aren't included in the apply graph. The plan
|
||||||
|
// builder successfully handles targeting resources. In the future,
|
||||||
|
// outputs should go into the diff so that this is unnecessary.
|
||||||
|
Targets []string
|
||||||
|
|
||||||
// DisableReduce, if true, will not reduce the graph. Great for testing.
|
// DisableReduce, if true, will not reduce the graph. Great for testing.
|
||||||
DisableReduce bool
|
DisableReduce bool
|
||||||
|
|
||||||
|
@ -114,6 +120,9 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
||||||
// Add the node to fix the state count boundaries
|
// Add the node to fix the state count boundaries
|
||||||
&CountBoundaryTransformer{},
|
&CountBoundaryTransformer{},
|
||||||
|
|
||||||
|
// Target
|
||||||
|
&TargetsTransformer{Targets: b.Targets},
|
||||||
|
|
||||||
// Single root
|
// Single root
|
||||||
&RootTransformer{},
|
&RootTransformer{},
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,9 +95,7 @@ func TestApplyGraphBuilder_depCbd(t *testing.T) {
|
||||||
Modules: []*ModuleDiff{
|
Modules: []*ModuleDiff{
|
||||||
&ModuleDiff{
|
&ModuleDiff{
|
||||||
Path: []string{"root"},
|
Path: []string{"root"},
|
||||||
Resources: map[string]*InstanceDiff{
|
Resources: map[string]*InstanceDiff{"aws_instance.A": &InstanceDiff{Destroy: true,
|
||||||
"aws_instance.A": &InstanceDiff{
|
|
||||||
Destroy: true,
|
|
||||||
Attributes: map[string]*ResourceAttrDiff{
|
Attributes: map[string]*ResourceAttrDiff{
|
||||||
"name": &ResourceAttrDiff{
|
"name": &ResourceAttrDiff{
|
||||||
Old: "",
|
Old: "",
|
||||||
|
@ -440,6 +438,54 @@ func TestApplyGraphBuilder_provisionerDestroy(t *testing.T) {
|
||||||
"null_resource.foo (destroy)")
|
"null_resource.foo (destroy)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApplyGraphBuilder_targetModule(t *testing.T) {
|
||||||
|
diff := &Diff{
|
||||||
|
Modules: []*ModuleDiff{
|
||||||
|
&ModuleDiff{
|
||||||
|
Path: []string{"root"},
|
||||||
|
Resources: map[string]*InstanceDiff{
|
||||||
|
"null_resource.foo": &InstanceDiff{
|
||||||
|
Attributes: map[string]*ResourceAttrDiff{
|
||||||
|
"name": &ResourceAttrDiff{
|
||||||
|
Old: "",
|
||||||
|
New: "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
&ModuleDiff{
|
||||||
|
Path: []string{"root", "child2"},
|
||||||
|
Resources: map[string]*InstanceDiff{
|
||||||
|
"null_resource.foo": &InstanceDiff{
|
||||||
|
Attributes: map[string]*ResourceAttrDiff{
|
||||||
|
"name": &ResourceAttrDiff{
|
||||||
|
Old: "",
|
||||||
|
New: "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &ApplyGraphBuilder{
|
||||||
|
Module: testModule(t, "graph-builder-apply-target-module"),
|
||||||
|
Diff: diff,
|
||||||
|
Providers: []string{"null"},
|
||||||
|
Targets: []string{"module.child2"},
|
||||||
|
}
|
||||||
|
|
||||||
|
g, err := b.Build(RootModulePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testGraphNotContains(t, g, "module.child1.output.instance_id")
|
||||||
|
}
|
||||||
|
|
||||||
const testApplyGraphBuilderStr = `
|
const testApplyGraphBuilderStr = `
|
||||||
aws_instance.create
|
aws_instance.create
|
||||||
provider.aws
|
provider.aws
|
||||||
|
|
|
@ -28,6 +28,13 @@ func (n *NodeApplyableOutput) Path() []string {
|
||||||
return n.PathValue
|
return n.PathValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemovableIfNotTargeted
|
||||||
|
func (n *NodeApplyableOutput) RemoveIfNotTargeted() bool {
|
||||||
|
// We need to add this so that this node will be removed if
|
||||||
|
// it isn't targeted or a dependency of a target.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// GraphNodeReferenceable
|
// GraphNodeReferenceable
|
||||||
func (n *NodeApplyableOutput) ReferenceableName() []string {
|
func (n *NodeApplyableOutput) ReferenceableName() []string {
|
||||||
name := fmt.Sprintf("output.%s", n.Config.Name)
|
name := fmt.Sprintf("output.%s", n.Config.Name)
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
variable "instance_id" {
|
||||||
|
}
|
||||||
|
|
||||||
|
output "instance_id" {
|
||||||
|
value = "${var.instance_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "foo" {
|
||||||
|
foo = "${var.instance_id}"
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
resource "aws_instance" "foo" {
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
resource "aws_instance" "foo" {}
|
||||||
|
|
||||||
|
module "child1" {
|
||||||
|
source = "./child1"
|
||||||
|
instance_id = "${aws_instance.foo.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "child2" {
|
||||||
|
source = "./child2"
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
variable "instance_id" {
|
||||||
|
}
|
||||||
|
|
||||||
|
output "instance_id" {
|
||||||
|
value = "${var.instance_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "null_resource" "foo" {
|
||||||
|
triggers = {
|
||||||
|
instance_id = "${var.instance_id}"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
resource "null_resource" "foo" {
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
resource "null_resource" "foo" {}
|
||||||
|
|
||||||
|
module "child1" {
|
||||||
|
source = "./child1"
|
||||||
|
instance_id = "${null_resource.foo.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "child2" {
|
||||||
|
source = "./child2"
|
||||||
|
}
|
Loading…
Reference in New Issue