Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

batch serviceusage reads #4854

Merged
merged 1 commit into from
Nov 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion google/batcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"log"
"sync"
"time"

"github.com/hashicorp/errwrap"
)

const defaultBatchSendIntervalSec = 10
Expand Down Expand Up @@ -154,7 +156,8 @@ func (b *RequestBatcher) SendRequestWithTimeout(batchKey string, request *BatchR
select {
case resp := <-respCh:
if resp.err != nil {
return nil, fmt.Errorf("Batch %q for request %q returned error: %v", batchKey, request.DebugId, resp.err)
// use wrapf so we can potentially extract the original error type
return nil, errwrap.Wrapf(fmt.Sprintf("Batch %q for request %q returned error: {{err}}", batchKey, request.DebugId), resp.err)
}
return resp.body, nil
case <-ctx.Done():
Expand Down
41 changes: 7 additions & 34 deletions google/resource_google_project_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ package google

import (
"fmt"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"google.golang.org/api/googleapi"
"google.golang.org/api/serviceusage/v1"
"log"
"strings"
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"google.golang.org/api/serviceusage/v1"
)

var ignoredProjectServices = []string{"dataproc-control.googleapis.com", "source.googleapis.com", "stackdriverprovisioning.googleapis.com"}
Expand Down Expand Up @@ -138,11 +137,13 @@ func resourceGoogleProjectServiceRead(d *schema.ResourceData, meta interface{})
}
srv := d.Get("service").(string)

enabled, err := isServiceEnabled(project, srv, config)
servicesRaw, err := BatchRequestReadServices(project, d, config)
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Project Service %s", d.Id()))
}
if enabled {
servicesList := servicesRaw.(map[string]struct{})

if _, ok := servicesList[srv]; ok {
d.Set("project", project)
d.Set("service", srv)
return nil
Expand Down Expand Up @@ -184,34 +185,6 @@ func resourceGoogleProjectServiceUpdate(d *schema.ResourceData, meta interface{}
return nil
}

// Retrieve enablement state for a given project's service
func isServiceEnabled(project, serviceName string, config *Config) (bool, error) {
// Verify project for services still exists
p, err := config.clientResourceManager.Projects.Get(project).Do()
if err != nil {
return false, err
}
if p.LifecycleState == "DELETE_REQUESTED" {
// Construct a 404 error for handleNotFoundError
return false, &googleapi.Error{
Code: 404,
Message: "Project deletion was requested",
}
}

resourceName := fmt.Sprintf("projects/%s/services/%s", project, serviceName)
var srv *serviceusage.GoogleApiServiceusageV1Service
err = retryTime(func() error {
var currErr error
srv, currErr = config.clientServiceUsage.Services.Get(resourceName).Do()
return currErr
}, 10)
if err != nil {
return false, errwrap.Wrapf(fmt.Sprintf("Failed to list enabled services for project %s: {{err}}", project), err)
}
return srv.State == "ENABLED", nil
}

// Disables a project service.
func disableServiceUsageProjectService(service, project string, d *schema.ResourceData, config *Config, disableDependentServices bool) error {
err := retryTimeDuration(func() error {
Expand Down
23 changes: 23 additions & 0 deletions google/serviceusage_batching.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

const (
batchKeyTmplServiceUsageEnableServices = "project/%s/services:batchEnable"
batchKeyTmplServiceUsageListServices = "project/%s/services"
)

// BatchRequestEnableServices can be used to batch requests to enable services
Expand Down Expand Up @@ -53,6 +54,22 @@ func BatchRequestEnableServices(services map[string]struct{}, project string, d
return err
}

func BatchRequestReadServices(project string, d *schema.ResourceData, config *Config) (interface{}, error) {
req := &BatchRequest{
ResourceName: project,
Body: nil,
// Use empty CombineF since the request is exactly the same no matter how many services we read.
CombineF: func(body interface{}, toAdd interface{}) (interface{}, error) { return nil, nil },
SendF: sendListServices(config, d.Timeout(schema.TimeoutRead)),
DebugId: fmt.Sprintf("List Project Services %s", project),
}

return config.requestBatcherServiceUsage.SendRequestWithTimeout(
fmt.Sprintf(batchKeyTmplServiceUsageListServices, project),
req,
d.Timeout(schema.TimeoutRead))
}

func combineServiceUsageServicesBatches(srvsRaw interface{}, toAddRaw interface{}) (interface{}, error) {
srvs, ok := srvsRaw.([]string)
if !ok {
Expand All @@ -75,3 +92,9 @@ func sendBatchFuncEnableServices(config *Config, timeout time.Duration) batcherS
return nil, enableServiceUsageProjectServices(toEnable, project, config, timeout)
}
}

func sendListServices(config *Config, timeout time.Duration) batcherSendFunc {
return func(project string, _ interface{}) (interface{}, error) {
return listCurrentlyEnabledServices(project, config, timeout)
}
}