command/show: json output enhancements (#20291)

* command/jsonplan: 
- add variables to plan output
- print known planned values for resources

Previously, resource attribute values were only displayed if the values
were wholly known. Now we will filter the unknown values out of the
change and print the known values.

* command/jsonstate: added depends_on and tainted fields
* command/show: update tests to reflect added fields
This commit is contained in:
Kristin Laemmert 2019-02-11 13:17:03 -08:00 committed by GitHub
parent 5f8916b4fd
commit f2f35265bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 5 deletions

View File

@ -29,6 +29,7 @@ const FormatVersion = "0.1"
type plan struct {
FormatVersion string `json:"format_version,omitempty"`
TerraformVersion string `json:"terraform_version,omitempty"`
Variables variables `json:"variables,omitempty"`
PlannedValues stateValues `json:"planned_values,omitempty"`
// ResourceChanges are sorted in a user-friendly order that is undefined at
// this time, but consistent.
@ -76,6 +77,14 @@ type output struct {
Value json.RawMessage `json:"value,omitempty"`
}
// variables is the JSON representation of the variables provided to the current
// plan.
type variables map[string]*variable
type variable struct {
Value json.RawMessage `json:"value,omitempty"`
}
// Marshal returns the json encoding of a terraform plan.
func Marshal(
config *configs.Config,
@ -87,8 +96,13 @@ func Marshal(
output := newPlan()
output.TerraformVersion = version.String()
err := output.marshalPlanVariables(p.VariableValues, schemas)
if err != nil {
return nil, fmt.Errorf("error in marshalPlanVariables: %s", err)
}
// output.PlannedValues
err := output.marshalPlannedValues(p.Changes, schemas)
err = output.marshalPlannedValues(p.Changes, schemas)
if err != nil {
return nil, fmt.Errorf("error in marshalPlannedValues: %s", err)
}
@ -122,6 +136,29 @@ func Marshal(
return ret, err
}
func (p *plan) marshalPlanVariables(vars map[string]plans.DynamicValue, schemas *terraform.Schemas) error {
if len(vars) == 0 {
return nil
}
p.Variables = make(variables, len(vars))
for k, v := range vars {
val, err := v.Decode(cty.DynamicPseudoType)
if err != nil {
return err
}
valJSON, err := ctyjson.Marshal(val, val.Type())
if err != nil {
return err
}
p.Variables[k] = &variable{
Value: valJSON,
}
}
return nil
}
func (p *plan) marshalResourceChanges(changes *plans.Changes, schemas *terraform.Schemas) error {
if changes == nil {
// Nothing to do!

View File

@ -166,6 +166,9 @@ func marshalPlanResources(changes *plans.Changes, ris []addrs.AbsResourceInstanc
if changeV.After != cty.NilVal {
if changeV.After.IsWhollyKnown() {
resource.AttributeValues = marshalAttributeValues(changeV.After, schema)
} else {
knowns := omitUnknowns(changeV.After)
resource.AttributeValues = marshalAttributeValues(knowns, schema)
}
}

View File

@ -84,6 +84,13 @@ type resource struct {
// unknown values are omitted or set to null, making them indistinguishable
// from absent values.
AttributeValues attributeValues `json:"values,omitempty"`
// DependsOn contains a list of the resource's dependencies. The entries are
// addresses relative to the containing module.
DependsOn []string `json:"depends_on,omitempty"`
// Tainted is true if the resource is tainted in terraform state.
Tainted bool `json:"tainted,omitempty"`
}
// attributeValues is the JSON representation of the attribute values of the
@ -276,6 +283,18 @@ func marshalResources(resources map[string]*states.Resource, schemas *terraform.
resource.AttributeValues = marshalAttributeValues(riObj.Value, schema)
if len(riObj.Dependencies) > 0 {
dependencies := make([]string, len(riObj.Dependencies))
for i, v := range riObj.Dependencies {
dependencies[i] = v.String()
}
resource.DependsOn = dependencies
}
if riObj.Status == states.ObjectTainted {
resource.Tainted = true
}
ret = append(ret, resource)
}

View File

@ -312,9 +312,12 @@ func showFixturePlanFile(t *testing.T) string {
}
// this simplified plan struct allows us to preserve field order when marshaling
// the command output.
// the command output. NOTE: we are leaving "terraform_version" out of this test
// to avoid needing to constantly update the expected output; as a potential
// TODO we could write a jsonplan compare function.
type plan struct {
FormatVersion string `json:"format_version,omitempty"`
Variables map[string]interface{} `json:"variables,omitempty"`
PlannedValues map[string]interface{} `json:"planned_values,omitempty"`
ResourceChanges []interface{} `json:"resource_changes,omitempty"`
OutputChanges map[string]interface{} `json:"output_changes,omitempty"`

View File

@ -1,5 +1,10 @@
{
"format_version": "0.1",
"variables": {
"test_var": {
"value": "bar"
}
},
"planned_values": {
"outputs": {
"test": {
@ -16,7 +21,10 @@
"type": "test_instance",
"name": "test",
"provider_name": "test",
"schema_version": 0
"schema_version": 0,
"values": {
"ami": "bar"
}
},
{
"address": "test_instance.test[1]",
@ -25,7 +33,10 @@
"type": "test_instance",
"name": "test",
"provider_name": "test",
"schema_version": 0
"schema_version": 0,
"values": {
"ami": "bar"
}
},
{
"address": "test_instance.test[2]",
@ -34,7 +45,10 @@
"type": "test_instance",
"name": "test",
"provider_name": "test",
"schema_version": 0
"schema_version": 0,
"values": {
"ami": "bar"
}
}
]
}

View File

@ -1,5 +1,10 @@
{
"format_version": "0.1",
"variables": {
"test_var": {
"value": "bar"
}
},
"planned_values": {
"outputs": {
"test": {

View File

@ -1,5 +1,10 @@
{
"format_version": "0.1",
"variables": {
"test_var": {
"value": "bar"
}
},
"planned_values": {
"outputs": {
"test": {