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.
pull/20348/head
James Bardin 7 years ago
parent f9b62cb5fe
commit da389d6cd4

@ -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 {

@ -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,

@ -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"),
),
},
},
})
}

@ -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
}
}
// 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[name+"."+idx] == "" {
result[name+"."+idx] = countFlatmapContainerValues(name+"."+idx, result)
if result[countKey] == "" {
result[countKey] = countFlatmapContainerValues(countKey, result)
}
return result, nil
}

Loading…
Cancel
Save