diff --git a/.changelog/38194.txt b/.changelog/38194.txt new file mode 100644 index 00000000000..1600e2917b9 --- /dev/null +++ b/.changelog/38194.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_db_event_subscription: Fix validation for `name` and `name_prefix` +``` diff --git a/internal/service/rds/event_subscription.go b/internal/service/rds/event_subscription.go index f4760047969..98eeebaf415 100644 --- a/internal/service/rds/event_subscription.go +++ b/internal/service/rds/event_subscription.go @@ -80,7 +80,7 @@ func resourceEventSubscription() *schema.Resource { Computed: true, ForceNew: true, ConflictsWith: []string{names.AttrName}, - ValidateFunc: validEventSubscriptionName, + ValidateFunc: validEventSubscriptionNamePrefix, }, "sns_topic": { Type: schema.TypeString, diff --git a/internal/service/rds/validate.go b/internal/service/rds/validate.go index 1647dc456f3..0373b5608d7 100644 --- a/internal/service/rds/validate.go +++ b/internal/service/rds/validate.go @@ -5,15 +5,25 @@ package rds import ( "fmt" + "strings" "github.com/YakDriver/regexache" ) func validEventSubscriptionName(v interface{}, k string) (ws []string, errors []error) { value := v.(string) - if !regexache.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) { + if !regexache.MustCompile(`^[A-Za-z][0-9A-Za-z-]*$`).MatchString(value) { errors = append(errors, fmt.Errorf( - "only alphanumeric characters and hyphens allowed in %q", k)) + "only ASCII letters, digits, and hyphens allowed in %q, and it must begin with a letter", k)) + } + // When using name prefix, the generated suffix will always end with a number, so this check is not relevant + if strings.HasSuffix(value, "-") { + errors = append(errors, fmt.Errorf( + "%q cannot end with a hyphen", k)) + } + if strings.Contains(value, "--") { + errors = append(errors, fmt.Errorf( + "%q cannot contain two consecutive hyphens", k)) } if len(value) > 255 { errors = append(errors, fmt.Errorf( @@ -22,6 +32,24 @@ func validEventSubscriptionName(v interface{}, k string) (ws []string, errors [] return } +func validEventSubscriptionNamePrefix(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if !regexache.MustCompile(`^[A-Za-z][0-9A-Za-z-]*$`).MatchString(value) { + errors = append(errors, fmt.Errorf( + "only ASCII letters, digits, and hyphens allowed in %q, and it must begin with a letter", k)) + } + if strings.Contains(value, "--") { + errors = append(errors, fmt.Errorf( + "%q cannot contain two consecutive hyphens", k)) + } + // When using name prefix, the limit must account for the generated suffix that is 26 characters long + if len(value) > 229 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 229 characters", k)) + } + return +} + func validOptionGroupName(v interface{}, k string) (ws []string, errors []error) { value := v.(string) if !regexache.MustCompile(`^[a-z]`).MatchString(value) { diff --git a/internal/service/rds/validate_test.go b/internal/service/rds/validate_test.go index 0d366b0dfa9..12850dda8ef 100644 --- a/internal/service/rds/validate_test.go +++ b/internal/service/rds/validate_test.go @@ -27,6 +27,11 @@ func TestValidEventSubscriptionName(t *testing.T) { } invalidNames := []string{ + "invalid_name", + "invalid-name-", + "-invalid-name", + "0invalid-name", + "invalid--name", "Here is a name with: colon", "and here is another * invalid name", "also $ invalid", @@ -46,6 +51,46 @@ func TestValidEventSubscriptionName(t *testing.T) { } } +func TestValidEventSubscriptionNamePrefix(t *testing.T) { + t.Parallel() + + validNames := []string{ + "valid-name", + "valid02-name", + "Valid-Name1", + "valid-name-", + } + for _, v := range validNames { + _, errors := validEventSubscriptionNamePrefix(v, names.AttrNamePrefix) + if len(errors) != 0 { + t.Fatalf("%q should be a valid RDS Event Subscription Name: %q", v, errors) + } + } + + invalidNames := []string{ + "invalid_name", + "-invalid-name", + "0invalid-name", + "invalid--name", + "Here is a name with: colon", + "and here is another * invalid name", + "also $ invalid", + "This . is also %% invalid@!)+(", + "*", + "", + " ", + "_", + // length > 229 + strings.Repeat("W", 230), + } + for _, v := range invalidNames { + _, errors := validEventSubscriptionNamePrefix(v, names.AttrNamePrefix) + if len(errors) == 0 { + t.Fatalf("%q should be an invalid RDS Event Subscription Name Prefix", v) + } + } +} + func TestValidOptionGroupName(t *testing.T) { t.Parallel()