From 44614c676559bc257557a926d440dc6016219aeb Mon Sep 17 00:00:00 2001 From: Krzysztof Wilczynski Date: Wed, 26 Oct 2016 12:09:14 +0100 Subject: [PATCH] provider/aws: Validate regular expression passed via the `name_regex` attribute. (#9622) * Clean-up for Go 1.7+ version. Signed-off-by: Krzysztof Wilczynski * 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 --- builtin/providers/aws/data_source_aws_ami.go | 94 +++++++++++-------- .../providers/aws/data_source_aws_ami_test.go | 51 ++++++++++ 2 files changed, 104 insertions(+), 41 deletions(-) diff --git a/builtin/providers/aws/data_source_aws_ami.go b/builtin/providers/aws/data_source_aws_ami.go index ff6200a2c1..bcdce62eac 100644 --- a/builtin/providers/aws/data_source_aws_ami.go +++ b/builtin/providers/aws/data_source_aws_ami.go @@ -19,24 +19,24 @@ func dataSourceAwsAmi() *schema.Resource { Read: dataSourceAwsAmiRead, Schema: map[string]*schema.Schema{ - "executable_users": &schema.Schema{ + "executable_users": { Type: schema.TypeList, Optional: true, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - "filter": &schema.Schema{ + "filter": { Type: schema.TypeSet, Optional: true, ForceNew: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, }, - "values": &schema.Schema{ + "values": { Type: schema.TypeList, Required: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -44,158 +44,159 @@ func dataSourceAwsAmi() *schema.Resource { }, }, }, - "name_regex": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - ForceNew: true, + "name_regex": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validateNameRegex, }, - "most_recent": &schema.Schema{ + "most_recent": { Type: schema.TypeBool, Optional: true, Default: false, ForceNew: true, }, - "owners": &schema.Schema{ + "owners": { Type: schema.TypeList, Optional: true, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, }, // Computed values. - "architecture": &schema.Schema{ + "architecture": { Type: schema.TypeString, Computed: true, }, - "creation_date": &schema.Schema{ + "creation_date": { Type: schema.TypeString, Computed: true, }, - "description": &schema.Schema{ + "description": { Type: schema.TypeString, Computed: true, }, - "hypervisor": &schema.Schema{ + "hypervisor": { Type: schema.TypeString, Computed: true, }, - "image_id": &schema.Schema{ + "image_id": { Type: schema.TypeString, Computed: true, }, - "image_location": &schema.Schema{ + "image_location": { Type: schema.TypeString, Computed: true, }, - "image_owner_alias": &schema.Schema{ + "image_owner_alias": { Type: schema.TypeString, Computed: true, }, - "image_type": &schema.Schema{ + "image_type": { Type: schema.TypeString, Computed: true, }, - "kernel_id": &schema.Schema{ + "kernel_id": { Type: schema.TypeString, Computed: true, }, - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Computed: true, }, - "owner_id": &schema.Schema{ + "owner_id": { Type: schema.TypeString, Computed: true, }, - "platform": &schema.Schema{ + "platform": { Type: schema.TypeString, Computed: true, }, - "public": &schema.Schema{ + "public": { Type: schema.TypeBool, Computed: true, }, - "ramdisk_id": &schema.Schema{ + "ramdisk_id": { Type: schema.TypeString, Computed: true, }, - "root_device_name": &schema.Schema{ + "root_device_name": { Type: schema.TypeString, Computed: true, }, - "root_device_type": &schema.Schema{ + "root_device_type": { Type: schema.TypeString, Computed: true, }, - "sriov_net_support": &schema.Schema{ + "sriov_net_support": { Type: schema.TypeString, Computed: true, }, - "state": &schema.Schema{ + "state": { Type: schema.TypeString, Computed: true, }, - "virtualization_type": &schema.Schema{ + "virtualization_type": { Type: schema.TypeString, Computed: true, }, // Complex computed values - "block_device_mappings": &schema.Schema{ + "block_device_mappings": { Type: schema.TypeSet, Computed: true, Set: amiBlockDeviceMappingHash, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "device_name": &schema.Schema{ + "device_name": { Type: schema.TypeString, Computed: true, }, - "no_device": &schema.Schema{ + "no_device": { Type: schema.TypeString, Computed: true, }, - "virtual_name": &schema.Schema{ + "virtual_name": { Type: schema.TypeString, Computed: true, }, - "ebs": &schema.Schema{ + "ebs": { Type: schema.TypeMap, Computed: true, }, }, }, }, - "product_codes": &schema.Schema{ + "product_codes": { Type: schema.TypeSet, Computed: true, Set: amiProductCodesHash, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "product_code_id": &schema.Schema{ + "product_code_id": { Type: schema.TypeString, Computed: true, }, - "product_code_type": &schema.Schema{ + "product_code_type": { Type: schema.TypeString, Computed: true, }, }, }, }, - "state_reason": &schema.Schema{ + "state_reason": { Type: schema.TypeMap, Computed: true, }, - "tags": &schema.Schema{ + "tags": { Type: schema.TypeSet, Computed: true, Set: amiTagsHash, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "key": &schema.Schema{ + "key": { Type: schema.TypeString, Computed: true, }, - "value": &schema.Schema{ + "value": { Type: schema.TypeString, Computed: true, }, @@ -497,3 +498,14 @@ func amiTagsHash(v interface{}) int { buf.WriteString(fmt.Sprintf("%s-", m["value"].(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 +} diff --git a/builtin/providers/aws/data_source_aws_ami_test.go b/builtin/providers/aws/data_source_aws_ami_test.go index d3046eff49..c37b4b87ca 100644 --- a/builtin/providers/aws/data_source_aws_ami_test.go +++ b/builtin/providers/aws/data_source_aws_ami_test.go @@ -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 { return nil }