terraform-provider-google/google/resource_logging_exclusion.go
Christoph Tavan 0bcb01266c Add google_logging_project_exclusion resource (#990)
Adds support for log exclusions in billingAccounts, organizations,
folders and projects, see:
https://cloud.google.com/logging/docs/exclusions

```
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./google -v -run=Exclusion -timeout 120m
=== RUN   TestAccLoggingBillingAccountExclusion_basic
=== PAUSE TestAccLoggingBillingAccountExclusion_basic
=== RUN   TestAccLoggingBillingAccountExclusion_update
=== PAUSE TestAccLoggingBillingAccountExclusion_update
=== RUN   TestAccLoggingFolderExclusion_basic
=== PAUSE TestAccLoggingFolderExclusion_basic
=== RUN   TestAccLoggingFolderExclusion_folderAcceptsFullFolderPath
=== PAUSE TestAccLoggingFolderExclusion_folderAcceptsFullFolderPath
=== RUN   TestAccLoggingFolderExclusion_update
=== PAUSE TestAccLoggingFolderExclusion_update
=== RUN   TestAccLoggingOrganizationExclusion_basic
=== PAUSE TestAccLoggingOrganizationExclusion_basic
=== RUN   TestAccLoggingOrganizationExclusion_update
=== PAUSE TestAccLoggingOrganizationExclusion_update
=== RUN   TestAccLoggingProjectExclusion_basic
=== PAUSE TestAccLoggingProjectExclusion_basic
=== RUN   TestAccLoggingProjectExclusion_disablePreservesFilter
=== PAUSE TestAccLoggingProjectExclusion_disablePreservesFilter
=== RUN   TestAccLoggingProjectExclusion_update
=== PAUSE TestAccLoggingProjectExclusion_update
=== CONT  TestAccLoggingBillingAccountExclusion_basic
=== CONT  TestAccLoggingOrganizationExclusion_update
=== CONT  TestAccLoggingProjectExclusion_update
=== CONT  TestAccLoggingFolderExclusion_folderAcceptsFullFolderPath
=== CONT  TestAccLoggingOrganizationExclusion_basic
--- PASS: TestAccLoggingProjectExclusion_update (3.60s)
--- PASS: TestAccLoggingOrganizationExclusion_update (4.40s)
=== CONT  TestAccLoggingFolderExclusion_update
--- PASS: TestAccLoggingOrganizationExclusion_basic (1.90s)
=== CONT  TestAccLoggingFolderExclusion_basic
--- PASS: TestAccLoggingBillingAccountExclusion_basic (6.21s)
=== CONT  TestAccLoggingBillingAccountExclusion_update
--- PASS: TestAccLoggingBillingAccountExclusion_update (5.90s)
=== CONT  TestAccLoggingProjectExclusion_disablePreservesFilter
--- PASS: TestAccLoggingProjectExclusion_disablePreservesFilter (3.90s)
=== CONT  TestAccLoggingProjectExclusion_basic
--- PASS: TestAccLoggingFolderExclusion_folderAcceptsFullFolderPath (16.67s)
--- PASS: TestAccLoggingProjectExclusion_basic (1.96s)
--- PASS: TestAccLoggingFolderExclusion_basic (15.30s)
--- PASS: TestAccLoggingFolderExclusion_update (18.35s)
PASS
ok  	github.com/terraform-providers/terraform-provider-google/google	22.810s
```
2018-05-18 08:55:04 -07:00

266 lines
8.0 KiB
Go

package google
import (
"fmt"
"regexp"
"strings"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/logging/v2"
)
var LoggingExclusionBaseSchema = map[string]*schema.Schema{
"filter": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"disabled": {
Type: schema.TypeBool,
Optional: true,
},
}
func ResourceLoggingExclusion(parentSpecificSchema map[string]*schema.Schema, newUpdaterFunc newResourceLoggingExclusionUpdaterFunc, resourceIdParser resourceIdParserFunc) *schema.Resource {
return &schema.Resource{
Create: resourceLoggingExclusionCreate(newUpdaterFunc),
Read: resourceLoggingExclusionRead(newUpdaterFunc),
Update: resourceLoggingExclusionUpdate(newUpdaterFunc),
Delete: resourceLoggingExclusionDelete(newUpdaterFunc),
Importer: &schema.ResourceImporter{
State: resourceLoggingExclusionImportState(resourceIdParser),
},
Schema: mergeSchemas(LoggingExclusionBaseSchema, parentSpecificSchema),
}
}
func resourceLoggingExclusionCreate(newUpdaterFunc newResourceLoggingExclusionUpdaterFunc) schema.CreateFunc {
return func(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
updater, err := newUpdaterFunc(d, config)
if err != nil {
return err
}
id, exclusion := expandResourceLoggingExclusion(d, updater.GetResourceType(), updater.GetResourceId())
err = updater.CreateLoggingExclusion(id.parent(), exclusion)
if err != nil {
return err
}
d.SetId(id.canonicalId())
return resourceLoggingExclusionRead(newUpdaterFunc)(d, meta)
}
}
func resourceLoggingExclusionRead(newUpdaterFunc newResourceLoggingExclusionUpdaterFunc) schema.ReadFunc {
return func(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
updater, err := newUpdaterFunc(d, config)
if err != nil {
return err
}
exclusion, err := updater.ReadLoggingExclusion(d.Id())
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Logging Exclusion %s", d.Get("name").(string)))
}
flattenResourceLoggingExclusion(d, exclusion)
if updater.GetResourceType() == "projects" {
d.Set("project", updater.GetResourceId())
}
return nil
}
}
func resourceLoggingExclusionUpdate(newUpdaterFunc newResourceLoggingExclusionUpdaterFunc) schema.UpdateFunc {
return func(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
updater, err := newUpdaterFunc(d, config)
if err != nil {
return err
}
exclusion, updateMask := expandResourceLoggingExclusionForUpdate(d)
err = updater.UpdateLoggingExclusion(d.Id(), exclusion, updateMask)
if err != nil {
return err
}
return resourceLoggingExclusionRead(newUpdaterFunc)(d, meta)
}
}
func resourceLoggingExclusionDelete(newUpdaterFunc newResourceLoggingExclusionUpdaterFunc) schema.DeleteFunc {
return func(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
updater, err := newUpdaterFunc(d, config)
if err != nil {
return err
}
err = updater.DeleteLoggingExclusion(d.Id())
if err != nil {
return err
}
d.SetId("")
return nil
}
}
func resourceLoggingExclusionImportState(resourceIdParser resourceIdParserFunc) schema.StateFunc {
return func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
err := resourceIdParser(d, config)
if err != nil {
return nil, err
}
return []*schema.ResourceData{d}, nil
}
}
func expandResourceLoggingExclusion(d *schema.ResourceData, resourceType, resourceId string) (LoggingExclusionId, *logging.LogExclusion) {
id := LoggingExclusionId{
resourceType: resourceType,
resourceId: resourceId,
name: d.Get("name").(string),
}
exclusion := logging.LogExclusion{
Name: d.Get("name").(string),
Description: d.Get("description").(string),
Filter: d.Get("filter").(string),
Disabled: d.Get("disabled").(bool),
}
return id, &exclusion
}
func flattenResourceLoggingExclusion(d *schema.ResourceData, exclusion *logging.LogExclusion) {
d.Set("name", exclusion.Name)
d.Set("description", exclusion.Description)
d.Set("filter", exclusion.Filter)
d.Set("disabled", exclusion.Disabled)
}
func expandResourceLoggingExclusionForUpdate(d *schema.ResourceData) (*logging.LogExclusion, string) {
// Can update description/filter/disabled right now.
exclusion := logging.LogExclusion{}
var updateMaskArr []string
if d.HasChange("description") {
exclusion.Description = d.Get("description").(string)
exclusion.ForceSendFields = append(exclusion.ForceSendFields, "Description")
updateMaskArr = append(updateMaskArr, "description")
}
if d.HasChange("filter") {
exclusion.Filter = d.Get("filter").(string)
exclusion.ForceSendFields = append(exclusion.ForceSendFields, "Filter")
updateMaskArr = append(updateMaskArr, "filter")
}
if d.HasChange("disabled") {
exclusion.Disabled = d.Get("disabled").(bool)
exclusion.ForceSendFields = append(exclusion.ForceSendFields, "Disabled")
updateMaskArr = append(updateMaskArr, "disabled")
}
updateMask := strings.Join(updateMaskArr, ",")
return &exclusion, updateMask
}
// The ResourceLoggingExclusionUpdater interface is implemented for each GCP
// resource supporting log exclusions.
//
// Implementations should keep track of the resource identifier.
type ResourceLoggingExclusionUpdater interface {
CreateLoggingExclusion(parent string, exclusion *logging.LogExclusion) error
ReadLoggingExclusion(id string) (*logging.LogExclusion, error)
UpdateLoggingExclusion(id string, exclusion *logging.LogExclusion, updateMask string) error
DeleteLoggingExclusion(id string) error
GetResourceType() string
// Returns the unique resource identifier.
GetResourceId() string
// Textual description of this resource to be used in error message.
// The description should include the unique resource identifier.
DescribeResource() string
}
type newResourceLoggingExclusionUpdaterFunc func(d *schema.ResourceData, config *Config) (ResourceLoggingExclusionUpdater, error)
// loggingExclusionResourceTypes contains all the possible Stackdriver Logging resource types. Used to parse ids safely.
var loggingExclusionResourceTypes = []string{
"billingAccounts",
"folders",
"organizations",
"projects",
}
// LoggingExclusionId represents the parts that make up the canonical id used within terraform for a logging resource.
type LoggingExclusionId struct {
resourceType string
resourceId string
name string
}
// loggingExclusionIdRegex matches valid logging exclusion canonical ids
var loggingExclusionIdRegex = regexp.MustCompile("(.+)/(.+)/exclusions/(.+)")
// canonicalId returns the LoggingExclusionId as the canonical id used within terraform.
func (l LoggingExclusionId) canonicalId() string {
return fmt.Sprintf("%s/%s/exclusions/%s", l.resourceType, l.resourceId, l.name)
}
// parent returns the "parent-level" resource that the exclusion is in (e.g. `folders/foo` for id `folders/foo/exclusions/bar`)
func (l LoggingExclusionId) parent() string {
return fmt.Sprintf("%s/%s", l.resourceType, l.resourceId)
}
// parseLoggingExclusionId parses a canonical id into a LoggingExclusionId, or returns an error on failure.
func parseLoggingExclusionId(id string) (*LoggingExclusionId, error) {
parts := loggingExclusionIdRegex.FindStringSubmatch(id)
if parts == nil {
return nil, fmt.Errorf("unable to parse logging exclusion id %#v", id)
}
// If our resourceType is not a valid logging exclusion resource type, complain loudly
validLoggingExclusionResourceType := false
for _, v := range loggingExclusionResourceTypes {
if v == parts[1] {
validLoggingExclusionResourceType = true
break
}
}
if !validLoggingExclusionResourceType {
return nil, fmt.Errorf("Logging resource type %s is not valid. Valid resource types: %#v", parts[1],
loggingExclusionResourceTypes)
}
return &LoggingExclusionId{
resourceType: parts[1],
resourceId: parts[2],
name: parts[3],
}, nil
}