command/show: add "module_version" to "module_calls" in config (#20367)

* command/show: add "module_version" to "module_calls" in config portion
of `terraform show`.

Also extended the `terraform show -json` test to run `init` so we could
add examples with modules. This does _not_ test the "module_version"
yet, but it _did_ help expose a bug in jsonplan where modules were
duplicated. This is also fixed in this PR.

* command/jsonconfig: rename version to version_constraint and
resolved_source to source.
This commit is contained in:
Kristin Laemmert 2019-02-19 08:12:33 -08:00 committed by GitHub
parent 0ff04b1232
commit 818b4ec068
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 248 additions and 20 deletions

View File

@ -41,11 +41,12 @@ type module struct {
} }
type moduleCall struct { type moduleCall struct {
ResolvedSource string `json:"resolved_source,omitempty"` Source string `json:"source,omitempty"`
Expressions map[string]interface{} `json:"expressions,omitempty"` Expressions map[string]interface{} `json:"expressions,omitempty"`
CountExpression *expression `json:"count_expression,omitempty"` CountExpression *expression `json:"count_expression,omitempty"`
ForEachExpression *expression `json:"for_each_expression,omitempty"` ForEachExpression *expression `json:"for_each_expression,omitempty"`
Module module `json:"module,omitempty"` Module module `json:"module,omitempty"`
VersionConstraint string `json:"version_constraint,omitempty"`
} }
// variables is the JSON representation of the variables provided to the current // variables is the JSON representation of the variables provided to the current
@ -197,7 +198,8 @@ func marshalModuleCalls(c *configs.Config, schemas *terraform.Schemas) map[strin
ret := make(map[string]moduleCall) ret := make(map[string]moduleCall)
for _, mc := range c.Module.ModuleCalls { for _, mc := range c.Module.ModuleCalls {
retMC := moduleCall{ retMC := moduleCall{
ResolvedSource: mc.SourceAddr, Source: mc.SourceAddr,
VersionConstraint: mc.Version.Required.String(),
} }
cExp := marshalExpression(mc.Count) cExp := marshalExpression(mc.Count)
if !cExp.Empty() { if !cExp.Empty() {

View File

@ -88,6 +88,7 @@ func marshalPlannedValues(changes *plans.Changes, schemas *terraform.Schemas) (m
// module -> [children modules] // module -> [children modules]
moduleResourceMap := make(map[string][]addrs.AbsResourceInstance) moduleResourceMap := make(map[string][]addrs.AbsResourceInstance)
moduleMap := make(map[string][]addrs.ModuleInstance) moduleMap := make(map[string][]addrs.ModuleInstance)
seenModules := make(map[string]bool)
for _, resource := range changes.Resources { for _, resource := range changes.Resources {
// if the resource is being deleted, skip over it. // if the resource is being deleted, skip over it.
@ -98,7 +99,10 @@ func marshalPlannedValues(changes *plans.Changes, schemas *terraform.Schemas) (m
// root has no parents. // root has no parents.
if containingModule != "" { if containingModule != "" {
parent := resource.Addr.Module.Parent().String() parent := resource.Addr.Module.Parent().String()
if !seenModules[parent] {
moduleMap[parent] = append(moduleMap[parent], resource.Addr.Module) moduleMap[parent] = append(moduleMap[parent], resource.Addr.Module)
seenModules[parent] = true
}
} }
} }
} }

View File

@ -10,6 +10,7 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/helper/copy"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
@ -146,24 +147,35 @@ func TestShow_json_output(t *testing.T) {
} }
t.Run(entry.Name(), func(t *testing.T) { t.Run(entry.Name(), func(t *testing.T) {
td := tempDir(t)
inputDir := filepath.Join(fixtureDir, entry.Name()) inputDir := filepath.Join(fixtureDir, entry.Name())
copy.CopyDir(inputDir, td)
cwd, err := os.Getwd() defer os.RemoveAll(td)
if err != nil { defer testChdir(t, td)()
t.Fatalf("err: %s", err)
}
if err := os.Chdir(inputDir); err != nil {
t.Fatalf("err: %s", err)
}
defer os.Chdir(cwd)
p := showFixtureProvider() p := showFixtureProvider()
ui := new(cli.MockUi) ui := new(cli.MockUi)
pc := &PlanCommand{ m := Meta{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p), testingOverrides: metaOverridesForProvider(p),
Ui: ui, Ui: ui,
}
// init
ic := &InitCommand{
Meta: m,
providerInstaller: &mockProviderInstaller{
Providers: map[string][]string{
"test": []string{"1.2.3"},
}, },
Dir: m.pluginDir(),
},
}
if code := ic.Run([]string{}); code != 0 {
t.Fatalf("init failed\n%s", ui.ErrorWriter)
}
pc := &PlanCommand{
Meta: m,
} }
args := []string{ args := []string{
@ -177,10 +189,7 @@ func TestShow_json_output(t *testing.T) {
// flush the plan output from the mock ui // flush the plan output from the mock ui
ui.OutputWriter.Reset() ui.OutputWriter.Reset()
sc := &ShowCommand{ sc := &ShowCommand{
Meta: Meta{ Meta: m,
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
},
} }
args = []string{ args = []string{

View File

@ -0,0 +1,11 @@
variable "test_var" {
default = "bar"
}
resource "test_instance" "test" {
ami = var.test_var
count = 3
}
output "test" {
value = var.test_var
}

View File

@ -0,0 +1,8 @@
module "test" {
source = "./foo"
test_var = "baz"
}
output "test" {
value = module.test.test
}

View File

@ -0,0 +1 @@
{"Modules":[{"Key":"","Source":"","Dir":"/Users/kristin/go/src/github.com/hashicorp/terraform/command/test-fixtures/show-json/modules"},{"Key":"test","Source":"./foo","Dir":"/Users/kristin/go/src/github.com/hashicorp/terraform/command/test-fixtures/show-json/modules/foo"}]}

View File

@ -0,0 +1,193 @@
{
"format_version": "0.1",
"planned_values": {
"outputs": {
"test": {
"sensitive": false,
"value": "baz"
}
},
"root_module": {
"child_modules": [
{
"resources": [
{
"address": "module.test.test_instance.test[0]",
"mode": "managed",
"type": "test_instance",
"name": "test",
"index": 0,
"provider_name": "test",
"schema_version": 0,
"values": {
"ami": "baz"
}
},
{
"address": "module.test.test_instance.test[1]",
"mode": "managed",
"type": "test_instance",
"name": "test",
"index": 1,
"provider_name": "test",
"schema_version": 0,
"values": {
"ami": "baz"
}
},
{
"address": "module.test.test_instance.test[2]",
"mode": "managed",
"type": "test_instance",
"name": "test",
"index": 2,
"provider_name": "test",
"schema_version": 0,
"values": {
"ami": "baz"
}
}
],
"address": "module.test"
}
]
}
},
"resource_changes": [
{
"address": "module.test.test_instance.test[0]",
"module_address": "module.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"index": 0,
"deposed": true,
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"ami": "baz"
},
"after_unknown": {
"ami": false,
"id": true
}
}
},
{
"address": "module.test.test_instance.test[1]",
"module_address": "module.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"index": 1,
"deposed": true,
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"ami": "baz"
},
"after_unknown": {
"ami": false,
"id": true
}
}
},
{
"address": "module.test.test_instance.test[2]",
"module_address": "module.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"index": 2,
"deposed": true,
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"ami": "baz"
},
"after_unknown": {
"ami": false,
"id": true
}
}
}
],
"output_changes": {
"test": {
"actions": [
"create"
],
"before": null,
"after": "baz",
"after_unknown": false
}
},
"configuration": {
"root_module": {
"outputs": {
"test": {
"expression": {
"references": [
"module.test.test"
]
}
}
},
"module_calls": {
"test": {
"source": "./foo",
"expressions": {
"test_var": {
"constant_value": "baz"
}
},
"module": {
"outputs": {
"test": {
"expression": {
"references": [
"var.test_var"
]
}
}
},
"resources": [
{
"address": "test_instance.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_config_key": "provider.test",
"expressions": {
"ami": {
"references": [
"var.test_var"
]
}
},
"schema_version": 0,
"count_expression": {
"constant_value": 3
}
}
],
"variables": {
"test_var": {
"default": "bar"
}
}
}
}
}
}
}
}