Skip to content

Commit

Permalink
Implement TypeSet resource.TestCheckFuncs
Browse files Browse the repository at this point in the history
  • Loading branch information
appilon committed Jun 12, 2020
1 parent fcabc0f commit 0cf3146
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 64 deletions.
114 changes: 114 additions & 0 deletions aws/internal/test/testing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package test

import (
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
)

const (
sentinelIndex = "*"
)

// TestCheckTypeSetElemNestedAttrs is a resource.TestCheckFunc that accepts a resource
// name, an attribute path, which should use the sentinel value '*' for indexing
// into a TypeSet. The function verifies that an element matches the whole value
// map.
//
// Use this function over SDK provided TestCheckFunctions when validating a
// TypeSet where its elements are a nested object with their own attrs/values.
//
// Please note, if the provided value map is not granular enough, there exists
// the possibility you match an element you were not intending to, in the TypeSet.
// Provide a full mapping of attributes to be sure the unique element exists.
func TestCheckTypeSetElemNestedAttrs(res, attr string, values map[string]string) resource.TestCheckFunc {
return func(s *terraform.State) error {
ms := s.RootModule()
rs, ok := ms.Resources[res]
if !ok {
return fmt.Errorf("Not found: %s in %s", res, ms.Path)
}

is := rs.Primary
if is == nil {
return fmt.Errorf("No primary instance: %s in %s", res, ms.Path)
}

matches := make(map[string]int)
attrParts := strings.Split(attr, ".")
for stateKey, stateValue := range is.Attributes {
stateKeyParts := strings.Split(stateKey, ".")
// a Set/List item with nested attrs would have a flatmap address of
// at least length 3
// foo.0.name = "bar"
if len(stateKeyParts) < 3 {
continue
}
var pathMatch bool
for i := range attrParts {
if attrParts[i] != stateKeyParts[i] && attrParts[i] != sentinelIndex {
break
}
if i == len(attrParts)-1 {
pathMatch = true
}
}
if !pathMatch {
continue
}
elementId := stateKeyParts[len(attrParts)-1]
nestedAttr := strings.Join(stateKeyParts[len(attrParts):], ".")
if v, keyExists := values[nestedAttr]; keyExists && v == stateValue {
matches[elementId] = matches[elementId] + 1
if matches[elementId] == len(values) {
return nil
}
}
}

return fmt.Errorf("%q no TypeSet element %q, with nested attrs %#v in state: %#v", res, attr, values, is.Attributes)
}
}

// TestCheckTypeSetElemAttr is a resource.TestCheckFunc that accepts a resource
// name, an attribute path, which should use the sentinel value '*' for indexing
// into a TypeSet. The function verifies that an element matches the provided
// value.
//
// Use this function over SDK provided TestCheckFunctions when validating a
// TypeSet where its elements are a simple value
func TestCheckTypeSetElemAttr(res, attr, value string) resource.TestCheckFunc {
return func(s *terraform.State) error {
ms := s.RootModule()
rs, ok := ms.Resources[res]
if !ok {
return fmt.Errorf("Not found: %s in %s", res, ms.Path)
}

is := rs.Primary
if is == nil {
return fmt.Errorf("No primary instance: %s in %s", res, ms.Path)
}

attrParts := strings.Split(attr, ".")
for stateKey, stateValue := range is.Attributes {
if stateValue == value {
stateKeyParts := strings.Split(stateKey, ".")
if len(stateKeyParts) == len(attrParts) {
for i := range attrParts {
if attrParts[i] != stateKeyParts[i] && attrParts[i] != sentinelIndex {
break
}
if i == len(attrParts)-1 {
return nil
}
}
}
}
}

return fmt.Errorf("%q no TypeSet element %q, with value %q in state: %#v", res, attr, value, is.Attributes)
}
}
25 changes: 13 additions & 12 deletions aws/resource_aws_apigatewayv2_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"

"github.com/terraform-providers/terraform-provider-aws/aws/internal/test"
)

