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

Allow partial URIs in Cloud Functions event_trigger.resource #4201

Merged
merged 1 commit into from
Aug 12, 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
76 changes: 38 additions & 38 deletions google/resource_cloudfunctions_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ func validateResourceCloudFunctionsFunctionName(v interface{}, k string) (ws []s
return
}

// based on compareSelfLinkOrResourceName, but less reusable and allows multi-/
// strings in the new state (config) part
func compareSelfLinkOrResourceNameWithMultipleParts(_, old, new string, _ *schema.ResourceData) bool {
return strings.HasSuffix(old, new)
}

func resourceCloudFunctionsFunction() *schema.Resource {
return &schema.Resource{
Create: resourceCloudFunctionsCreate,
Expand Down Expand Up @@ -237,8 +243,9 @@ func resourceCloudFunctionsFunction() *schema.Resource {
Required: true,
},
"resource": {
Type: schema.TypeString,
Required: true,
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: compareSelfLinkOrResourceNameWithMultipleParts,
},
"failure_policy": {
Type: schema.TypeList,
Expand Down Expand Up @@ -562,26 +569,38 @@ func expandEventTrigger(configured []interface{}, project string) *cloudfunction

data := configured[0].(map[string]interface{})
eventType := data["event_type"].(string)
shape := ""
switch {
case strings.HasPrefix(eventType, "google.storage.object."):
shape = "projects/%s/buckets/%s"
case strings.HasPrefix(eventType, "google.pubsub.topic."):
shape = "projects/%s/topics/%s"
// Legacy style triggers
case strings.HasPrefix(eventType, "providers/cloud.storage/eventTypes/"):
shape = "projects/%s/buckets/%s"
case strings.HasPrefix(eventType, "providers/cloud.pubsub/eventTypes/"):
shape = "projects/%s/topics/%s"
case strings.HasPrefix(eventType, "providers/cloud.firestore/eventTypes/"):
// Firestore doesn't not yet support multiple databases, so "(default)" is assumed.
// https://cloud.google.com/functions/docs/calling/cloud-firestore#deploying_your_function
shape = "projects/%s/databases/(default)/documents/%s"
resource := data["resource"].(string)

// if resource starts with "projects/", we can reasonably assume it's a
// partial URI. Otherwise, it's a shortname. Construct a partial URI based
// on the event type if so.
if !strings.HasPrefix(resource, "projects/") {
shape := ""
switch {
case strings.HasPrefix(eventType, "google.storage.object."):
shape = "projects/%s/buckets/%s"
case strings.HasPrefix(eventType, "google.pubsub.topic."):
shape = "projects/%s/topics/%s"
// Legacy style triggers
case strings.HasPrefix(eventType, "providers/cloud.storage/eventTypes/"):
// Note that this is an uncommon way to refer to buckets; normally,
// you'd use to the global URL of the bucket and not the project
// scoped one.
shape = "projects/%s/buckets/%s"
case strings.HasPrefix(eventType, "providers/cloud.pubsub/eventTypes/"):
shape = "projects/%s/topics/%s"
case strings.HasPrefix(eventType, "providers/cloud.firestore/eventTypes/"):
// Firestore doesn't not yet support multiple databases, so "(default)" is assumed.
// https://cloud.google.com/functions/docs/calling/cloud-firestore#deploying_your_function
shape = "projects/%s/databases/(default)/documents/%s"
}

resource = fmt.Sprintf(shape, project, resource)
}

return &cloudfunctions.EventTrigger{
EventType: eventType,
Resource: fmt.Sprintf(shape, project, data["resource"].(string)),
Resource: resource,
FailurePolicy: expandFailurePolicy(data["failure_policy"].([]interface{})),
}
}
Expand All @@ -592,28 +611,9 @@ func flattenEventTrigger(eventTrigger *cloudfunctions.EventTrigger) []map[string
return result
}

resource := ""
switch {
case strings.HasPrefix(eventTrigger.EventType, "google.storage.object."):
resource = GetResourceNameFromSelfLink(eventTrigger.Resource)
case strings.HasPrefix(eventTrigger.EventType, "google.pubsub.topic."):
resource = GetResourceNameFromSelfLink(eventTrigger.Resource)
// Legacy style triggers
case strings.HasPrefix(eventTrigger.EventType, "providers/cloud.storage/eventTypes/"):
resource = GetResourceNameFromSelfLink(eventTrigger.Resource)
case strings.HasPrefix(eventTrigger.EventType, "providers/cloud.pubsub/eventTypes/"):
resource = GetResourceNameFromSelfLink(eventTrigger.Resource)
case strings.HasPrefix(eventTrigger.EventType, "providers/cloud.firestore/eventTypes/"):
// Simply taking the substring after the last "/" is not sufficient for firestore as resources may have slashes.
// For the eventTrigger.Resource "projects/my-project/databases/(default)/documents/messages/{messageId}" we extract
// the resource "messages/{messageId}" by taking the everything after the 5th "/"
parts := strings.SplitN(eventTrigger.Resource, "/", 6)
resource = parts[len(parts)-1]
}

result = append(result, map[string]interface{}{
"event_type": eventTrigger.EventType,
"resource": resource,
"resource": eventTrigger.Resource,
"failure_policy": flattenFailurePolicy(eventTrigger.FailurePolicy),
})

Expand Down
4 changes: 3 additions & 1 deletion google/resource_cloudfunctions_function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,8 @@ resource "google_cloudfunctions_function" "function" {
func testAccCloudFunctionsFunction_bucket(functionName string, bucketName string,
zipFilePath string) string {
return fmt.Sprintf(`
data "google_client_config" "current" {}

resource "google_storage_bucket" "bucket" {
name = "%s"
}
Expand All @@ -599,7 +601,7 @@ resource "google_cloudfunctions_function" "function" {
entry_point = "helloGCS"
event_trigger {
event_type = "google.storage.object.finalize"
resource = "${google_storage_bucket.bucket.name}"
resource = "projects/${data.google_client_config.current.project}/buckets/${google_storage_bucket.bucket.name}"
failure_policy {
retry = true
}
Expand Down
3 changes: 2 additions & 1 deletion website/docs/r/cloudfunctions_function.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ Cloud Storage, Cloud Pub/Sub and Cloud Firestore triggers are supported at this
Legacy triggers are supported, such as `"providers/cloud.storage/eventTypes/object.change"`,
`"providers/cloud.pubsub/eventTypes/topic.publish"` and `"providers/cloud.firestore/eventTypes/document.create"`.

* `resource` - (Required) Required. The name of the resource from which to observe events, for example, `"myBucket"`
* `resource` - (Required) Required. The name or partial URI of the resource from
which to observe events. For example, `"myBucket"` or `"projects/my-project/topics/my-topic"`

* `failure_policy` - (Optional) Specifies policy for failed executions. Structure is documented below.

Expand Down