Merge pull request #11921 from hashicorp/b-untarget-output

terraform: outputs should not be included if not targeted
This commit is contained in:
Mitchell Hashimoto 2017-02-15 10:47:14 -08:00 committed by GitHub
commit bbae22007d
11 changed files with 150 additions and 9 deletions

View File

@ -215,6 +215,7 @@ func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, error) {
State: c.state,
Providers: c.components.ResourceProviders(),
Provisioners: c.components.ResourceProvisioners(),
Targets: c.targets,
Destroy: c.destroy,
Validate: opts.Validate,
}).Build(RootModulePath)

View File

@ -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) {
m := testModule(t, "apply-targeted-module-resource")
p := testProvider("aws")

View File

@ -28,6 +28,12 @@ type ApplyGraphBuilder struct {
// Provisioners is the list of provisioners supported.
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 bool
@ -114,6 +120,9 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
// Add the node to fix the state count boundaries
&CountBoundaryTransformer{},
// Target
&TargetsTransformer{Targets: b.Targets},
// Single root
&RootTransformer{},
}

View File

@ -95,17 +95,15 @@ func TestApplyGraphBuilder_depCbd(t *testing.T) {
Modules: []*ModuleDiff{
&ModuleDiff{
Path: []string{"root"},
Resources: map[string]*InstanceDiff{
"aws_instance.A": &InstanceDiff{
Destroy: true,
Attributes: map[string]*ResourceAttrDiff{
"name": &ResourceAttrDiff{
Old: "",
New: "foo",
RequiresNew: true,
},
Resources: map[string]*InstanceDiff{"aws_instance.A": &InstanceDiff{Destroy: true,
Attributes: map[string]*ResourceAttrDiff{
"name": &ResourceAttrDiff{
Old: "",
New: "foo",
RequiresNew: true,
},
},
},
"aws_instance.B": &InstanceDiff{
Attributes: map[string]*ResourceAttrDiff{
@ -440,6 +438,54 @@ func TestApplyGraphBuilder_provisionerDestroy(t *testing.T) {
"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 = `
aws_instance.create
provider.aws

View File

@ -28,6 +28,13 @@ func (n *NodeApplyableOutput) Path() []string {
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
func (n *NodeApplyableOutput) ReferenceableName() []string {
name := fmt.Sprintf("output.%s", n.Config.Name)

View File

@ -0,0 +1,10 @@
variable "instance_id" {
}
output "instance_id" {
value = "${var.instance_id}"
}
resource "aws_instance" "foo" {
foo = "${var.instance_id}"
}

View File

@ -0,0 +1,2 @@
resource "aws_instance" "foo" {
}

View File

@ -0,0 +1,10 @@
resource "aws_instance" "foo" {}
module "child1" {
source = "./child1"
instance_id = "${aws_instance.foo.id}"
}
module "child2" {
source = "./child2"
}

View File

@ -0,0 +1,12 @@
variable "instance_id" {
}
output "instance_id" {
value = "${var.instance_id}"
}
resource "null_resource" "foo" {
triggers = {
instance_id = "${var.instance_id}"
}
}

View File

@ -0,0 +1,2 @@
resource "null_resource" "foo" {
}

View File

@ -0,0 +1,10 @@
resource "null_resource" "foo" {}
module "child1" {
source = "./child1"
instance_id = "${null_resource.foo.id}"
}
module "child2" {
source = "./child2"
}