diff --git a/google-beta/resource_pubsub_subscription.go b/google-beta/resource_pubsub_subscription.go index 5175402453..7aedd4eb7e 100644 --- a/google-beta/resource_pubsub_subscription.go +++ b/google-beta/resource_pubsub_subscription.go @@ -26,6 +26,18 @@ import ( "github.com/hashicorp/terraform/helper/schema" ) +func comparePubsubSubscriptionExpirationPolicy(_, old, new string, _ *schema.ResourceData) bool { + trimmedNew := strings.TrimLeft(new, "0") + trimmedOld := strings.TrimLeft(old, "0") + if strings.Contains(trimmedNew, ".") { + trimmedNew = strings.TrimRight(strings.TrimSuffix(trimmedNew, "s"), "0") + "s" + } + if strings.Contains(trimmedOld, ".") { + trimmedOld = strings.TrimRight(strings.TrimSuffix(trimmedOld, "s"), "0") + "s" + } + return trimmedNew == trimmedOld +} + func resourcePubsubSubscription() *schema.Resource { return &schema.Resource{ Create: resourcePubsubSubscriptionCreate, @@ -61,6 +73,21 @@ func resourcePubsubSubscription() *schema.Resource { Computed: true, Optional: true, }, + "expiration_policy": { + Type: schema.TypeList, + Computed: true, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ttl": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: comparePubsubSubscriptionExpirationPolicy, + }, + }, + }, + }, "labels": { Type: schema.TypeMap, Optional: true, @@ -153,6 +180,12 @@ func resourcePubsubSubscriptionCreate(d *schema.ResourceData, meta interface{}) } else if v, ok := d.GetOkExists("retain_acked_messages"); !isEmptyValue(reflect.ValueOf(retainAckedMessagesProp)) && (ok || !reflect.DeepEqual(v, retainAckedMessagesProp)) { obj["retainAckedMessages"] = retainAckedMessagesProp } + expirationPolicyProp, err := expandPubsubSubscriptionExpirationPolicy(d.Get("expiration_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("expiration_policy"); !isEmptyValue(reflect.ValueOf(expirationPolicyProp)) && (ok || !reflect.DeepEqual(v, expirationPolicyProp)) { + obj["expirationPolicy"] = expirationPolicyProp + } url, err := replaceVars(d, config, "https://pubsub.googleapis.com/v1/projects/{{project}}/subscriptions/{{name}}") if err != nil { @@ -224,6 +257,9 @@ func resourcePubsubSubscriptionRead(d *schema.ResourceData, meta interface{}) er if err := d.Set("retain_acked_messages", flattenPubsubSubscriptionRetainAckedMessages(res["retainAckedMessages"], d)); err != nil { return fmt.Errorf("Error reading Subscription: %s", err) } + if err := d.Set("expiration_policy", flattenPubsubSubscriptionExpirationPolicy(res["expirationPolicy"], d)); err != nil { + return fmt.Errorf("Error reading Subscription: %s", err) + } return nil } @@ -262,6 +298,12 @@ func resourcePubsubSubscriptionUpdate(d *schema.ResourceData, meta interface{}) } else if v, ok := d.GetOkExists("retain_acked_messages"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, retainAckedMessagesProp)) { obj["retainAckedMessages"] = retainAckedMessagesProp } + expirationPolicyProp, err := expandPubsubSubscriptionExpirationPolicy(d.Get("expiration_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("expiration_policy"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, expirationPolicyProp)) { + obj["expirationPolicy"] = expirationPolicyProp + } obj, err = resourcePubsubSubscriptionUpdateEncoder(d, meta, obj) if err != nil { @@ -295,6 +337,10 @@ func resourcePubsubSubscriptionUpdate(d *schema.ResourceData, meta interface{}) if d.HasChange("retain_acked_messages") { updateMask = append(updateMask, "retainAckedMessages") } + + if d.HasChange("expiration_policy") { + updateMask = append(updateMask, "expirationPolicy") + } // updateMask is a URL parameter but not present in the schema, so replaceVars // won't set it url, err = addQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) @@ -404,6 +450,23 @@ func flattenPubsubSubscriptionRetainAckedMessages(v interface{}, d *schema.Resou return v } +func flattenPubsubSubscriptionExpirationPolicy(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["ttl"] = + flattenPubsubSubscriptionExpirationPolicyTtl(original["ttl"], d) + return []interface{}{transformed} +} +func flattenPubsubSubscriptionExpirationPolicyTtl(v interface{}, d *schema.ResourceData) interface{} { + return v +} + func expandPubsubSubscriptionName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { project, err := getProject(d, config) if err != nil { @@ -511,6 +574,29 @@ func expandPubsubSubscriptionRetainAckedMessages(v interface{}, d TerraformResou return v, nil } +func expandPubsubSubscriptionExpirationPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTtl, err := expandPubsubSubscriptionExpirationPolicyTtl(original["ttl"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTtl); val.IsValid() && !isEmptyValue(val) { + transformed["ttl"] = transformedTtl + } + + return transformed, nil +} + +func expandPubsubSubscriptionExpirationPolicyTtl(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func resourcePubsubSubscriptionUpdateEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { newObj := make(map[string]interface{}) newObj["subscription"] = obj diff --git a/google-beta/resource_pubsub_subscription_generated_test.go b/google-beta/resource_pubsub_subscription_generated_test.go index 88c858dae1..b64b1ae03b 100644 --- a/google-beta/resource_pubsub_subscription_generated_test.go +++ b/google-beta/resource_pubsub_subscription_generated_test.go @@ -67,6 +67,10 @@ resource "google_pubsub_subscription" "example" { retain_acked_messages = true ack_deadline_seconds = 20 + + expiration_policy { + ttl = "300000.5s" + } } `, context) } diff --git a/website/docs/r/pubsub_subscription.html.markdown b/website/docs/r/pubsub_subscription.html.markdown index bb8ed0dfe5..2f776dcec7 100644 --- a/website/docs/r/pubsub_subscription.html.markdown +++ b/website/docs/r/pubsub_subscription.html.markdown @@ -85,6 +85,10 @@ resource "google_pubsub_subscription" "example" { retain_acked_messages = true ack_deadline_seconds = 20 + + expiration_policy { + ttl = "300000.5s" + } } ``` ## Example Usage - Pubsub Subscription Different Project @@ -165,6 +169,15 @@ The following arguments are supported: messages are not expunged from the subscription's backlog, even if they are acknowledged, until they fall out of the messageRetentionDuration window. + +* `expiration_policy` - + (Optional) + A policy that specifies the conditions for this subscription's expiration. + A subscription is considered active as long as any connected subscriber + is successfully consuming messages from the subscription or is issuing + operations on the subscription. If expirationPolicy is not set, a default + policy with ttl of 31 days will be used. The minimum allowed value for + expirationPolicy.ttl is 1 day. Structure is documented below. * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. @@ -198,6 +211,18 @@ The `push_config` block supports: - v1beta1: uses the push format defined in the v1beta1 Pub/Sub API. - v1 or v1beta2: uses the push format defined in the v1 Pub/Sub API. +The `expiration_policy` block supports: + +* `ttl` - + (Optional) + Specifies the "time-to-live" duration for an associated resource. The + resource expires if it is not active for a period of ttl. The definition + of "activity" depends on the type of the associated resource. The minimum + and maximum allowed values for ttl depend on the type of the associated + resource, as well. If ttl is not set, the associated resource never expires. + A duration in seconds with up to nine fractional digits, terminated by 's'. + Example - "3.5s". + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: