Merge pull request #19995 from hashicorp/f-cmd-fmt-reduce-diff
command/format: Reduce whitespaces in empty fields
This commit is contained in:
commit
cb39836705
|
@ -100,7 +100,7 @@ func ResourceChange(
|
|||
buf.WriteString(addr.String())
|
||||
}
|
||||
|
||||
buf.WriteString(" {\n")
|
||||
buf.WriteString(" {")
|
||||
|
||||
p := blockBodyDiffPrinter{
|
||||
buf: &buf,
|
||||
|
@ -122,9 +122,12 @@ func ResourceChange(
|
|||
panic(fmt.Sprintf("failed to decode plan for %s while rendering diff: %s", addr, err))
|
||||
}
|
||||
|
||||
p.writeBlockBodyDiff(schema, changeV.Before, changeV.After, 6, path)
|
||||
|
||||
buf.WriteString(" }\n")
|
||||
bodyWritten := p.writeBlockBodyDiff(schema, changeV.Before, changeV.After, 6, path)
|
||||
if bodyWritten {
|
||||
buf.WriteString("\n")
|
||||
buf.WriteString(strings.Repeat(" ", 4))
|
||||
}
|
||||
buf.WriteString("}\n")
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
@ -143,9 +146,12 @@ type blockBodyDiffPrinter struct {
|
|||
|
||||
const forcesNewResourceCaption = " [red]# forces replacement[reset]"
|
||||
|
||||
func (p *blockBodyDiffPrinter) writeBlockBodyDiff(schema *configschema.Block, old, new cty.Value, indent int, path cty.Path) {
|
||||
// writeBlockBodyDiff writes attribute or block differences
|
||||
// and returns true if any differences were found and written
|
||||
func (p *blockBodyDiffPrinter) writeBlockBodyDiff(schema *configschema.Block, old, new cty.Value, indent int, path cty.Path) bool {
|
||||
path = ctyEnsurePathCapacity(path, 1)
|
||||
|
||||
bodyWritten := false
|
||||
blankBeforeBlocks := false
|
||||
{
|
||||
attrNames := make([]string, 0, len(schema.Attributes))
|
||||
|
@ -176,6 +182,7 @@ func (p *blockBodyDiffPrinter) writeBlockBodyDiff(schema *configschema.Block, ol
|
|||
oldVal := ctyGetAttrMaybeNull(old, name)
|
||||
newVal := ctyGetAttrMaybeNull(new, name)
|
||||
|
||||
bodyWritten = true
|
||||
p.writeAttrDiff(name, attrS, oldVal, newVal, attrNameLen, indent, path)
|
||||
}
|
||||
}
|
||||
|
@ -192,16 +199,20 @@ func (p *blockBodyDiffPrinter) writeBlockBodyDiff(schema *configschema.Block, ol
|
|||
oldVal := ctyGetAttrMaybeNull(old, name)
|
||||
newVal := ctyGetAttrMaybeNull(new, name)
|
||||
|
||||
bodyWritten = true
|
||||
p.writeNestedBlockDiffs(name, blockS, oldVal, newVal, blankBeforeBlocks, indent, path)
|
||||
|
||||
// Always include a blank for any subsequent block types.
|
||||
blankBeforeBlocks = true
|
||||
}
|
||||
}
|
||||
|
||||
return bodyWritten
|
||||
}
|
||||
|
||||
func (p *blockBodyDiffPrinter) writeAttrDiff(name string, attrS *configschema.Attribute, old, new cty.Value, nameLen, indent int, path cty.Path) {
|
||||
path = append(path, cty.GetAttrStep{Name: name})
|
||||
p.buf.WriteString("\n")
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
showJustNew := false
|
||||
var action plans.Action
|
||||
|
@ -239,9 +250,6 @@ func (p *blockBodyDiffPrinter) writeAttrDiff(name string, attrS *configschema.At
|
|||
p.writeValueDiff(old, new, indent+2, path)
|
||||
}
|
||||
}
|
||||
|
||||
p.buf.WriteString("\n")
|
||||
|
||||
}
|
||||
|
||||
func (p *blockBodyDiffPrinter) writeNestedBlockDiffs(name string, blockS *configschema.NestedBlock, old, new cty.Value, blankBefore bool, indent int, path cty.Path) {
|
||||
|
@ -393,6 +401,7 @@ func (p *blockBodyDiffPrinter) writeNestedBlockDiffs(name string, blockS *config
|
|||
}
|
||||
|
||||
func (p *blockBodyDiffPrinter) writeNestedBlockDiff(name string, label *string, blockS *configschema.Block, action plans.Action, old, new cty.Value, indent int, path cty.Path) {
|
||||
p.buf.WriteString("\n")
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
p.writeActionSymbol(action)
|
||||
|
||||
|
@ -406,12 +415,12 @@ func (p *blockBodyDiffPrinter) writeNestedBlockDiff(name string, label *string,
|
|||
p.buf.WriteString(p.color.Color(forcesNewResourceCaption))
|
||||
}
|
||||
|
||||
p.buf.WriteString("\n")
|
||||
|
||||
p.writeBlockBodyDiff(blockS, old, new, indent+4, path)
|
||||
|
||||
p.buf.WriteString(strings.Repeat(" ", indent+2))
|
||||
p.buf.WriteString("}\n")
|
||||
bodyWritten := p.writeBlockBodyDiff(blockS, old, new, indent+4, path)
|
||||
if bodyWritten {
|
||||
p.buf.WriteString("\n")
|
||||
p.buf.WriteString(strings.Repeat(" ", indent+2))
|
||||
}
|
||||
p.buf.WriteString("}")
|
||||
}
|
||||
|
||||
func (p *blockBodyDiffPrinter) writeValue(val cty.Value, action plans.Action, indent int) {
|
||||
|
@ -438,11 +447,15 @@ func (p *blockBodyDiffPrinter) writeValue(val cty.Value, action plans.Action, in
|
|||
jv, err := ctyjson.Unmarshal(src, ty)
|
||||
if err == nil {
|
||||
p.buf.WriteString("jsonencode(")
|
||||
p.buf.WriteByte('\n')
|
||||
p.buf.WriteString(strings.Repeat(" ", indent+4))
|
||||
p.writeValue(jv, action, indent+4)
|
||||
p.buf.WriteByte('\n')
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
if jv.LengthInt() == 0 {
|
||||
p.writeValue(jv, action, 0)
|
||||
} else {
|
||||
p.buf.WriteByte('\n')
|
||||
p.buf.WriteString(strings.Repeat(" ", indent+4))
|
||||
p.writeValue(jv, action, indent+4)
|
||||
p.buf.WriteByte('\n')
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
}
|
||||
p.buf.WriteByte(')')
|
||||
break // don't *also* do the normal behavior below
|
||||
}
|
||||
|
@ -463,21 +476,26 @@ func (p *blockBodyDiffPrinter) writeValue(val cty.Value, action plans.Action, in
|
|||
fmt.Fprintf(p.buf, "%#v", val)
|
||||
}
|
||||
case ty.IsListType() || ty.IsSetType() || ty.IsTupleType():
|
||||
p.buf.WriteString("[\n")
|
||||
p.buf.WriteString("[")
|
||||
|
||||
it := val.ElementIterator()
|
||||
for it.Next() {
|
||||
_, val := it.Element()
|
||||
|
||||
p.buf.WriteString("\n")
|
||||
p.buf.WriteString(strings.Repeat(" ", indent+2))
|
||||
p.writeActionSymbol(action)
|
||||
p.writeValue(val, action, indent+4)
|
||||
p.buf.WriteString(",\n")
|
||||
p.buf.WriteString(",")
|
||||
}
|
||||
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
if val.LengthInt() > 0 {
|
||||
p.buf.WriteString("\n")
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
}
|
||||
p.buf.WriteString("]")
|
||||
case ty.IsMapType():
|
||||
p.buf.WriteString("{\n")
|
||||
p.buf.WriteString("{")
|
||||
|
||||
keyLen := 0
|
||||
for it := val.ElementIterator(); it.Next(); {
|
||||
|
@ -489,19 +507,23 @@ func (p *blockBodyDiffPrinter) writeValue(val cty.Value, action plans.Action, in
|
|||
|
||||
for it := val.ElementIterator(); it.Next(); {
|
||||
key, val := it.Element()
|
||||
|
||||
p.buf.WriteString("\n")
|
||||
p.buf.WriteString(strings.Repeat(" ", indent+2))
|
||||
p.writeActionSymbol(action)
|
||||
p.writeValue(key, action, indent+4)
|
||||
p.buf.WriteString(strings.Repeat(" ", keyLen-len(key.AsString())))
|
||||
p.buf.WriteString(" = ")
|
||||
p.writeValue(val, action, indent+4)
|
||||
p.buf.WriteString("\n")
|
||||
}
|
||||
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
if val.LengthInt() > 0 {
|
||||
p.buf.WriteString("\n")
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
}
|
||||
p.buf.WriteString("}")
|
||||
case ty.IsObjectType():
|
||||
p.buf.WriteString("{\n")
|
||||
p.buf.WriteString("{")
|
||||
|
||||
atys := ty.AttributeTypes()
|
||||
attrNames := make([]string, 0, len(atys))
|
||||
|
@ -516,16 +538,20 @@ func (p *blockBodyDiffPrinter) writeValue(val cty.Value, action plans.Action, in
|
|||
|
||||
for _, attrName := range attrNames {
|
||||
val := val.GetAttr(attrName)
|
||||
|
||||
p.buf.WriteString("\n")
|
||||
p.buf.WriteString(strings.Repeat(" ", indent+2))
|
||||
p.writeActionSymbol(action)
|
||||
p.buf.WriteString(attrName)
|
||||
p.buf.WriteString(strings.Repeat(" ", nameLen-len(attrName)))
|
||||
p.buf.WriteString(" = ")
|
||||
p.writeValue(val, action, indent+4)
|
||||
p.buf.WriteString("\n")
|
||||
}
|
||||
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
if len(attrNames) > 0 {
|
||||
p.buf.WriteString("\n")
|
||||
p.buf.WriteString(strings.Repeat(" ", indent))
|
||||
}
|
||||
p.buf.WriteString("}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -414,6 +414,28 @@ func TestResourceChange_JSON(t *testing.T) {
|
|||
}
|
||||
)
|
||||
}
|
||||
`,
|
||||
},
|
||||
"creation (empty)": {
|
||||
Action: plans.Create,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.NullVal(cty.EmptyObject),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"json_field": cty.StringVal(`{}`),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"json_field": {Type: cty.String, Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be created
|
||||
+ resource "test_instance" "example" {
|
||||
+ id = (known after apply)
|
||||
+ json_field = jsonencode({})
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
@ -423,6 +445,39 @@ func TestResourceChange_JSON(t *testing.T) {
|
|||
func TestResourceChange_primitiveList(t *testing.T) {
|
||||
testCases := map[string]testCase{
|
||||
"in-place update - creation": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"list_field": cty.NullVal(cty.List(cty.String)),
|
||||
}),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"list_field": cty.ListVal([]cty.Value{
|
||||
cty.StringVal("new-element"),
|
||||
}),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"list_field": {Type: cty.List(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be updated in-place
|
||||
~ resource "test_instance" "example" {
|
||||
ami = "ami-STATIC"
|
||||
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
||||
+ list_field = [
|
||||
+ "new-element",
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
"in-place update - first addition": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
|
@ -574,6 +629,97 @@ func TestResourceChange_primitiveList(t *testing.T) {
|
|||
- "cccc",
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
"creation - empty list": {
|
||||
Action: plans.Create,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.NullVal(cty.EmptyObject),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"list_field": cty.ListValEmpty(cty.String),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"list_field": {Type: cty.List(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be created
|
||||
+ resource "test_instance" "example" {
|
||||
+ ami = "ami-STATIC"
|
||||
+ id = (known after apply)
|
||||
+ list_field = []
|
||||
}
|
||||
`,
|
||||
},
|
||||
"in-place update - full to empty": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"list_field": cty.ListVal([]cty.Value{
|
||||
cty.StringVal("aaaa"),
|
||||
cty.StringVal("bbbb"),
|
||||
cty.StringVal("cccc"),
|
||||
}),
|
||||
}),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"list_field": cty.ListValEmpty(cty.String),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"list_field": {Type: cty.List(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be updated in-place
|
||||
~ resource "test_instance" "example" {
|
||||
ami = "ami-STATIC"
|
||||
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
||||
~ list_field = [
|
||||
- "aaaa",
|
||||
- "bbbb",
|
||||
- "cccc",
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
"in-place update - null to empty": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"list_field": cty.NullVal(cty.List(cty.String)),
|
||||
}),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"list_field": cty.ListValEmpty(cty.String),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"list_field": {Type: cty.List(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be updated in-place
|
||||
~ resource "test_instance" "example" {
|
||||
ami = "ami-STATIC"
|
||||
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
||||
+ list_field = []
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
@ -583,6 +729,39 @@ func TestResourceChange_primitiveList(t *testing.T) {
|
|||
func TestResourceChange_primitiveSet(t *testing.T) {
|
||||
testCases := map[string]testCase{
|
||||
"in-place update - creation": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"set_field": cty.NullVal(cty.Set(cty.String)),
|
||||
}),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"set_field": cty.SetVal([]cty.Value{
|
||||
cty.StringVal("new-element"),
|
||||
}),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"set_field": {Type: cty.Set(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be updated in-place
|
||||
~ resource "test_instance" "example" {
|
||||
ami = "ami-STATIC"
|
||||
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
||||
+ set_field = [
|
||||
+ "new-element",
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
"in-place update - first insertion": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
|
@ -734,6 +913,95 @@ func TestResourceChange_primitiveSet(t *testing.T) {
|
|||
- "cccc",
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
"creation - empty set": {
|
||||
Action: plans.Create,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.NullVal(cty.EmptyObject),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"set_field": cty.SetValEmpty(cty.String),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"set_field": {Type: cty.Set(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be created
|
||||
+ resource "test_instance" "example" {
|
||||
+ ami = "ami-STATIC"
|
||||
+ id = (known after apply)
|
||||
+ set_field = []
|
||||
}
|
||||
`,
|
||||
},
|
||||
"in-place update - full to empty set": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"set_field": cty.SetVal([]cty.Value{
|
||||
cty.StringVal("aaaa"),
|
||||
cty.StringVal("bbbb"),
|
||||
}),
|
||||
}),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"set_field": cty.SetValEmpty(cty.String),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"set_field": {Type: cty.Set(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be updated in-place
|
||||
~ resource "test_instance" "example" {
|
||||
ami = "ami-STATIC"
|
||||
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
||||
~ set_field = [
|
||||
- "aaaa",
|
||||
- "bbbb",
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
"in-place update - null to empty set": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"set_field": cty.NullVal(cty.Set(cty.String)),
|
||||
}),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"set_field": cty.SetValEmpty(cty.String),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"set_field": {Type: cty.Set(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be updated in-place
|
||||
~ resource "test_instance" "example" {
|
||||
ami = "ami-STATIC"
|
||||
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
||||
+ set_field = []
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
@ -743,6 +1011,39 @@ func TestResourceChange_primitiveSet(t *testing.T) {
|
|||
func TestResourceChange_map(t *testing.T) {
|
||||
testCases := map[string]testCase{
|
||||
"in-place update - creation": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"map_field": cty.NullVal(cty.Map(cty.String)),
|
||||
}),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"map_field": cty.MapVal(map[string]cty.Value{
|
||||
"new-key": cty.StringVal("new-element"),
|
||||
}),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"map_field": {Type: cty.Map(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be updated in-place
|
||||
~ resource "test_instance" "example" {
|
||||
ami = "ami-STATIC"
|
||||
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
||||
+ map_field = {
|
||||
+ "new-key" = "new-element"
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
"in-place update - first insertion": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
|
@ -894,6 +1195,31 @@ func TestResourceChange_map(t *testing.T) {
|
|||
- "c" = "cccc" -> null
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
"creation - empty": {
|
||||
Action: plans.Create,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.NullVal(cty.EmptyObject),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.UnknownVal(cty.String),
|
||||
"ami": cty.StringVal("ami-STATIC"),
|
||||
"map_field": cty.MapValEmpty(cty.String),
|
||||
}),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"map_field": {Type: cty.Map(cty.String), Optional: true},
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
ExpectedOutput: ` # test_instance.example will be created
|
||||
+ resource "test_instance" "example" {
|
||||
+ ami = "ami-STATIC"
|
||||
+ id = (known after apply)
|
||||
+ map_field = {}
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
@ -956,6 +1282,53 @@ func TestResourceChange_nestedList(t *testing.T) {
|
|||
`,
|
||||
},
|
||||
"in-place update - creation": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-BEFORE"),
|
||||
"root_block_device": cty.ListValEmpty(cty.EmptyObject),
|
||||
}),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-AFTER"),
|
||||
"root_block_device": cty.ListVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"volume_type": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
},
|
||||
BlockTypes: map[string]*configschema.NestedBlock{
|
||||
"root_block_device": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"volume_type": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingList,
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: ` # test_instance.example will be updated in-place
|
||||
~ resource "test_instance" "example" {
|
||||
~ ami = "ami-BEFORE" -> "ami-AFTER"
|
||||
id = "i-02ae66f368e8518a9"
|
||||
|
||||
+ root_block_device {}
|
||||
}
|
||||
`,
|
||||
},
|
||||
"in-place update - first insertion": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
|
|
Loading…
Reference in New Issue