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:
parent
5f8916b4fd
commit
f2f35265bc
|
@ -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!
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
{
|
||||
"format_version": "0.1",
|
||||
"variables": {
|
||||
"test_var": {
|
||||
"value": "bar"
|
||||
}
|
||||
},
|
||||
"planned_values": {
|
||||
"outputs": {
|
||||
"test": {
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
{
|
||||
"format_version": "0.1",
|
||||
"variables": {
|
||||
"test_var": {
|
||||
"value": "bar"
|
||||
}
|
||||
},
|
||||
"planned_values": {
|
||||
"outputs": {
|
||||
"test": {
|
||||
|
|
Loading…
Reference in New Issue