diff --git a/google/resource_google_project_services.go b/google/resource_google_project_services.go index aecf2ab1..206a4f3a 100644 --- a/google/resource_google_project_services.go +++ b/google/resource_google_project_services.go @@ -32,8 +32,11 @@ func resourceGoogleProjectServices() *schema.Resource { "services": { Type: schema.TypeSet, Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: StringNotInSlice(ignoredProjectServices, false), + }, }, "disable_on_destroy": &schema.Schema{ Type: schema.TypeBool, @@ -44,13 +47,11 @@ func resourceGoogleProjectServices() *schema.Resource { } } +var ignoredProjectServices = []string{"dataproc-control.googleapis.com", "source.googleapis.com", "stackdriverprovisioning.googleapis.com"} + // These services can only be enabled as a side-effect of enabling other services, // so don't bother storing them in the config or using them for diffing. -var ignoreProjectServices = map[string]struct{}{ - "dataproc-control.googleapis.com": struct{}{}, - "source.googleapis.com": struct{}{}, - "stackdriverprovisioning.googleapis.com": struct{}{}, -} +var ignoreProjectServices = golangSetFromStringSlice(ignoredProjectServices) func resourceGoogleProjectServicesCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) diff --git a/google/utils.go b/google/utils.go index 38c4fbfd..29ce7d00 100644 --- a/google/utils.go +++ b/google/utils.go @@ -341,6 +341,15 @@ func convertStringSet(set *schema.Set) []string { return s } +func golangSetFromStringSlice(strings []string) map[string]struct{} { + set := map[string]struct{}{} + for _, v := range strings { + set[v] = struct{}{} + } + + return set +} + func mergeSchemas(a, b map[string]*schema.Schema) map[string]*schema.Schema { merged := make(map[string]*schema.Schema) diff --git a/google/validation.go b/google/validation.go index 6ab10c49..b840b57a 100644 --- a/google/validation.go +++ b/google/validation.go @@ -186,3 +186,25 @@ func validateProjectName() schema.SchemaValidateFunc { return } } + +// StringNotInSlice returns a SchemaValidateFunc which tests if the provided value +// is of type string and that it matches none of the element in the invalid slice. +// if ignorecase is true, case is ignored. +func StringNotInSlice(invalid []string, ignoreCase bool) schema.SchemaValidateFunc { + return func(i interface{}, k string) (s []string, es []error) { + v, ok := i.(string) + if !ok { + es = append(es, fmt.Errorf("expected type of %s to be string", k)) + return + } + + for _, str := range invalid { + if v == str || (ignoreCase && strings.ToLower(v) == strings.ToLower(str)) { + es = append(es, fmt.Errorf("expected %s to not match any of %v, got %s", k, invalid, v)) + return + } + } + + return + } +}