Merge pull request #20067 from hashicorp/b-cmd-fmt-unknown-set

command/format: Fix rendering of unknown elements in set/map/list
This commit is contained in:
Radek Simko 2019-01-22 16:09:44 +00:00 committed by GitHub
commit 7e0be7d8b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 208 additions and 2 deletions

View File

@ -377,6 +377,9 @@ func (p *blockBodyDiffPrinter) writeNestedBlockDiffs(name string, blockS *config
var action plans.Action var action plans.Action
var oldValue, newValue cty.Value var oldValue, newValue cty.Value
switch { switch {
case !val.IsKnown():
action = plans.Update
newValue = val
case !old.HasElement(val).True(): case !old.HasElement(val).True():
action = plans.Create action = plans.Create
oldValue = cty.NullVal(val.Type()) oldValue = cty.NullVal(val.Type())
@ -697,7 +700,7 @@ func (p *blockBodyDiffPrinter) writeValueDiff(old, new cty.Value, indent int, pa
for it := new.ElementIterator(); it.Next(); { for it := new.ElementIterator(); it.Next(); {
_, val := it.Element() _, val := it.Element()
allVals = append(allVals, val) allVals = append(allVals, val)
if old.HasElement(val).False() { if val.IsKnown() && old.HasElement(val).False() {
addedVals = append(addedVals, val) addedVals = append(addedVals, val)
} }
} }
@ -726,6 +729,8 @@ func (p *blockBodyDiffPrinter) writeValueDiff(old, new cty.Value, indent int, pa
var action plans.Action var action plans.Action
switch { switch {
case !val.IsKnown():
action = plans.Update
case added.HasElement(val).True(): case added.HasElement(val).True():
action = plans.Create action = plans.Create
case removed.HasElement(val).True(): case removed.HasElement(val).True():
@ -1062,7 +1067,7 @@ func ctyObjectSimilarity(old, new cty.Value) float64 {
} }
func ctyEqualWithUnknown(old, new cty.Value) bool { func ctyEqualWithUnknown(old, new cty.Value) bool {
if !old.IsKnown() || !new.IsKnown() { if !old.IsWhollyKnown() || !new.IsWhollyKnown() {
return false return false
} }
return old.Equals(new).True() return old.Equals(new).True()

View File

@ -720,6 +720,92 @@ func TestResourceChange_primitiveList(t *testing.T) {
~ id = "i-02ae66f368e8518a9" -> (known after apply) ~ id = "i-02ae66f368e8518a9" -> (known after apply)
+ list_field = [] + list_field = []
} }
`,
},
"update to unknown element": {
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.ListVal([]cty.Value{
cty.StringVal("aaaa"),
cty.UnknownVal(cty.String),
cty.StringVal("cccc"),
}),
}),
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",
+ (known after apply),
"cccc",
]
}
`,
},
"update - two new unknown elements": {
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.ListVal([]cty.Value{
cty.StringVal("aaaa"),
cty.UnknownVal(cty.String),
cty.UnknownVal(cty.String),
cty.StringVal("cccc"),
}),
}),
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",
+ (known after apply),
+ (known after apply),
"cccc",
]
}
`, `,
}, },
} }
@ -1002,6 +1088,80 @@ func TestResourceChange_primitiveSet(t *testing.T) {
~ id = "i-02ae66f368e8518a9" -> (known after apply) ~ id = "i-02ae66f368e8518a9" -> (known after apply)
+ set_field = [] + set_field = []
} }
`,
},
"in-place update to unknown": {
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.UnknownVal(cty.Set(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",
] -> (known after apply)
}
`,
},
"in-place update to unknown element": {
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.SetVal([]cty.Value{
cty.StringVal("aaaa"),
cty.UnknownVal(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",
~ (known after apply),
]
}
`, `,
}, },
} }
@ -1220,6 +1380,47 @@ func TestResourceChange_map(t *testing.T) {
+ id = (known after apply) + id = (known after apply)
+ map_field = {} + map_field = {}
} }
`,
},
"update to unknown element": {
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.MapVal(map[string]cty.Value{
"a": cty.StringVal("aaaa"),
"b": cty.StringVal("bbbb"),
"c": cty.StringVal("cccc"),
}),
}),
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{
"a": cty.StringVal("aaaa"),
"b": cty.UnknownVal(cty.String),
"c": cty.StringVal("cccc"),
}),
}),
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 = {
"a" = "aaaa"
~ "b" = "bbbb" -> (known after apply)
"c" = "cccc"
}
}
`, `,
}, },
} }