func init() {
Expand Down Expand Up @@ -374,10 +376,9 @@ func TestAccAWSAPIGatewayV2Api_CorsConfiguration(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAPIGatewayV2ApiDestroy,
DisableBinaryDriver: true,
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSAPIGatewayV2ApiDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSAPIGatewayV2ApiConfig_corsConfiguration(rName),
Expand All @@ -389,12 +390,12 @@ func TestAccAWSAPIGatewayV2Api_CorsConfiguration(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "cors_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_credentials", "false"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_headers.#", "1"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_headers.2053999599", "Authorization"),
test.TestCheckTypeSetElemAttr(resourceName, "cors_configuration.0.allow_headers.*", "Authorization"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_methods.#", "2"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_methods.4248514160", "GET"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_methods.2928708052", "put"),
test.TestCheckTypeSetElemAttr(resourceName, "cors_configuration.0.allow_methods.*", "GET"),
test.TestCheckTypeSetElemAttr(resourceName, "cors_configuration.0.allow_methods.*", "put"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_origins.#", "1"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_origins.89023941", "https://www.example.com"),
test.TestCheckTypeSetElemAttr(resourceName, "cors_configuration.0.allow_origins.*", "https://www.example.com"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.expose_headers.#", "0"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.max_age", "0"),
resource.TestCheckResourceAttr(resourceName, "description", ""),
Expand Down Expand Up @@ -422,12 +423,12 @@ func TestAccAWSAPIGatewayV2Api_CorsConfiguration(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_credentials", "true"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_headers.#", "0"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_methods.#", "1"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_methods.163128923", "*"),
test.TestCheckTypeSetElemAttr(resourceName, "cors_configuration.0.allow_methods.*", "*"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_origins.#", "2"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_origins.1868318776", "HTTP://WWW.EXAMPLE.ORG"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.allow_origins.3551736600", "https://example.io"),
test.TestCheckTypeSetElemAttr(resourceName, "cors_configuration.0.allow_origins.*", "HTTP://WWW.EXAMPLE.ORG"),
test.TestCheckTypeSetElemAttr(resourceName, "cors_configuration.0.allow_origins.*", "https://example.io"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.expose_headers.#", "1"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.expose_headers.115091893", "X-Api-Id"),
test.TestCheckTypeSetElemAttr(resourceName, "cors_configuration.0.expose_headers.*", "X-Api-Id"),
resource.TestCheckResourceAttr(resourceName, "cors_configuration.0.max_age", "500"),
resource.TestCheckResourceAttr(resourceName, "description", ""),
testAccMatchResourceAttrRegionalARN(resourceName, "execution_arn", "execute-api", regexp.MustCompile(`.+`)),
Expand Down
71 changes: 49 additions & 22 deletions aws/resource_aws_db_parameter_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/test"
)

func init() {
Expand Down Expand Up @@ -79,10 +80,9 @@ func TestAccAWSDBParameterGroup_basic(t *testing.T) {
groupName := fmt.Sprintf("parameter-group-test-terraform-%d", acctest.RandInt())

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSDBParameterGroupDestroy,
DisableBinaryDriver: true,
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSDBParameterGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSDBParameterGroupConfig(groupName),
Expand All @@ -91,12 +91,18 @@ func TestAccAWSDBParameterGroup_basic(t *testing.T) {
testAccCheckAWSDBParameterGroupAttributes(&v, groupName),
resource.TestCheckResourceAttr(resourceName, "name", groupName),
resource.TestCheckResourceAttr(resourceName, "family", "mysql5.6"),
resource.TestCheckResourceAttr(resourceName, "parameter.1708034931.name", "character_set_results"),
resource.TestCheckResourceAttr(resourceName, "parameter.1708034931.value", "utf8"),
resource.TestCheckResourceAttr(resourceName, "parameter.2421266705.name", "character_set_server"),
resource.TestCheckResourceAttr(resourceName, "parameter.2421266705.value", "utf8"),
resource.TestCheckResourceAttr(resourceName, "parameter.2478663599.name", "character_set_client"),
resource.TestCheckResourceAttr(resourceName, "parameter.2478663599.value", "utf8"),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "character_set_results",
"value": "utf8",
}),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "character_set_server",
"value": "utf8",
}),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "character_set_client",
"value": "utf8",
}),
testAccMatchResourceAttrRegionalARN(resourceName, "arn", "rds", regexp.MustCompile(fmt.Sprintf("pg:%s$", groupName))),
),
},
Expand All @@ -112,16 +118,26 @@ func TestAccAWSDBParameterGroup_basic(t *testing.T) {
testAccCheckAWSDBParameterGroupAttributes(&v, groupName),
resource.TestCheckResourceAttr(resourceName, "name", groupName),
resource.TestCheckResourceAttr(resourceName, "family", "mysql5.6"),
resource.TestCheckResourceAttr(resourceName, "parameter.1706463059.name", "collation_connection"),
resource.TestCheckResourceAttr(resourceName, "parameter.1706463059.value", "utf8_unicode_ci"),
resource.TestCheckResourceAttr(resourceName, "parameter.1708034931.name", "character_set_results"),
resource.TestCheckResourceAttr(resourceName, "parameter.1708034931.value", "utf8"),
resource.TestCheckResourceAttr(resourceName, "parameter.2421266705.name", "character_set_server"),
resource.TestCheckResourceAttr(resourceName, "parameter.2421266705.value", "utf8"),
resource.TestCheckResourceAttr(resourceName, "parameter.2475805061.name", "collation_server"),
resource.TestCheckResourceAttr(resourceName, "parameter.2475805061.value", "utf8_unicode_ci"),
resource.TestCheckResourceAttr(resourceName, "parameter.2478663599.name", "character_set_client"),
resource.TestCheckResourceAttr(resourceName, "parameter.2478663599.value", "utf8"),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "collation_connection",
"value": "utf8_unicode_ci",
}),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "character_set_results",
"value": "utf8",
}),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "character_set_server",
"value": "utf8",
}),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "collation_server",
"value": "utf8_unicode_ci",
}),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "character_set_client",
"value": "utf8",
}),
testAccMatchResourceAttrRegionalARN(resourceName, "arn", "rds", regexp.MustCompile(fmt.Sprintf("pg:%s$", groupName))),
),
},
Expand All @@ -132,8 +148,19 @@ func TestAccAWSDBParameterGroup_basic(t *testing.T) {
testAccCheckAWSDBParameterGroupAttributes(&v, groupName),
testAccCheckAWSDBParameterNotUserDefined(resourceName, "collation_connection"),
testAccCheckAWSDBParameterNotUserDefined(resourceName, "collation_server"),
resource.TestCheckNoResourceAttr(resourceName, "parameter.2475805061.value"),
resource.TestCheckNoResourceAttr(resourceName, "parameter.1706463059.value"),
resource.TestCheckResourceAttr(resourceName, "parameter.#", "3"),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "character_set_results",
"value": "utf8",
}),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "character_set_server",
"value": "utf8",
}),
test.TestCheckTypeSetElemNestedAttrs(resourceName, "parameter.*", map[string]string{
"name": "character_set_client",
"value": "utf8",
}),
),
},
},
Expand Down
Loading

0 comments on commit 0cf3146

Please sign in to comment.