simple list diffs may also have missing elements

Like was done for list blocks, simple lists of strings may be missing
empty string elements, and any list may be implicitly truncated.
This commit is contained in:
James Bardin 2019-02-14 12:32:42 -05:00
parent f9b62cb5fe
commit da389d6cd4
4 changed files with 121 additions and 5 deletions

View File

@ -171,7 +171,7 @@ func testResourceUpdate(d *schema.ResourceData, meta interface{}) error {
if errMsg != "" {
return errors.New(errMsg)
}
return nil
return testResourceRead(d, meta)
}
func testResourceDelete(d *schema.ResourceData, meta interface{}) error {

View File

@ -30,6 +30,13 @@ func testResourceList() *schema.Resource {
Optional: true,
ForceNew: true,
},
"sublist": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"sublist_block": {
Type: schema.TypeList,
Optional: true,

View File

@ -218,3 +218,61 @@ resource "test_resource_list" "foo" {
},
})
}
func TestResourceList_emptyStrings(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
Providers: testAccProviders,
CheckDestroy: testAccCheckResourceDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: strings.TrimSpace(`
resource "test_resource_list" "foo" {
list_block {
sublist = ["a", ""]
}
list_block {
sublist = [""]
}
list_block {
sublist = ["", "c", ""]
}
}
`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.0.sublist.0", "a"),
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.0.sublist.1", ""),
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.1.sublist.0", ""),
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.2.sublist.0", ""),
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.2.sublist.1", "c"),
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.2.sublist.2", ""),
),
},
resource.TestStep{
Config: strings.TrimSpace(`
resource "test_resource_list" "foo" {
list_block {
sublist = [""]
}
list_block {
sublist = []
}
list_block {
sublist = ["", "c"]
}
}
`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.0.sublist.#", "1"),
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.0.sublist.0", ""),
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.1.sublist.#", "0"),
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.2.sublist.1", "c"),
resource.TestCheckResourceAttr("test_resource_list.foo", "list_block.2.sublist.#", "2"),
),
},
},
})
}

View File

@ -624,7 +624,7 @@ func (d *InstanceDiff) applyBlockDiff(path []string, attrs map[string]string, sc
if err != nil {
// this shouldn't happen since we added these
// ourself, but make note of it just in case.
log.Printf("[ERROR] bas list index in %q: %s", k, err)
log.Printf("[ERROR] bad list index in %q: %s", k, err)
continue
}
if i >= length {
@ -811,10 +811,61 @@ func (d *InstanceDiff) applyCollectionDiff(path []string, attrs map[string]strin
}
}
// Fill in the count value if it was missing for some reason:
if result[name+"."+idx] == "" {
result[name+"."+idx] = countFlatmapContainerValues(name+"."+idx, result)
// Just like in nested list blocks, for simple lists we may need to fill in
// missing empty strings.
countKey := name + "." + idx
count := result[countKey]
length, _ := strconv.Atoi(count)
if count != "" && count != hcl2shim.UnknownVariableValue &&
attrSchema.Type.Equals(cty.List(cty.String)) {
// insert empty strings into missing indexes
for i := 0; i < length; i++ {
key := fmt.Sprintf("%s.%d", name, i)
if _, ok := result[key]; !ok {
result[key] = ""
}
}
}
// now check for truncation in any type of list
if attrSchema.Type.IsListType() {
for key := range result {
if key == countKey {
continue
}
if len(key) <= len(name)+1 {
// not sure what this is, but don't panic
continue
}
index := key[len(name)+1:]
// It is possible to have nested sets or maps, so look for another dot
dot := strings.Index(index, ".")
if dot > 0 {
index = index[:dot]
}
// This shouldn't have any more dots, since the element type is only string.
num, err := strconv.Atoi(index)
if err != nil {
log.Printf("[ERROR] bad list index in %q: %s", currentKey, err)
continue
}
if num >= length {
delete(result, key)
}
}
}
// Fill in the count value if it was missing for some reason:
if result[countKey] == "" {
result[countKey] = countFlatmapContainerValues(countKey, result)
}
return result, nil
}