Skip to content

Commit f74b5a6

Browse files
authored
helper/resource: Added error when errantly checking list, map, or set attributes in TestCheckNoResourceAttr, TestCheckResourceAttr, and TestCheckResourceAttrSet (#920)
Reference: hashicorp/terraform-plugin-sdk#885
1 parent 40ff3ed commit f74b5a6

File tree

3 files changed

+990
-64
lines changed

3 files changed

+990
-64
lines changed

.changelog/920.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:enhancement
2+
helper/resource: Added error when errantly checking list, map, or set attributes in `TestCheckNoResourceAttr`, `TestCheckResourceAttr`, and `TestCheckResourceAttrSet`
3+
```
4+
5+
```release-note:note
6+
helper/resource: False positive checks of list, map, and set attributes with `TestCheckNoResourceAttr` and `TestCheckResourceAttrSet` will now return an error to explain how to accurately check those types of attributes. Some previously passing tests will now fail until the check is correctly updated.
7+
```

helper/resource/testing.go

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -823,11 +823,33 @@ func TestCheckModuleResourceAttrSet(mp []string, name string, key string) TestCh
823823
}
824824

825825
func testCheckResourceAttrSet(is *terraform.InstanceState, name string, key string) error {
826-
if val, ok := is.Attributes[key]; !ok || val == "" {
827-
return fmt.Errorf("%s: Attribute '%s' expected to be set", name, key)
826+
val, ok := is.Attributes[key]
827+
828+
if ok && val != "" {
829+
return nil
828830
}
829831

830-
return nil
832+
if _, ok := is.Attributes[key+".#"]; ok {
833+
return fmt.Errorf(
834+
"%s: list or set attribute '%s' must be checked by element count key (%s) or element value keys (e.g. %s). Set element value checks should use TestCheckTypeSet functions instead.",
835+
name,
836+
key,
837+
key+".#",
838+
key+".0",
839+
)
840+
}
841+
842+
if _, ok := is.Attributes[key+".%"]; ok {
843+
return fmt.Errorf(
844+
"%s: map attribute '%s' must be checked by element count key (%s) or element value keys (e.g. %s).",
845+
name,
846+
key,
847+
key+".%",
848+
key+".examplekey",
849+
)
850+
}
851+
852+
return fmt.Errorf("%s: Attribute '%s' expected to be set", name, key)
831853
}
832854

833855
// TestCheckResourceAttr ensures a specific value is stored in state for the
@@ -892,30 +914,48 @@ func TestCheckModuleResourceAttr(mp []string, name string, key string, value str
892914
}
893915

894916
func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, value string) error {
895-
// Empty containers may be elided from the state.
896-
// If the intent here is to check for an empty container, allow the key to
897-
// also be non-existent.
898-
emptyCheck := false
899-
if value == "0" && (strings.HasSuffix(key, ".#") || strings.HasSuffix(key, ".%")) {
900-
emptyCheck = true
901-
}
917+
v, ok := is.Attributes[key]
902918

903-
if v, ok := is.Attributes[key]; !ok || v != value {
904-
if emptyCheck && !ok {
919+
if !ok {
920+
// Empty containers may be elided from the state.
921+
// If the intent here is to check for an empty container, allow the key to
922+
// also be non-existent.
923+
if value == "0" && (strings.HasSuffix(key, ".#") || strings.HasSuffix(key, ".%")) {
905924
return nil
906925
}
907926

908-
if !ok {
909-
return fmt.Errorf("%s: Attribute '%s' not found", name, key)
927+
if _, ok := is.Attributes[key+".#"]; ok {
928+
return fmt.Errorf(
929+
"%s: list or set attribute '%s' must be checked by element count key (%s) or element value keys (e.g. %s). Set element value checks should use TestCheckTypeSet functions instead.",
930+
name,
931+
key,
932+
key+".#",
933+
key+".0",
934+
)
935+
}
936+
937+
if _, ok := is.Attributes[key+".%"]; ok {
938+
return fmt.Errorf(
939+
"%s: map attribute '%s' must be checked by element count key (%s) or element value keys (e.g. %s).",
940+
name,
941+
key,
942+
key+".%",
943+
key+".examplekey",
944+
)
910945
}
911946

947+
return fmt.Errorf("%s: Attribute '%s' not found", name, key)
948+
}
949+
950+
if v != value {
912951
return fmt.Errorf(
913952
"%s: Attribute '%s' expected %#v, got %#v",
914953
name,
915954
key,
916955
value,
917956
v)
918957
}
958+
919959
return nil
920960
}
921961

@@ -976,23 +1016,39 @@ func TestCheckModuleNoResourceAttr(mp []string, name string, key string) TestChe
9761016
}
9771017

9781018
func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key string) error {
1019+
v, ok := is.Attributes[key]
1020+
9791021
// Empty containers may sometimes be included in the state.
9801022
// If the intent here is to check for an empty container, allow the value to
9811023
// also be "0".
982-
emptyCheck := false
983-
if strings.HasSuffix(key, ".#") || strings.HasSuffix(key, ".%") {
984-
emptyCheck = true
985-
}
986-
987-
val, exists := is.Attributes[key]
988-
if emptyCheck && val == "0" {
1024+
if v == "0" && (strings.HasSuffix(key, ".#") || strings.HasSuffix(key, ".%")) {
9891025
return nil
9901026
}
9911027

992-
if exists {
1028+
if ok {
9931029
return fmt.Errorf("%s: Attribute '%s' found when not expected", name, key)
9941030
}
9951031

1032+
if _, ok := is.Attributes[key+".#"]; ok {
1033+
return fmt.Errorf(
1034+
"%s: list or set attribute '%s' must be checked by element count key (%s) or element value keys (e.g. %s). Set element value checks should use TestCheckTypeSet functions instead.",
1035+
name,
1036+
key,
1037+
key+".#",
1038+
key+".0",
1039+
)
1040+
}
1041+
1042+
if _, ok := is.Attributes[key+".%"]; ok {
1043+
return fmt.Errorf(
1044+
"%s: map attribute '%s' must be checked by element count key (%s) or element value keys (e.g. %s).",
1045+
name,
1046+
key,
1047+
key+".%",
1048+
key+".examplekey",
1049+
)
1050+
}
1051+
9961052
return nil
9971053
}
9981054

0 commit comments

Comments
 (0)