Generate Pubsub Topics/Subscriptions with MM (+add labels) (#3043)

<!-- This change is generated by MagicModules. -->
/cc @drebes
This commit is contained in:
The Magician 2019-02-19 15:10:44 -08:00 committed by Riley Karson
parent 5a4bb8f299
commit 2950923ee6
11 changed files with 969 additions and 300 deletions

View File

@ -137,6 +137,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
GeneratedComputeResourcesMap,
GeneratedCloudBuildResourcesMap,
GeneratedDnsResourcesMap,
GeneratedPubsubResourcesMap,
GeneratedRedisResourcesMap,
GeneratedResourceManagerResourcesMap,
GeneratedSourceRepoResourcesMap,
@ -228,11 +229,9 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
"google_project_organization_policy": resourceGoogleProjectOrganizationPolicy(),
"google_project_usage_export_bucket": resourceProjectUsageBucket(),
"google_project_services": resourceGoogleProjectServices(),
"google_pubsub_topic": resourcePubsubTopic(),
"google_pubsub_topic_iam_binding": ResourceIamBindingWithImport(IamPubsubTopicSchema, NewPubsubTopicIamUpdater, PubsubTopicIdParseFunc),
"google_pubsub_topic_iam_member": ResourceIamMemberWithImport(IamPubsubTopicSchema, NewPubsubTopicIamUpdater, PubsubTopicIdParseFunc),
"google_pubsub_topic_iam_policy": ResourceIamPolicyWithImport(IamPubsubTopicSchema, NewPubsubTopicIamUpdater, PubsubTopicIdParseFunc),
"google_pubsub_subscription": resourcePubsubSubscription(),
"google_pubsub_subscription_iam_binding": ResourceIamBindingWithImport(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
"google_pubsub_subscription_iam_member": ResourceIamMemberWithImport(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),
"google_pubsub_subscription_iam_policy": ResourceIamPolicyWithImport(IamPubsubSubscriptionSchema, NewPubsubSubscriptionIamUpdater, PubsubSubscriptionIdParseFunc),

View File

@ -0,0 +1,22 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google
import "github.com/hashicorp/terraform/helper/schema"
var GeneratedPubsubResourcesMap = map[string]*schema.Resource{
"google_pubsub_topic": resourcePubsubTopic(),
"google_pubsub_subscription": resourcePubsubSubscription(),
}

32
google/pubsub_utils.go Normal file
View File

@ -0,0 +1,32 @@
package google
import (
"fmt"
"regexp"
"github.com/hashicorp/terraform/helper/schema"
)
func comparePubsubSubscriptionBasename(_, old, new string, _ *schema.ResourceData) bool {
if GetResourceNameFromSelfLink(old) == GetResourceNameFromSelfLink(new) {
return true
}
return false
}
func getComputedSubscriptionName(project, subscription string) string {
match, _ := regexp.MatchString("projects\\/.*\\/subscriptions\\/.*", subscription)
if match {
return subscription
}
return fmt.Sprintf("projects/%s/subscriptions/%s", project, subscription)
}
func getComputedTopicName(project, topic string) string {
match, _ := regexp.MatchString("projects\\/.*\\/topics\\/.*", topic)
if match {
return topic
}
return fmt.Sprintf("projects/%s/topics/%s", project, topic)
}

View File

@ -1,11 +1,29 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google
import (
"fmt"
"log"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/pubsub/v1"
"regexp"
)
func resourcePubsubSubscription() *schema.Resource {
@ -16,61 +34,66 @@ func resourcePubsubSubscription() *schema.Resource {
Delete: resourcePubsubSubscriptionDelete,
Importer: &schema.ResourceImporter{
State: resourcePubsubSubscriptionStateImporter,
State: resourcePubsubSubscriptionImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(240 * time.Second),
Update: schema.DefaultTimeout(240 * time.Second),
Delete: schema.DefaultTimeout(240 * time.Second),
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: comparePubsubSubscriptionBasename,
},
"topic": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: compareSelfLinkOrResourceName,
},
"ack_deadline_seconds": {
Type: schema.TypeInt,
Computed: true,
Optional: true,
Computed: true,
ForceNew: true,
},
"project": {
Type: schema.TypeString,
"labels": {
Type: schema.TypeMap,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"path": {
Type: schema.TypeString,
Computed: true,
},
"push_config": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"push_endpoint": {
Type: schema.TypeString,
Required: true,
},
"attributes": {
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"push_endpoint": {
Type: schema.TypeString,
Required: true,
},
},
},
},
"path": {
Type: schema.TypeString,
Computed: true,
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
},
}
}
@ -78,74 +101,102 @@ func resourcePubsubSubscription() *schema.Resource {
func resourcePubsubSubscriptionCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
obj := make(map[string]interface{})
nameProp, err := expandPubsubSubscriptionName(d.Get("name"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
obj["name"] = nameProp
}
topicProp, err := expandPubsubSubscriptionTopic(d.Get("topic"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("topic"); !isEmptyValue(reflect.ValueOf(topicProp)) && (ok || !reflect.DeepEqual(v, topicProp)) {
obj["topic"] = topicProp
}
labelsProp, err := expandPubsubSubscriptionLabels(d.Get("labels"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
obj["labels"] = labelsProp
}
pushConfigProp, err := expandPubsubSubscriptionPushConfig(d.Get("push_config"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("push_config"); !isEmptyValue(reflect.ValueOf(pushConfigProp)) && (ok || !reflect.DeepEqual(v, pushConfigProp)) {
obj["pushConfig"] = pushConfigProp
}
ackDeadlineSecondsProp, err := expandPubsubSubscriptionAckDeadlineSeconds(d.Get("ack_deadline_seconds"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("ack_deadline_seconds"); !isEmptyValue(reflect.ValueOf(ackDeadlineSecondsProp)) && (ok || !reflect.DeepEqual(v, ackDeadlineSecondsProp)) {
obj["ackDeadlineSeconds"] = ackDeadlineSecondsProp
}
url, err := replaceVars(d, config, "https://pubsub.googleapis.com/v1/projects/{{project}}/subscriptions/{{name}}")
if err != nil {
return err
}
name := getComputedSubscriptionName(project, d.Get("name").(string))
computed_topic_name := getComputedTopicName(project, d.Get("topic").(string))
// process optional parameters
var ackDeadlineSeconds int64
ackDeadlineSeconds = 10
if v, ok := d.GetOk("ack_deadline_seconds"); ok {
ackDeadlineSeconds = int64(v.(int))
}
subscription := &pubsub.Subscription{
AckDeadlineSeconds: ackDeadlineSeconds,
Topic: computed_topic_name,
PushConfig: expandPubsubSubscriptionPushConfig(d.Get("push_config").([]interface{})),
}
call := config.clientPubsub.Projects.Subscriptions.Create(name, subscription)
res, err := call.Do()
log.Printf("[DEBUG] Creating new Subscription: %#v", obj)
res, err := sendRequestWithTimeout(config, "PUT", url, obj, d.Timeout(schema.TimeoutCreate))
if err != nil {
return err
return fmt.Errorf("Error creating Subscription: %s", err)
}
d.SetId(res.Name)
// Store the ID now
id, err := replaceVars(d, config, "projects/{{project}}/subscriptions/{{name}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
log.Printf("[DEBUG] Finished creating Subscription %q: %#v", d.Id(), res)
return resourcePubsubSubscriptionRead(d, meta)
}
func getComputedTopicName(project, topic string) string {
match, _ := regexp.MatchString("projects\\/.*\\/topics\\/.*", topic)
if match {
return topic
}
return fmt.Sprintf("projects/%s/topics/%s", project, topic)
}
func getComputedSubscriptionName(project, subscription string) string {
match, _ := regexp.MatchString("projects\\/.*\\/subscriptions\\/.*", subscription)
if match {
return subscription
}
return fmt.Sprintf("projects/%s/subscriptions/%s", project, subscription)
}
func resourcePubsubSubscriptionRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
url, err := replaceVars(d, config, "https://pubsub.googleapis.com/v1/projects/{{project}}/subscriptions/{{name}}")
if err != nil {
return err
}
name := d.Id()
subscription, err := config.clientPubsub.Projects.Subscriptions.Get(name).Do()
res, err := sendRequest(config, "GET", url, nil)
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Pubsub Subscription %q", name))
return handleNotFoundError(err, d, fmt.Sprintf("PubsubSubscription %q", d.Id()))
}
d.Set("name", GetResourceNameFromSelfLink(subscription.Name))
d.Set("topic", subscription.Topic)
d.Set("ack_deadline_seconds", subscription.AckDeadlineSeconds)
d.Set("path", subscription.Name)
d.Set("push_config", flattenPubsubSubscriptionPushConfig(subscription.PushConfig))
d.Set("project", project)
res, err = resourcePubsubSubscriptionDecoder(d, meta, res)
if err != nil {
return err
}
project, err := getProject(d, config)
if err != nil {
return err
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading Subscription: %s", err)
}
if err := d.Set("name", flattenPubsubSubscriptionName(res["name"], d)); err != nil {
return fmt.Errorf("Error reading Subscription: %s", err)
}
if err := d.Set("topic", flattenPubsubSubscriptionTopic(res["topic"], d)); err != nil {
return fmt.Errorf("Error reading Subscription: %s", err)
}
if err := d.Set("labels", flattenPubsubSubscriptionLabels(res["labels"], d)); err != nil {
return fmt.Errorf("Error reading Subscription: %s", err)
}
if err := d.Set("push_config", flattenPubsubSubscriptionPushConfig(res["pushConfig"], d)); err != nil {
return fmt.Errorf("Error reading Subscription: %s", err)
}
if err := d.Set("ack_deadline_seconds", flattenPubsubSubscriptionAckDeadlineSeconds(res["ackDeadlineSeconds"], d)); err != nil {
return fmt.Errorf("Error reading Subscription: %s", err)
}
return nil
}
@ -153,76 +204,259 @@ func resourcePubsubSubscriptionRead(d *schema.ResourceData, meta interface{}) er
func resourcePubsubSubscriptionUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
d.Partial(true)
if d.HasChange("push_config") {
_, err := config.clientPubsub.Projects.Subscriptions.ModifyPushConfig(d.Id(), &pubsub.ModifyPushConfigRequest{
PushConfig: expandPubsubSubscriptionPushConfig(d.Get("push_config").([]interface{})),
}).Do()
if err != nil {
return fmt.Errorf("Error updating subscription %q: %s", d.Get("name"), err)
}
obj := make(map[string]interface{})
labelsProp, err := expandPubsubSubscriptionLabels(d.Get("labels"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
obj["labels"] = labelsProp
}
pushConfigProp, err := expandPubsubSubscriptionPushConfig(d.Get("push_config"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("push_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, pushConfigProp)) {
obj["pushConfig"] = pushConfigProp
}
ackDeadlineSecondsProp, err := expandPubsubSubscriptionAckDeadlineSeconds(d.Get("ack_deadline_seconds"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("ack_deadline_seconds"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, ackDeadlineSecondsProp)) {
obj["ackDeadlineSeconds"] = ackDeadlineSecondsProp
}
d.Partial(false)
obj, err = resourcePubsubSubscriptionUpdateEncoder(d, meta, obj)
if err != nil {
return err
}
return nil
url, err := replaceVars(d, config, "https://pubsub.googleapis.com/v1/projects/{{project}}/subscriptions/{{name}}")
if err != nil {
return err
}
log.Printf("[DEBUG] Updating Subscription %q: %#v", d.Id(), obj)
updateMask := []string{}
if d.HasChange("labels") {
updateMask = append(updateMask, "labels")
}
if d.HasChange("push_config") {
updateMask = append(updateMask, "pushConfig")
}
if d.HasChange("ack_deadline_seconds") {
updateMask = append(updateMask, "ackDeadlineSeconds")
}
// 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, ",")})
if err != nil {
return err
}
_, err = sendRequestWithTimeout(config, "PATCH", url, obj, d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("Error updating Subscription %q: %s", d.Id(), err)
}
return resourcePubsubSubscriptionRead(d, meta)
}
func resourcePubsubSubscriptionDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
name := d.Id()
call := config.clientPubsub.Projects.Subscriptions.Delete(name)
_, err := call.Do()
url, err := replaceVars(d, config, "https://pubsub.googleapis.com/v1/projects/{{project}}/subscriptions/{{name}}")
if err != nil {
return err
}
var obj map[string]interface{}
log.Printf("[DEBUG] Deleting Subscription %q", d.Id())
res, err := sendRequestWithTimeout(config, "DELETE", url, obj, d.Timeout(schema.TimeoutDelete))
if err != nil {
return handleNotFoundError(err, d, "Subscription")
}
log.Printf("[DEBUG] Finished deleting Subscription %q: %#v", d.Id(), res)
return nil
}
func resourcePubsubSubscriptionStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
func resourcePubsubSubscriptionImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
if err := parseImportId([]string{"projects/(?P<project>[^/]+)/subscriptions/(?P<name>[^/]+)", "(?P<project>[^/]+)/(?P<name>[^/]+)", "(?P<name>[^/]+)"}, d, config); err != nil {
return nil, err
}
id := fmt.Sprintf("projects/%s/subscriptions/%s", project, d.Id())
// Replace import id for the resource id
id, err := replaceVars(d, config, "projects/{{project}}/subscriptions/{{name}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
func flattenPubsubSubscriptionPushConfig(pushConfig *pubsub.PushConfig) []map[string]interface{} {
configs := make([]map[string]interface{}, 0, 1)
if pushConfig == nil || len(pushConfig.PushEndpoint) == 0 {
return configs
func flattenPubsubSubscriptionName(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return v
}
configs = append(configs, map[string]interface{}{
"push_endpoint": pushConfig.PushEndpoint,
"attributes": pushConfig.Attributes,
})
return configs
return NameFromSelfLinkStateFunc(v)
}
func expandPubsubSubscriptionPushConfig(configured []interface{}) *pubsub.PushConfig {
if len(configured) == 0 || configured[0] == nil {
// An empty `pushConfig` indicates that the Pub/Sub system should stop pushing messages
// from the given subscription and allow messages to be pulled and acknowledged.
return &pubsub.PushConfig{}
func flattenPubsubSubscriptionTopic(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return v
}
return ConvertSelfLinkToV1(v.(string))
}
func flattenPubsubSubscriptionLabels(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenPubsubSubscriptionPushConfig(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["push_endpoint"] =
flattenPubsubSubscriptionPushConfigPushEndpoint(original["pushEndpoint"], d)
transformed["attributes"] =
flattenPubsubSubscriptionPushConfigAttributes(original["attributes"], d)
return []interface{}{transformed}
}
func flattenPubsubSubscriptionPushConfigPushEndpoint(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenPubsubSubscriptionPushConfigAttributes(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func flattenPubsubSubscriptionAckDeadlineSeconds(v interface{}, d *schema.ResourceData) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
return intVal
} // let terraform core handle it if we can't convert the string to an int.
}
return v
}
func expandPubsubSubscriptionName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
project, err := getProject(d, config)
if err != nil {
return "", err
}
pushConfig := configured[0].(map[string]interface{})
return &pubsub.PushConfig{
PushEndpoint: pushConfig["push_endpoint"].(string),
Attributes: convertStringMap(pushConfig["attributes"].(map[string]interface{})),
subscription := d.Get("name").(string)
re := regexp.MustCompile("projects\\/(.*)\\/subscriptions\\/(.*)")
match := re.FindStringSubmatch(subscription)
if len(match) == 3 {
// We need to preserve the behavior where the user passes the subscription name already in the long form,
// however we need it to be stored as the short form since it's used for the replaceVars in the URL.
// The unintuitive behavior is that if the user provides the long form, we use the project from there, not the one
// specified on the resource or provider.
// TODO(drebes): consider depracating the long form behavior for 3.0
d.Set("project", match[1])
d.Set("name", match[2])
return subscription, nil
}
return fmt.Sprintf("projects/%s/subscriptions/%s", project, subscription), nil
}
func expandPubsubSubscriptionTopic(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
project, err := getProject(d, config)
if err != nil {
return "", err
}
topic := d.Get("topic").(string)
re := regexp.MustCompile("projects\\/(.*)\\/topics\\/(.*)")
match := re.FindStringSubmatch(topic)
if len(match) == 3 {
return topic, nil
} else {
// If no full topic given, we expand it to a full topic on the same project
fullTopic := fmt.Sprintf("projects/%s/topics/%s", project, topic)
d.Set("topic", fullTopic)
return fullTopic, nil
}
}
func expandPubsubSubscriptionLabels(v interface{}, d *schema.ResourceData, config *Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
}
m := make(map[string]string)
for k, val := range v.(map[string]interface{}) {
m[k] = val.(string)
}
return m, nil
}
func expandPubsubSubscriptionPushConfig(v interface{}, d *schema.ResourceData, 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{})
transformedPushEndpoint, err := expandPubsubSubscriptionPushConfigPushEndpoint(original["push_endpoint"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedPushEndpoint); val.IsValid() && !isEmptyValue(val) {
transformed["pushEndpoint"] = transformedPushEndpoint
}
transformedAttributes, err := expandPubsubSubscriptionPushConfigAttributes(original["attributes"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedAttributes); val.IsValid() && !isEmptyValue(val) {
transformed["attributes"] = transformedAttributes
}
return transformed, nil
}
func expandPubsubSubscriptionPushConfigPushEndpoint(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return v, nil
}
func expandPubsubSubscriptionPushConfigAttributes(v interface{}, d *schema.ResourceData, config *Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
}
m := make(map[string]string)
for k, val := range v.(map[string]interface{}) {
m[k] = val.(string)
}
return m, nil
}
func expandPubsubSubscriptionAckDeadlineSeconds(v interface{}, d *schema.ResourceData, 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
return newObj, nil
}
func resourcePubsubSubscriptionDecoder(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) {
path := fmt.Sprintf("projects/%s/subscriptions/%s", d.Get("project"), d.Get("name"))
d.Set("path", path)
return res, nil
}

View File

@ -0,0 +1,93 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google
import (
"fmt"
"strings"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccPubsubSubscription_pubsubSubscriptionPullExample(t *testing.T) {
t.Parallel()
context := map[string]interface{}{
"random_suffix": acctest.RandString(10),
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckPubsubSubscriptionDestroy,
Steps: []resource.TestStep{
{
Config: testAccPubsubSubscription_pubsubSubscriptionPullExample(context),
},
{
ResourceName: "google_pubsub_subscription.example",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func testAccPubsubSubscription_pubsubSubscriptionPullExample(context map[string]interface{}) string {
return Nprintf(`
resource "google_pubsub_topic" "example" {
name = "example-topic-%{random_suffix}"
}
resource "google_pubsub_subscription" "example" {
name = "example-subscription-%{random_suffix}"
topic = "${google_pubsub_topic.example.name}"
labels = {
foo = "bar"
}
ack_deadline_seconds = 20
}
`, context)
}
func testAccCheckPubsubSubscriptionDestroy(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
if rs.Type != "google_pubsub_subscription" {
continue
}
if strings.HasPrefix(name, "data.") {
continue
}
config := testAccProvider.Meta().(*Config)
url, err := replaceVarsForTest(rs, "https://pubsub.googleapis.com/v1/projects/{{project}}/subscriptions/{{name}}")
if err != nil {
return err
}
_, err = sendRequest(config, "GET", url, nil)
if err == nil {
return fmt.Errorf("PubsubSubscription still exists at %s", url)
}
}
return nil
}

View File

@ -6,14 +6,13 @@ import (
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccPubsubSubscription_basic(t *testing.T) {
func TestAccPubsubSubscription_fullName(t *testing.T) {
t.Parallel()
topic := fmt.Sprintf("tf-test-topic-%s", acctest.RandString(10))
subscription := fmt.Sprintf("tf-test-sub-%s", acctest.RandString(10))
subscription := fmt.Sprintf("projects/%s/subscriptions/tf-test-sub-%s", getTestProjectFromEnv(), acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -21,7 +20,7 @@ func TestAccPubsubSubscription_basic(t *testing.T) {
CheckDestroy: testAccCheckPubsubSubscriptionDestroy,
Steps: []resource.TestStep{
{
Config: testAccPubsubSubscription_basic(topic, subscription),
Config: testAccPubsubSubscription_fullName(topic, subscription, "bar", 20),
},
{
ResourceName: "google_pubsub_subscription.foo",
@ -33,6 +32,55 @@ func TestAccPubsubSubscription_basic(t *testing.T) {
})
}
func TestAccPubsubSubscription_update(t *testing.T) {
t.Parallel()
topic := fmt.Sprintf("tf-test-topic-%s", acctest.RandString(10))
subscriptionShort := fmt.Sprintf("tf-test-sub-%s", acctest.RandString(10))
subscriptionLong := fmt.Sprintf("projects/%s/subscriptions/%s", getTestProjectFromEnv(), subscriptionShort)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckPubsubSubscriptionDestroy,
Steps: []resource.TestStep{
{
Config: testAccPubsubSubscription_fullName(topic, subscriptionLong, "bar", 20),
},
{
ResourceName: "google_pubsub_subscription.foo",
ImportStateId: subscriptionLong,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccPubsubSubscription_fullName(topic, subscriptionLong, "baz", 30),
Check: resource.TestCheckResourceAttr(
"google_pubsub_subscription.foo", "path", subscriptionLong,
),
},
{
ResourceName: "google_pubsub_subscription.foo",
ImportStateId: subscriptionLong,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccPubsubSubscription_fullName(topic, subscriptionShort, "baz", 30),
Check: resource.TestCheckResourceAttr(
"google_pubsub_subscription.foo", "path", subscriptionLong,
),
},
{
ResourceName: "google_pubsub_subscription.foo",
ImportStateId: subscriptionShort,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
// TODO: Add acceptance test for push delivery.
//
// Testing push endpoints is tricky for the following reason:
@ -45,23 +93,8 @@ func TestAccPubsubSubscription_basic(t *testing.T) {
// An easy way to test this would be to create an App Engine Hello World app. With AppEngine, SSL certificate, DNS and domain registry is handled for us.
// App Engine is not yet supported by Terraform but once it is, it will provide an easy path to testing push configs.
// Another option would be to use Cloud Functions once Terraform support is added.
func testAccCheckPubsubSubscriptionDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "google_pubsub_subscription" {
continue
}
config := testAccProvider.Meta().(*Config)
sub, _ := config.clientPubsub.Projects.Subscriptions.Get(rs.Primary.ID).Do()
if sub != nil {
return fmt.Errorf("Subscription still present")
}
}
return nil
}
func testAccPubsubSubscription_basic(topic, subscription string) string {
func testAccPubsubSubscription_fullName(topic, subscription, label string, deadline int) string {
return fmt.Sprintf(`
resource "google_pubsub_topic" "foo" {
name = "%s"
@ -69,9 +102,12 @@ resource "google_pubsub_topic" "foo" {
resource "google_pubsub_subscription" "foo" {
name = "%s"
topic = "${google_pubsub_topic.foo.name}"
ack_deadline_seconds = 20
}`, topic, subscription)
topic = "${google_pubsub_topic.foo.id}"
labels = {
foo = "%s"
}
ack_deadline_seconds = %d
}`, topic, subscription, label, deadline)
}
func TestGetComputedTopicName(t *testing.T) {

View File

@ -1,11 +1,26 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google
import (
"fmt"
"regexp"
"log"
"reflect"
"time"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/pubsub/v1"
)
func resourcePubsubTopic() *schema.Resource {
@ -15,7 +30,12 @@ func resourcePubsubTopic() *schema.Resource {
Delete: resourcePubsubTopicDelete,
Importer: &schema.ResourceImporter{
State: resourcePubsubTopicStateImporter,
State: resourcePubsubTopicImport,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(240 * time.Second),
Delete: schema.DefaultTimeout(240 * time.Second),
},
Schema: map[string]*schema.Schema{
@ -23,9 +43,14 @@ func resourcePubsubTopic() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: linkDiffSuppress,
DiffSuppressFunc: compareSelfLinkOrResourceName,
},
"labels": {
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"project": {
Type: schema.TypeString,
Optional: true,
@ -39,21 +64,39 @@ func resourcePubsubTopic() *schema.Resource {
func resourcePubsubTopicCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
obj := make(map[string]interface{})
nameProp, err := expandPubsubTopicName(d.Get("name"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
obj["name"] = nameProp
}
labelsProp, err := expandPubsubTopicLabels(d.Get("labels"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
obj["labels"] = labelsProp
}
url, err := replaceVars(d, config, "https://pubsub.googleapis.com/v1/projects/{{project}}/topics/{{name}}")
if err != nil {
return err
}
name := fmt.Sprintf("projects/%s/topics/%s", project, d.Get("name").(string))
topic := &pubsub.Topic{}
call := config.clientPubsub.Projects.Topics.Create(name, topic)
res, err := call.Do()
log.Printf("[DEBUG] Creating new Topic: %#v", obj)
res, err := sendRequestWithTimeout(config, "PUT", url, obj, d.Timeout(schema.TimeoutCreate))
if err != nil {
return err
return fmt.Errorf("Error creating Topic: %s", err)
}
d.SetId(res.Name)
// Store the ID now
id, err := replaceVars(d, config, "projects/{{project}}/topics/{{name}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
log.Printf("[DEBUG] Finished creating Topic %q: %#v", d.Id(), res)
return resourcePubsubTopicRead(d, meta)
}
@ -61,20 +104,30 @@ func resourcePubsubTopicCreate(d *schema.ResourceData, meta interface{}) error {
func resourcePubsubTopicRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
url, err := replaceVars(d, config, "https://pubsub.googleapis.com/v1/projects/{{project}}/topics/{{name}}")
if err != nil {
return err
}
name := d.Id()
call := config.clientPubsub.Projects.Topics.Get(name)
res, err := call.Do()
res, err := sendRequest(config, "GET", url, nil)
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Pubsub Topic %q", name))
return handleNotFoundError(err, d, fmt.Sprintf("PubsubTopic %q", d.Id()))
}
d.Set("name", GetResourceNameFromSelfLink(res.Name))
d.Set("project", project)
project, err := getProject(d, config)
if err != nil {
return err
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading Topic: %s", err)
}
if err := d.Set("name", flattenPubsubTopicName(res["name"], d)); err != nil {
return fmt.Errorf("Error reading Topic: %s", err)
}
if err := d.Set("labels", flattenPubsubTopicLabels(res["labels"], d)); err != nil {
return fmt.Errorf("Error reading Topic: %s", err)
}
return nil
}
@ -82,31 +135,60 @@ func resourcePubsubTopicRead(d *schema.ResourceData, meta interface{}) error {
func resourcePubsubTopicDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
name := d.Id()
call := config.clientPubsub.Projects.Topics.Delete(name)
_, err := call.Do()
url, err := replaceVars(d, config, "https://pubsub.googleapis.com/v1/projects/{{project}}/topics/{{name}}")
if err != nil {
return err
}
var obj map[string]interface{}
log.Printf("[DEBUG] Deleting Topic %q", d.Id())
res, err := sendRequestWithTimeout(config, "DELETE", url, obj, d.Timeout(schema.TimeoutDelete))
if err != nil {
return handleNotFoundError(err, d, "Topic")
}
log.Printf("[DEBUG] Finished deleting Topic %q: %#v", d.Id(), res)
return nil
}
func resourcePubsubTopicStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
func resourcePubsubTopicImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
topicId := regexp.MustCompile("^projects/[^/]+/topics/[^/]+$")
if topicId.MatchString(d.Id()) {
return []*schema.ResourceData{d}, nil
if err := parseImportId([]string{"projects/(?P<project>[^/]+)/topics/(?P<name>[^/]+)", "(?P<project>[^/]+)/(?P<name>[^/]+)", "(?P<name>[^/]+)"}, d, config); err != nil {
return nil, err
}
if config.Project == "" {
return nil, fmt.Errorf("The default project for the provider must be set when using the `{name}` id format.")
// Replace import id for the resource id
id, err := replaceVars(d, config, "projects/{{project}}/topics/{{name}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
id := fmt.Sprintf("projects/%s/topics/%s", config.Project, d.Id())
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
func flattenPubsubTopicName(v interface{}, d *schema.ResourceData) interface{} {
if v == nil {
return v
}
return NameFromSelfLinkStateFunc(v)
}
func flattenPubsubTopicLabels(v interface{}, d *schema.ResourceData) interface{} {
return v
}
func expandPubsubTopicName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) {
return GetResourceNameFromSelfLink(v.(string)), nil
}
func expandPubsubTopicLabels(v interface{}, d *schema.ResourceData, config *Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
}
m := make(map[string]string)
for k, val := range v.(map[string]interface{}) {
m[k] = val.(string)
}
return m, nil
}

View File

@ -0,0 +1,86 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------
package google
import (
"fmt"
"strings"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccPubsubTopic_pubsubTopicBasicExample(t *testing.T) {
t.Parallel()
context := map[string]interface{}{
"random_suffix": acctest.RandString(10),
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckPubsubTopicDestroy,
Steps: []resource.TestStep{
{
Config: testAccPubsubTopic_pubsubTopicBasicExample(context),
},
{
ResourceName: "google_pubsub_topic.example",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func testAccPubsubTopic_pubsubTopicBasicExample(context map[string]interface{}) string {
return Nprintf(`
resource "google_pubsub_topic" "example" {
name = "example-topic-%{random_suffix}"
labels = {
foo = "bar"
}
}
`, context)
}
func testAccCheckPubsubTopicDestroy(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
if rs.Type != "google_pubsub_topic" {
continue
}
if strings.HasPrefix(name, "data.") {
continue
}
config := testAccProvider.Meta().(*Config)
url, err := replaceVarsForTest(rs, "https://pubsub.googleapis.com/v1/projects/{{project}}/topics/{{name}}")
if err != nil {
return err
}
_, err = sendRequest(config, "GET", url, nil)
if err == nil {
return fmt.Errorf("PubsubTopic still exists at %s", url)
}
}
return nil
}

View File

@ -1,65 +0,0 @@
package google
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccPubsubTopic_basic(t *testing.T) {
t.Parallel()
topicName := acctest.RandomWithPrefix("tf-test-topic")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckPubsubTopicDestroy,
Steps: []resource.TestStep{
{
Config: testAccPubsubTopic_basic(topicName),
},
// Check importing with just the topic name
{
ResourceName: "google_pubsub_topic.foo",
ImportStateId: topicName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"force_destroy"},
},
// Check importing with the full resource id
{
ResourceName: "google_pubsub_topic.foo",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"force_destroy"},
},
},
})
}
func testAccCheckPubsubTopicDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "google_pubsub_topic" {
continue
}
config := testAccProvider.Meta().(*Config)
topic, _ := config.clientPubsub.Projects.Topics.Get(rs.Primary.ID).Do()
if topic != nil {
return fmt.Errorf("Topic still present")
}
}
return nil
}
func testAccPubsubTopic_basic(name string) string {
return fmt.Sprintf(`
resource "google_pubsub_topic" "foo" {
name = "%s"
}`, name)
}

View File

@ -1,52 +1,101 @@
---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google"
page_title: "Google: google_pubsub_subscription"
sidebar_current: "docs-google-pubsub-subscription-x"
sidebar_current: "docs-google-pubsub-subscription"
description: |-
Creates a subscription in Google's pubsub queueing system
A named resource representing the stream of messages from a single,
specific topic, to be delivered to the subscribing application.
---
# google\_pubsub\_subscription
Creates a subscription in Google's pubsub queueing system. For more information see
[the official documentation](https://cloud.google.com/pubsub/docs) and
[API](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions).
A named resource representing the stream of messages from a single,
specific topic, to be delivered to the subscribing application.
## Example Usage
To get more information about Subscription, see:
* [API documentation](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions)
* How-to Guides
* [Managing Subscriptions](https://cloud.google.com/pubsub/docs/admin#managing_subscriptions)
## Example Usage - Pubsub Subscription Push
```hcl
resource "google_pubsub_topic" "default-topic" {
name = "default-topic"
resource "google_pubsub_topic" "example" {
name = "example-topic"
}
resource "google_pubsub_subscription" "default" {
name = "default-subscription"
topic = "${google_pubsub_topic.default-topic.name}"
resource "google_pubsub_subscription" "example" {
name = "example-subscription"
topic = "${google_pubsub_topic.example.name}"
ack_deadline_seconds = 20
labels = {
foo = "bar"
}
push_config {
push_endpoint = "https://example.com/push"
attributes = {
attributes {
x-goog-version = "v1"
}
}
}
```
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
<a href="https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fdocs-examples.git&cloudshell_working_dir=pubsub_subscription_pull&cloudshell_image=gcr.io%2Fgraphite-cloud-shell-images%2Fterraform%3Alatest&open_in_editor=main.tf&cloudshell_print=.%2Fmotd&cloudshell_tutorial=.%2Ftutorial.md" target="_blank">
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
</a>
</div>
## Example Usage - Pubsub Subscription Pull
If the subscription has a topic in a different project:
```hcl
resource "google_pubsub_topic" "topic-different-project" {
project = "another-project"
name = "topic-different-project"
resource "google_pubsub_topic" "example" {
name = "example-topic"
}
resource "google_pubsub_subscription" "default" {
name = "default-subscription"
topic = "${google_pubsub_topic.topic-different-project.id}"
resource "google_pubsub_subscription" "example" {
name = "example-subscription"
topic = "${google_pubsub_topic.example.name}"
labels = {
foo = "bar"
}
ack_deadline_seconds = 20
}
```
## Example Usage - Pubsub Subscription Different Project
```hcl
resource "google_pubsub_topic" "example" {
project = "topic-project"
name = "example-topic"
}
resource "google_pubsub_subscription" "example" {
project = "subscription-project"
name = "example-subscription"
topic = "${google_pubsub_topic.example.id}"
}
```
@ -54,45 +103,105 @@ resource "google_pubsub_subscription" "default" {
The following arguments are supported:
* `name` - (Required) A unique name for the resource, required by pubsub.
Changing this forces a new resource to be created.
* `topic` - (Required) The topic name or id to bind this subscription to, required by pubsub.
Changing this forces a new resource to be created.
* `name` -
(Required)
Name of the subscription.
* `topic` -
(Required)
A reference to a Topic resource.
- - -
* `ack_deadline_seconds` - (Optional) The maximum number of seconds a
subscriber has to acknowledge a received message, otherwise the message is
redelivered. Changing this forces a new resource to be created.
* `project` - (Optional) The ID of the project in which the resource belongs. If it
is not provided, the provider project is used.
* `labels` -
(Optional)
A set of key/value label pairs to assign to this Subscription.
* `push_config` - (Optional) Block configuration for push options. More
configuration options are detailed below.
* `push_config` -
(Optional)
If push delivery is used with this subscription, this field is used to
configure it. An empty pushConfig signifies that the subscriber will
pull and ack messages using API methods. Structure is documented below.
The optional `push_config` block supports:
* `ack_deadline_seconds` -
(Optional)
This value is the maximum time after a subscriber receives a message
before the subscriber should acknowledge the message. After message
delivery but before the ack deadline expires and before the message is
acknowledged, it is an outstanding message and will not be delivered
again during that time (on a best-effort basis).
For pull subscriptions, this value is used as the initial value for
the ack deadline. To override this value for a given message, call
subscriptions.modifyAckDeadline with the corresponding ackId if using
pull. The minimum custom deadline you can specify is 10 seconds. The
maximum custom deadline you can specify is 600 seconds (10 minutes).
If this parameter is 0, a default value of 10 seconds is used.
For push delivery, this value is also used to set the request timeout
for the call to the push endpoint.
If the subscriber never acknowledges the message, the Pub/Sub system
will eventually redeliver the message.
* `project` - (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.
* `push_endpoint` - (Required) The URL of the endpoint to which messages should
be pushed. Changing this forces a new resource to be created.
* `attributes` - (Optional) Key-value pairs of API supported attributes used
to control aspects of the message delivery. Currently, only
`x-goog-version` is supported, which controls the format of the data
delivery. For more information, read [the API docs
here](https://cloud.google.com/pubsub/reference/rest/v1/projects.subscriptions#PushConfig.FIELDS.attributes).
Changing this forces a new resource to be created.
The `push_config` block supports:
* `push_endpoint` -
(Required)
A URL locating the endpoint to which messages should be pushed.
For example, a Webhook endpoint might use
"https://example.com/push".
* `attributes` -
(Optional)
Endpoint configuration attributes.
Every endpoint has a set of API supported attributes that can
be used to control different aspects of the message delivery.
The currently supported attribute is x-goog-version, which you
can use to change the format of the pushed message. This
attribute indicates the version of the data expected by
the endpoint. This controls the shape of the pushed message
(i.e., its fields and metadata). The endpoint version is
based on the version of the Pub/Sub API.
If not present during the subscriptions.create call,
it will default to the version of the API used to make
such call. If not present during a subscriptions.modifyPushConfig
call, its value will not be changed. subscriptions.get
calls will always return a valid version, even if the
subscription was created without this attribute.
The possible values for this attribute are:
- 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.
## Attributes Reference
* `path` - Path of the subscription in the format `projects/{project}/subscriptions/{sub}`
In addition to the arguments listed above, the following computed attributes are exported:
* `path`: Path of the subscription in the format `projects/{project}/subscriptions/{name}`
## Timeouts
This resource provides the following
[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
- `create` - Default is 4 minutes.
- `update` - Default is 4 minutes.
- `delete` - Default is 4 minutes.
## Import
Pubsub subscription can be imported using the `name`, e.g.
Subscription can be imported using any of these accepted formats:
```
$ terraform import google_pubsub_subscription.default default-subscription
$ terraform import google_pubsub_subscription.default projects/{{project}}/subscriptions/{{name}}
$ terraform import google_pubsub_subscription.default {{project}}/{{name}}
$ terraform import google_pubsub_subscription.default {{name}}
```
-> If you're importing a resource with beta features, make sure to include `-provider=google-beta`
as an argument so that Terraform uses the correct provider to import your resource.

View File

@ -1,23 +1,50 @@
---
# ----------------------------------------------------------------------------
#
# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
#
# ----------------------------------------------------------------------------
#
# This file is automatically generated by Magic Modules and manual
# changes will be clobbered when the file is regenerated.
#
# Please read more about how to change this file in
# .github/CONTRIBUTING.md.
#
# ----------------------------------------------------------------------------
layout: "google"
page_title: "Google: google_pubsub_topic"
sidebar_current: "docs-google-pubsub-topic-x"
sidebar_current: "docs-google-pubsub-topic"
description: |-
Creates a topic in Google's pubsub queueing system
A named resource to which messages are sent by publishers.
---
# google\_pubsub\_topic
Creates a topic in Google's pubsub queueing system. For more information see
[the official documentation](https://cloud.google.com/pubsub/docs) and
[API](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics).
A named resource to which messages are sent by publishers.
## Example Usage
To get more information about Topic, see:
* [API documentation](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics)
* How-to Guides
* [Managing Topics](https://cloud.google.com/pubsub/docs/admin#managing_topics)
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
<a href="https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fdocs-examples.git&cloudshell_working_dir=pubsub_topic_basic&cloudshell_image=gcr.io%2Fgraphite-cloud-shell-images%2Fterraform%3Alatest&open_in_editor=main.tf&cloudshell_print=.%2Fmotd&cloudshell_tutorial=.%2Ftutorial.md" target="_blank">
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
</a>
</div>
## Example Usage - Pubsub Topic Basic
```hcl
resource "google_pubsub_topic" "mytopic" {
name = "default-topic"
resource "google_pubsub_topic" "example" {
name = "example-topic"
labels = {
foo = "bar"
}
}
```
@ -25,26 +52,40 @@ resource "google_pubsub_topic" "mytopic" {
The following arguments are supported:
* `name` - (Required) A unique name for the pubsub topic.
Changing this forces a new resource to be created.
* `name` -
(Required)
Name of the topic.
- - -
* `project` - (Optional) The ID of the project in which the resource belongs. If it
is not provided, the provider project is used.
## Attributes Reference
* `labels` -
(Optional)
A set of key/value label pairs to assign to this Topic.
* `project` - (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.
Only the arguments listed above are exposed as attributes.
## Timeouts
This resource provides the following
[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
- `create` - Default is 4 minutes.
- `delete` - Default is 4 minutes.
## Import
Pubsub topics can be imported using the `name` or full topic id, e.g.
Topic can be imported using any of these accepted formats:
```
$ terraform import google_pubsub_topic.mytopic default-topic
$ terraform import google_pubsub_topic.default projects/{{project}}/topics/{{name}}
$ terraform import google_pubsub_topic.default {{project}}/{{name}}
$ terraform import google_pubsub_topic.default {{name}}
```
```
$ terraform import google_pubsub_topic.mytopic projects/my-gcp-project/topics/default-topic
```
When importing using only the name, the provider project must be set.
-> If you're importing a resource with beta features, make sure to include `-provider=google-beta`
as an argument so that Terraform uses the correct provider to import your resource.