provider/aws: Validate regular expression passed via the name_regex attribute. (#9622)

* Clean-up for Go 1.7+ version.

Signed-off-by: Krzysztof Wilczynski <krzysztof.wilczynski@linux.com>

* Validate regular expression passed via the `name_regex` attribute.

This commit adds a simple ValidateFunc to check whether the regular
expression that was passed down via the `name_regex` attribute is valid.

Signed-off-by: Krzysztof Wilczynski <krzysztof.wilczynski@linux.com>
This commit is contained in:
Krzysztof Wilczynski 2016-10-26 12:09:14 +01:00 committed by Paul Stack
parent d05db51f7e
commit 44614c6765
2 changed files with 104 additions and 41 deletions

View File

@ -19,24 +19,24 @@ func dataSourceAwsAmi() *schema.Resource {
Read: dataSourceAwsAmiRead, Read: dataSourceAwsAmiRead,
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"executable_users": &schema.Schema{ "executable_users": {
Type: schema.TypeList, Type: schema.TypeList,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString}, Elem: &schema.Schema{Type: schema.TypeString},
}, },
"filter": &schema.Schema{ "filter": {
Type: schema.TypeSet, Type: schema.TypeSet,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": &schema.Schema{ "name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
}, },
"values": &schema.Schema{ "values": {
Type: schema.TypeList, Type: schema.TypeList,
Required: true, Required: true,
Elem: &schema.Schema{Type: schema.TypeString}, Elem: &schema.Schema{Type: schema.TypeString},
@ -44,158 +44,159 @@ func dataSourceAwsAmi() *schema.Resource {
}, },
}, },
}, },
"name_regex": &schema.Schema{ "name_regex": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
ValidateFunc: validateNameRegex,
}, },
"most_recent": &schema.Schema{ "most_recent": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Default: false, Default: false,
ForceNew: true, ForceNew: true,
}, },
"owners": &schema.Schema{ "owners": {
Type: schema.TypeList, Type: schema.TypeList,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString}, Elem: &schema.Schema{Type: schema.TypeString},
}, },
// Computed values. // Computed values.
"architecture": &schema.Schema{ "architecture": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"creation_date": &schema.Schema{ "creation_date": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"description": &schema.Schema{ "description": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"hypervisor": &schema.Schema{ "hypervisor": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"image_id": &schema.Schema{ "image_id": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"image_location": &schema.Schema{ "image_location": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"image_owner_alias": &schema.Schema{ "image_owner_alias": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"image_type": &schema.Schema{ "image_type": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"kernel_id": &schema.Schema{ "kernel_id": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"name": &schema.Schema{ "name": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"owner_id": &schema.Schema{ "owner_id": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"platform": &schema.Schema{ "platform": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"public": &schema.Schema{ "public": {
Type: schema.TypeBool, Type: schema.TypeBool,
Computed: true, Computed: true,
}, },
"ramdisk_id": &schema.Schema{ "ramdisk_id": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"root_device_name": &schema.Schema{ "root_device_name": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"root_device_type": &schema.Schema{ "root_device_type": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"sriov_net_support": &schema.Schema{ "sriov_net_support": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"state": &schema.Schema{ "state": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"virtualization_type": &schema.Schema{ "virtualization_type": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
// Complex computed values // Complex computed values
"block_device_mappings": &schema.Schema{ "block_device_mappings": {
Type: schema.TypeSet, Type: schema.TypeSet,
Computed: true, Computed: true,
Set: amiBlockDeviceMappingHash, Set: amiBlockDeviceMappingHash,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"device_name": &schema.Schema{ "device_name": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"no_device": &schema.Schema{ "no_device": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"virtual_name": &schema.Schema{ "virtual_name": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"ebs": &schema.Schema{ "ebs": {
Type: schema.TypeMap, Type: schema.TypeMap,
Computed: true, Computed: true,
}, },
}, },
}, },
}, },
"product_codes": &schema.Schema{ "product_codes": {
Type: schema.TypeSet, Type: schema.TypeSet,
Computed: true, Computed: true,
Set: amiProductCodesHash, Set: amiProductCodesHash,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"product_code_id": &schema.Schema{ "product_code_id": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"product_code_type": &schema.Schema{ "product_code_type": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
}, },
}, },
}, },
"state_reason": &schema.Schema{ "state_reason": {
Type: schema.TypeMap, Type: schema.TypeMap,
Computed: true, Computed: true,
}, },
"tags": &schema.Schema{ "tags": {
Type: schema.TypeSet, Type: schema.TypeSet,
Computed: true, Computed: true,
Set: amiTagsHash, Set: amiTagsHash,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"key": &schema.Schema{ "key": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"value": &schema.Schema{ "value": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
@ -497,3 +498,14 @@ func amiTagsHash(v interface{}) int {
buf.WriteString(fmt.Sprintf("%s-", m["value"].(string))) buf.WriteString(fmt.Sprintf("%s-", m["value"].(string)))
return hashcode.String(buf.String()) return hashcode.String(buf.String())
} }
func validateNameRegex(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if _, err := regexp.Compile(value); err != nil {
errors = append(errors, fmt.Errorf(
"%q contains an invalid regular expression: %s",
k, err))
}
return
}

View File

@ -155,6 +155,57 @@ func TestAccAWSAmiDataSource_localNameFilter(t *testing.T) {
}) })
} }
func TestResourceValidateNameRegex(t *testing.T) {
type testCases struct {
Value string
ErrCount int
}
invalidCases := []testCases{
{
Value: `\`,
ErrCount: 1,
},
{
Value: `**`,
ErrCount: 1,
},
{
Value: `(.+`,
ErrCount: 1,
},
}
for _, tc := range invalidCases {
_, errors := validateNameRegex(tc.Value, "name_regex")
if len(errors) != tc.ErrCount {
t.Fatalf("Expected %q to trigger a validation error.", tc.Value)
}
}
validCases := []testCases{
{
Value: `\/`,
ErrCount: 0,
},
{
Value: `.*`,
ErrCount: 0,
},
{
Value: `\b(?:\d{1,3}\.){3}\d{1,3}\b`,
ErrCount: 0,
},
}
for _, tc := range validCases {
_, errors := validateNameRegex(tc.Value, "name_regex")
if len(errors) != tc.ErrCount {
t.Fatalf("Expected %q not to trigger a validation error.", tc.Value)
}
}
}
func testAccCheckAwsAmiDataSourceDestroy(s *terraform.State) error { func testAccCheckAwsAmiDataSourceDestroy(s *terraform.State) error {
return nil return nil
} }