mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
command/json*: updating documentation and adding tests (#19944)
A few minor fixes and cleanups as a result of said tests. Hooray for eventual consistency!
This commit is contained in:
parent
e997373f44
commit
cdf7cc2449
@ -67,7 +67,7 @@ type change struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type output struct {
|
type output struct {
|
||||||
Sensitive bool `json:"sensitive,omitempty"`
|
Sensitive bool `json:"sensitive"`
|
||||||
Value json.RawMessage `json:"value,omitempty"`
|
Value json.RawMessage `json:"value,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,9 @@ type stateValues struct {
|
|||||||
type attributeValues map[string]interface{}
|
type attributeValues map[string]interface{}
|
||||||
|
|
||||||
func marshalAttributeValues(value cty.Value, schema *configschema.Block) attributeValues {
|
func marshalAttributeValues(value cty.Value, schema *configschema.Block) attributeValues {
|
||||||
|
if value == cty.NilVal {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
ret := make(attributeValues)
|
ret := make(attributeValues)
|
||||||
|
|
||||||
it := value.ElementIterator()
|
it := value.ElementIterator()
|
||||||
@ -118,9 +121,7 @@ func marshalPlannedValues(changes *plans.Changes, schemas *terraform.Schemas) (m
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// marshalPlannedValues returns two resource slices:
|
// marshalPlanResources
|
||||||
// The former has attribute values populated and the latter has true/false in
|
|
||||||
// place of values indicating whether the values are known at plan time.
|
|
||||||
func marshalPlanResources(changes *plans.Changes, ris []addrs.AbsResourceInstance, schemas *terraform.Schemas) ([]resource, error) {
|
func marshalPlanResources(changes *plans.Changes, ris []addrs.AbsResourceInstance, schemas *terraform.Schemas) ([]resource, error) {
|
||||||
var ret []resource
|
var ret []resource
|
||||||
|
|
||||||
|
313
command/jsonplan/values_test.go
Normal file
313
command/jsonplan/values_test.go
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
package jsonplan
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/addrs"
|
||||||
|
"github.com/hashicorp/terraform/configs/configschema"
|
||||||
|
"github.com/hashicorp/terraform/plans"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMarshalAttributeValues(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Attr cty.Value
|
||||||
|
Schema *configschema.Block
|
||||||
|
Want attributeValues
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
cty.NilVal,
|
||||||
|
&configschema.Block{
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"foo": {
|
||||||
|
Type: cty.String,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.StringVal("bar"),
|
||||||
|
}),
|
||||||
|
&configschema.Block{
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"foo": {
|
||||||
|
Type: cty.String,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attributeValues{"foo": cty.StringVal("bar")},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.NullVal(cty.String),
|
||||||
|
}),
|
||||||
|
&configschema.Block{
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"foo": {
|
||||||
|
Type: cty.String,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attributeValues{"foo": cty.NullVal(cty.String)},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.MapVal(map[string]cty.Value{
|
||||||
|
"hello": cty.StringVal("world"),
|
||||||
|
}),
|
||||||
|
"baz": cty.ListVal([]cty.Value{
|
||||||
|
cty.StringVal("goodnight"),
|
||||||
|
cty.StringVal("moon"),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
&configschema.Block{
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"bar": {
|
||||||
|
Type: cty.Map(cty.String),
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"baz": {
|
||||||
|
Type: cty.List(cty.String),
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attributeValues{
|
||||||
|
"bar": cty.MapVal(map[string]cty.Value{
|
||||||
|
"hello": cty.StringVal("world"),
|
||||||
|
}),
|
||||||
|
"baz": cty.ListVal([]cty.Value{
|
||||||
|
cty.StringVal("goodnight"),
|
||||||
|
cty.StringVal("moon"),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
got := marshalAttributeValues(test.Attr, test.Schema)
|
||||||
|
eq := reflect.DeepEqual(got, test.Want)
|
||||||
|
if !eq {
|
||||||
|
t.Fatalf("wrong result:\nGot: %v\nWant: %#v\n", got, test.Want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalPlannedOutputs(t *testing.T) {
|
||||||
|
after, _ := plans.NewDynamicValue(cty.StringVal("after"), cty.DynamicPseudoType)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
Changes *plans.Changes
|
||||||
|
Want map[string]output
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
&plans.Changes{},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&plans.Changes{
|
||||||
|
Outputs: []*plans.OutputChangeSrc{
|
||||||
|
{
|
||||||
|
Addr: addrs.OutputValue{Name: "bar"}.Absolute(addrs.RootModuleInstance),
|
||||||
|
ChangeSrc: plans.ChangeSrc{
|
||||||
|
Action: plans.Create,
|
||||||
|
After: after,
|
||||||
|
},
|
||||||
|
Sensitive: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
map[string]output{
|
||||||
|
"bar": {
|
||||||
|
Sensitive: false,
|
||||||
|
Value: json.RawMessage(`"after"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // Delete action
|
||||||
|
&plans.Changes{
|
||||||
|
Outputs: []*plans.OutputChangeSrc{
|
||||||
|
{
|
||||||
|
Addr: addrs.OutputValue{Name: "bar"}.Absolute(addrs.RootModuleInstance),
|
||||||
|
ChangeSrc: plans.ChangeSrc{
|
||||||
|
Action: plans.Delete,
|
||||||
|
},
|
||||||
|
Sensitive: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
map[string]output{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
got, err := marshalPlannedOutputs(test.Changes)
|
||||||
|
if test.Err {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("succeeded; want error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
eq := reflect.DeepEqual(got, test.Want)
|
||||||
|
if !eq {
|
||||||
|
t.Fatalf("wrong result:\nGot: %#v\nWant: %#v\n", got, test.Want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalPlanResources(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Action plans.Action
|
||||||
|
Before cty.Value
|
||||||
|
After cty.Value
|
||||||
|
Want []resource
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Action: plans.Create,
|
||||||
|
Before: cty.NullVal(cty.EmptyObject),
|
||||||
|
After: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"woozles": cty.UnknownVal(cty.String),
|
||||||
|
"foozles": cty.UnknownVal(cty.String),
|
||||||
|
}),
|
||||||
|
Want: []resource{resource{
|
||||||
|
Address: "test_thing.example",
|
||||||
|
Mode: "managed",
|
||||||
|
Type: "test_thing",
|
||||||
|
Name: "example",
|
||||||
|
Index: addrs.InstanceKey(nil),
|
||||||
|
ProviderName: "test",
|
||||||
|
SchemaVersion: 1,
|
||||||
|
AttributeValues: attributeValues(nil),
|
||||||
|
}},
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: plans.Delete,
|
||||||
|
Before: cty.NullVal(cty.EmptyObject),
|
||||||
|
After: cty.NilVal,
|
||||||
|
Want: nil,
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: plans.Update,
|
||||||
|
Before: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"woozles": cty.StringVal("foo"),
|
||||||
|
"foozles": cty.StringVal("bar"),
|
||||||
|
}),
|
||||||
|
After: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"woozles": cty.StringVal("baz"),
|
||||||
|
"foozles": cty.StringVal("bat"),
|
||||||
|
}),
|
||||||
|
Want: []resource{resource{
|
||||||
|
Address: "test_thing.example",
|
||||||
|
Mode: "managed",
|
||||||
|
Type: "test_thing",
|
||||||
|
Name: "example",
|
||||||
|
Index: addrs.InstanceKey(nil),
|
||||||
|
ProviderName: "test",
|
||||||
|
SchemaVersion: 1,
|
||||||
|
AttributeValues: attributeValues{
|
||||||
|
"woozles": cty.StringVal("baz"),
|
||||||
|
"foozles": cty.StringVal("bat"),
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
Err: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
before, err := plans.NewDynamicValue(test.Before, test.Before.Type())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
after, err := plans.NewDynamicValue(test.After, test.After.Type())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
testChange := &plans.Changes{
|
||||||
|
Resources: []*plans.ResourceInstanceChangeSrc{
|
||||||
|
{
|
||||||
|
Addr: addrs.Resource{
|
||||||
|
Mode: addrs.ManagedResourceMode,
|
||||||
|
Type: "test_thing",
|
||||||
|
Name: "example",
|
||||||
|
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||||
|
ProviderAddr: addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance),
|
||||||
|
ChangeSrc: plans.ChangeSrc{
|
||||||
|
Action: test.Action,
|
||||||
|
Before: before,
|
||||||
|
After: after,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ris := testResourceAddrs()
|
||||||
|
|
||||||
|
got, err := marshalPlanResources(testChange, ris, testSchemas())
|
||||||
|
if test.Err {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("succeeded; want error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
eq := reflect.DeepEqual(got, test.Want)
|
||||||
|
if !eq {
|
||||||
|
t.Fatalf("wrong result:\nGot: %#v\nWant: %#v\n", got, test.Want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSchemas() *terraform.Schemas {
|
||||||
|
return &terraform.Schemas{
|
||||||
|
Providers: map[string]*terraform.ProviderSchema{
|
||||||
|
"test": &terraform.ProviderSchema{
|
||||||
|
ResourceTypes: map[string]*configschema.Block{
|
||||||
|
"test_thing": {
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"woozles": {Type: cty.String, Optional: true, Computed: true},
|
||||||
|
"foozles": {Type: cty.String, Optional: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ResourceTypeSchemaVersions: map[string]uint64{
|
||||||
|
"test_thing": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testResourceAddrs() []addrs.AbsResourceInstance {
|
||||||
|
return []addrs.AbsResourceInstance{
|
||||||
|
mustAddr("test_thing.example"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustAddr(str string) addrs.AbsResourceInstance {
|
||||||
|
addr, diags := addrs.ParseAbsResourceInstanceStr(str)
|
||||||
|
if diags.HasErrors() {
|
||||||
|
panic(diags.Err())
|
||||||
|
}
|
||||||
|
return addr
|
||||||
|
}
|
@ -33,7 +33,7 @@ type stateValues struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type output struct {
|
type output struct {
|
||||||
Sensitive bool `json:"sensitive,omitempty"`
|
Sensitive bool `json:"sensitive"`
|
||||||
Value json.RawMessage `json:"value,omitempty"`
|
Value json.RawMessage `json:"value,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +86,9 @@ type resource struct {
|
|||||||
type attributeValues map[string]interface{}
|
type attributeValues map[string]interface{}
|
||||||
|
|
||||||
func marshalAttributeValues(value cty.Value, schema *configschema.Block) attributeValues {
|
func marshalAttributeValues(value cty.Value, schema *configschema.Block) attributeValues {
|
||||||
|
if value == cty.NilVal {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
ret := make(attributeValues)
|
ret := make(attributeValues)
|
||||||
|
|
||||||
it := value.ElementIterator()
|
it := value.ElementIterator()
|
||||||
@ -229,7 +232,7 @@ func marshalResources(resources map[string]*states.Resource, schemas *terraform.
|
|||||||
Address: r.Addr.String(),
|
Address: r.Addr.String(),
|
||||||
Type: r.Addr.Type,
|
Type: r.Addr.Type,
|
||||||
Name: r.Addr.Name,
|
Name: r.Addr.Name,
|
||||||
ProviderName: r.ProviderConfig.ProviderConfig.String(),
|
ProviderName: r.ProviderConfig.ProviderConfig.StringCompact(),
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.Addr.Mode {
|
switch r.Addr.Mode {
|
||||||
|
253
command/jsonstate/state_test.go
Normal file
253
command/jsonstate/state_test.go
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
package jsonstate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/addrs"
|
||||||
|
"github.com/hashicorp/terraform/configs/configschema"
|
||||||
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMarshalOutputs(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Outputs map[string]*states.OutputValue
|
||||||
|
Want map[string]output
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
map[string]*states.OutputValue{
|
||||||
|
"test": {
|
||||||
|
Sensitive: true,
|
||||||
|
Value: cty.StringVal("sekret"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
map[string]output{
|
||||||
|
"test": {
|
||||||
|
Sensitive: true,
|
||||||
|
Value: json.RawMessage(`"sekret"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
map[string]*states.OutputValue{
|
||||||
|
"test": {
|
||||||
|
Sensitive: false,
|
||||||
|
Value: cty.StringVal("not_so_sekret"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
map[string]output{
|
||||||
|
"test": {
|
||||||
|
Sensitive: false,
|
||||||
|
Value: json.RawMessage(`"not_so_sekret"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
got, err := marshalOutputs(test.Outputs)
|
||||||
|
if test.Err {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("succeeded; want error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
eq := reflect.DeepEqual(got, test.Want)
|
||||||
|
if !eq {
|
||||||
|
// printing the output isn't terribly useful, but it does help indicate which test case failed
|
||||||
|
t.Fatalf("wrong result:\nGot: %#v\nWant: %#v\n", got, test.Want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalAttributeValues(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Attr cty.Value
|
||||||
|
Schema *configschema.Block
|
||||||
|
Want attributeValues
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
cty.NilVal,
|
||||||
|
&configschema.Block{
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"foo": {
|
||||||
|
Type: cty.String,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.StringVal("bar"),
|
||||||
|
}),
|
||||||
|
&configschema.Block{
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"foo": {
|
||||||
|
Type: cty.String,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attributeValues{"foo": cty.StringVal("bar")},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.NullVal(cty.String),
|
||||||
|
}),
|
||||||
|
&configschema.Block{
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"foo": {
|
||||||
|
Type: cty.String,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attributeValues{"foo": cty.NullVal(cty.String)},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.MapVal(map[string]cty.Value{
|
||||||
|
"hello": cty.StringVal("world"),
|
||||||
|
}),
|
||||||
|
"baz": cty.ListVal([]cty.Value{
|
||||||
|
cty.StringVal("goodnight"),
|
||||||
|
cty.StringVal("moon"),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
&configschema.Block{
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"bar": {
|
||||||
|
Type: cty.Map(cty.String),
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"baz": {
|
||||||
|
Type: cty.List(cty.String),
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attributeValues{
|
||||||
|
"bar": cty.MapVal(map[string]cty.Value{
|
||||||
|
"hello": cty.StringVal("world"),
|
||||||
|
}),
|
||||||
|
"baz": cty.ListVal([]cty.Value{
|
||||||
|
cty.StringVal("goodnight"),
|
||||||
|
cty.StringVal("moon"),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
got := marshalAttributeValues(test.Attr, test.Schema)
|
||||||
|
eq := reflect.DeepEqual(got, test.Want)
|
||||||
|
if !eq {
|
||||||
|
t.Fatalf("wrong result:\nGot: %v\nWant: %#v\n", got, test.Want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalResources(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Resources map[string]*states.Resource
|
||||||
|
Schemas *terraform.Schemas
|
||||||
|
Want []resource
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
map[string]*states.Resource{
|
||||||
|
"test_thing.baz": {
|
||||||
|
Addr: addrs.Resource{
|
||||||
|
Mode: addrs.ManagedResourceMode,
|
||||||
|
Type: "test_thing",
|
||||||
|
Name: "bar",
|
||||||
|
},
|
||||||
|
EachMode: states.EachList,
|
||||||
|
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
|
||||||
|
addrs.IntKey(0): {
|
||||||
|
Current: &states.ResourceInstanceObjectSrc{
|
||||||
|
SchemaVersion: 1,
|
||||||
|
Status: states.ObjectReady,
|
||||||
|
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ProviderConfig: addrs.ProviderConfig{
|
||||||
|
Type: "test",
|
||||||
|
}.Absolute(addrs.RootModuleInstance),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
testSchemas(),
|
||||||
|
[]resource{
|
||||||
|
resource{
|
||||||
|
Address: "test_thing.bar",
|
||||||
|
Mode: "managed",
|
||||||
|
Type: "test_thing",
|
||||||
|
Name: "bar",
|
||||||
|
Index: addrs.IntKey(0),
|
||||||
|
ProviderName: "test",
|
||||||
|
SchemaVersion: 1,
|
||||||
|
AttributeValues: attributeValues{
|
||||||
|
"foozles": cty.NullVal(cty.String),
|
||||||
|
"woozles": cty.StringVal("confuzles"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
got, err := marshalResources(test.Resources, test.Schemas)
|
||||||
|
if test.Err {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("succeeded; want error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
eq := reflect.DeepEqual(got, test.Want)
|
||||||
|
if !eq {
|
||||||
|
t.Fatalf("wrong result:\nGot: %#v\nWant: %#v\n", got, test.Want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSchemas() *terraform.Schemas {
|
||||||
|
return &terraform.Schemas{
|
||||||
|
Providers: map[string]*terraform.ProviderSchema{
|
||||||
|
"test": &terraform.ProviderSchema{
|
||||||
|
ResourceTypes: map[string]*configschema.Block{
|
||||||
|
"test_thing": {
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"woozles": {Type: cty.String, Optional: true, Computed: true},
|
||||||
|
"foozles": {Type: cty.String, Optional: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,15 @@ from a state or plan file. This can be used to inspect a plan to ensure
|
|||||||
that the planned operations are expected, or to inspect the current state
|
that the planned operations are expected, or to inspect the current state
|
||||||
as Terraform sees it.
|
as Terraform sees it.
|
||||||
|
|
||||||
|
Machine-readable output is generated by adding the `-json` command-line
|
||||||
|
flag. This is only available when using `show` with a path to a Terraform
|
||||||
|
plan file.
|
||||||
|
|
||||||
|
**NOTE**
|
||||||
|
When using the `-json` command-line flag, any sensitive values in
|
||||||
|
terraform state will be displayed in plain text. For more information, see
|
||||||
|
[_Sensitive Data in State_](/docs/state/sensitive-data.html).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Usage: `terraform show [options] [path]`
|
Usage: `terraform show [options] [path]`
|
||||||
@ -24,3 +33,4 @@ The command-line flags are all optional. The list of available flags are:
|
|||||||
|
|
||||||
* `-no-color` - Disables output with coloring
|
* `-no-color` - Disables output with coloring
|
||||||
|
|
||||||
|
* `-json` - Displays machine-readable output from a plan file
|
||||||
|
Loading…
Reference in New Issue
Block a user