diff --git a/google/resource_cloudfunctions_function.go b/google/resource_cloudfunctions_function.go index ddafce2e..2d4a8080 100644 --- a/google/resource_cloudfunctions_function.go +++ b/google/resource_cloudfunctions_function.go @@ -72,6 +72,28 @@ func joinMapKeys(mapToJoin *map[int]bool) string { return strings.Join(keys, ",") } +func validateResourceCloudFunctionsFunctionName(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if len(value) > 48 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 48 characters", k)) + } + if !regexp.MustCompile("^[a-zA-Z0-9-_]+$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q can only contain letters, numbers, underscores and hyphens", k)) + } + if !regexp.MustCompile("^[a-zA-Z]").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must start with a letter", k)) + } + if !regexp.MustCompile("[a-zA-Z0-9]$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must end with a number or a letter", k)) + } + return +} + func resourceCloudFunctionsFunction() *schema.Resource { return &schema.Resource{ Create: resourceCloudFunctionsCreate, @@ -91,30 +113,10 @@ func resourceCloudFunctionsFunction() *schema.Resource { Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { - value := v.(string) - - if len(value) > 48 { - errors = append(errors, fmt.Errorf( - "%q cannot be longer than 48 characters", k)) - } - if !regexp.MustCompile("^[a-zA-Z0-9-_]+$").MatchString(value) { - errors = append(errors, fmt.Errorf( - "%q can only contain letters, numbers, underscores and hyphens", k)) - } - if !regexp.MustCompile("^[a-zA-Z]").MatchString(value) { - errors = append(errors, fmt.Errorf( - "%q must start with a letter", k)) - } - if !regexp.MustCompile("[a-zA-Z0-9]$").MatchString(value) { - errors = append(errors, fmt.Errorf( - "%q must end with a number or a letter", k)) - } - return - }, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateResourceCloudFunctionsFunctionName, }, "source_archive_bucket": { diff --git a/google/resource_cloudfunctions_function_test.go b/google/resource_cloudfunctions_function_test.go index b7cdcb0e..6e336882 100644 --- a/google/resource_cloudfunctions_function_test.go +++ b/google/resource_cloudfunctions_function_test.go @@ -25,6 +25,41 @@ const testPubSubTriggerPath = "./test-fixtures/cloudfunctions/pubsub_trigger.js" const testBucketTriggerPath = "./test-fixtures/cloudfunctions/bucket_trigger.js" const testFirestoreTriggerPath = "./test-fixtures/cloudfunctions/firestore_trigger.js" +func TestCloudFunctionsFunction_nameValidator(t *testing.T) { + validNames := []string{ + "a", + "aA", + "a0", + "has-hyphen", + "has_underscore", + "hasUpperCase", + "allChars_-A0", + } + for _, tc := range validNames { + wrns, errs := validateResourceCloudFunctionsFunctionName(tc, "function.name") + if len(wrns) > 0 { + t.Errorf("Expected no validation warnings for test case %q, got: %+v", tc, wrns) + } + if len(errs) > 0 { + t.Errorf("Expected no validation errors for test name %q, got: %+v", tc, errs) + } + } + + invalidNames := []string{ + "0startsWithNumber", + "endsWith_", + "endsWith-", + "bad*Character", + "aFunctionsNameThatIsLongerThanFortyEightCharacters", + } + for _, tc := range invalidNames { + _, errs := validateResourceCloudFunctionsFunctionName(tc, "function.name") + if len(errs) == 0 { + t.Errorf("Expected errors for invalid test name %q, got none", tc) + } + } +} + func TestAccCloudFunctionsFunction_basic(t *testing.T) { t.Parallel()