From 02714e16b0ccae394fb78798f2aa40902b993a28 Mon Sep 17 00:00:00 2001 From: Emily Ye Date: Wed, 22 Jan 2020 12:24:24 -0800 Subject: [PATCH 1/2] add label and user label to MonitoringNotificationChannel data source, fix tests --- ..._source_monitoring_notification_channel.go | 68 ++++---- ...ce_monitoring_notification_channel_test.go | 161 ++++++++++++------ ...itoring_notification_channel.html.markdown | 15 +- 3 files changed, 158 insertions(+), 86 deletions(-) diff --git a/third_party/terraform/data_sources/data_source_monitoring_notification_channel.go b/third_party/terraform/data_sources/data_source_monitoring_notification_channel.go index 995ad75f5fbb..645f1081055c 100644 --- a/third_party/terraform/data_sources/data_source_monitoring_notification_channel.go +++ b/third_party/terraform/data_sources/data_source_monitoring_notification_channel.go @@ -1,8 +1,8 @@ package google import ( - "errors" "fmt" + "strings" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) @@ -14,6 +14,8 @@ func dataSourceMonitoringNotificationChannel() *schema.Resource { addOptionalFieldsToSchema(dsSchema, "display_name") addOptionalFieldsToSchema(dsSchema, "project") addOptionalFieldsToSchema(dsSchema, "type") + addOptionalFieldsToSchema(dsSchema, "labels") + addOptionalFieldsToSchema(dsSchema, "user_labels") return &schema.Resource{ Read: dataSourceMonitoringNotificationChannelRead, @@ -33,26 +35,41 @@ func dataSourceMonitoringNotificationChannelRead(d *schema.ResourceData, meta in channelType := d.Get("type").(string) if displayName == "" && channelType == "" { - return errors.New("Must at least provide either `display_name` or `type`") + return fmt.Errorf("At least one of display_name or type must be provided") } - filter := "" + labels, err := expandMonitoringNotificationChannelLabels(d.Get("labels"), d, config) + if err != nil { + return err + } + + userLabels, err := expandMonitoringNotificationChannelLabels(d.Get("user_labels"), d, config) + if err != nil { + return err + } + + filters := make([]string, 0, len(labels)+2) + if displayName != "" { - filter = fmt.Sprintf("display_name=\"%s\"", displayName) + filters = append(filters, fmt.Sprintf(`display_name="%s"`, displayName)) } if channelType != "" { - channelFilter := fmt.Sprintf("type=\"%s\"", channelType) - if filter != "" { - filter += fmt.Sprintf(" AND %s", channelFilter) - } else { - filter = channelFilter - } + filters = append(filters, fmt.Sprintf(`type="%s"`, channelType)) + } + + for k, v := range labels { + filters = append(filters, fmt.Sprintf(`labels.%s="%s"`, k, v)) } - params := make(map[string]string) - params["filter"] = filter + for k, v := range userLabels { + filters = append(filters, fmt.Sprintf(`user_labels.%s="%s"`, k, v)) + } + filter := strings.Join(filters, " AND ") + params := map[string]string{ + "filter": filter, + } url, err = addQueryParams(url, params) if err != nil { return err @@ -68,32 +85,21 @@ func dataSourceMonitoringNotificationChannelRead(d *schema.ResourceData, meta in return fmt.Errorf("Error retrieving NotificationChannels: %s", err) } - var pageMonitoringNotificationChannels []interface{} + var channels []interface{} if v, ok := response["notificationChannels"]; ok { - pageMonitoringNotificationChannels = v.([]interface{}) + channels = v.([]interface{}) } - - if len(pageMonitoringNotificationChannels) == 0 { - return fmt.Errorf("No NotificationChannel found using filter=%s", filter) + if len(channels) == 0 { + return fmt.Errorf("No NotificationChannel found using filter: %s", filter) } - - if len(pageMonitoringNotificationChannels) > 1 { - return fmt.Errorf("More than one matching NotificationChannel found using filter=%s", filter) + if len(channels) > 1 { + return fmt.Errorf("Found more than one 1 NotificationChannel matching specified filter: %s", filter) } - - res := pageMonitoringNotificationChannels[0].(map[string]interface{}) + res := channels[0].(map[string]interface{}) name := flattenMonitoringNotificationChannelName(res["name"], d).(string) d.Set("name", name) - d.Set("project", project) - d.Set("labels", flattenMonitoringNotificationChannelLabels(res["labels"], d)) - d.Set("verification_status", flattenMonitoringNotificationChannelVerificationStatus(res["verificationStatus"], d)) - d.Set("type", flattenMonitoringNotificationChannelType(res["type"], d)) - d.Set("user_labels", flattenMonitoringNotificationChannelUserLabels(res["userLabels"], d)) - d.Set("description", flattenMonitoringNotificationChannelDescription(res["descriptionx"], d)) - d.Set("display_name", flattenMonitoringNotificationChannelDisplayName(res["displayName"], d)) - d.Set("enabled", flattenMonitoringNotificationChannelEnabled(res["enabled"], d)) d.SetId(name) - return nil + return resourceMonitoringNotificationChannelRead(d, meta) } diff --git a/third_party/terraform/tests/data_source_monitoring_notification_channel_test.go b/third_party/terraform/tests/data_source_monitoring_notification_channel_test.go index 2d8ecbd7ff1b..18d47f2dd124 100644 --- a/third_party/terraform/tests/data_source_monitoring_notification_channel_test.go +++ b/third_party/terraform/tests/data_source_monitoring_notification_channel_test.go @@ -18,25 +18,42 @@ func TestAccDataSourceGoogleMonitoringNotificationChannel_byDisplayName(t *testi Config: testAccDataSourceGoogleMonitoringNotificationChannel_byDisplayName(acctest.RandomWithPrefix("tf-test")), Check: resource.ComposeTestCheckFunc( checkDataSourceStateMatchesResourceState( - "data.google_monitoring_notification_channel.my", - "google_monitoring_notification_channel.my"), + "data.google_monitoring_notification_channel.default", + "google_monitoring_notification_channel.default"), ), }, }, }) } -func TestAccDataSourceGoogleMonitoringNotificationChannel_byType(t *testing.T) { +func TestAccDataSourceGoogleMonitoringNotificationChannel_byTypeAndLabel(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceGoogleMonitoringNotificationChannel_byType(acctest.RandomWithPrefix("tf-test")), + Config: testAccDataSourceGoogleMonitoringNotificationChannel_byTypeAndLabel(acctest.RandomWithPrefix("tf-test")), Check: resource.ComposeTestCheckFunc( checkDataSourceStateMatchesResourceState( - "data.google_monitoring_notification_channel.my", - "google_monitoring_notification_channel.my"), + "data.google_monitoring_notification_channel.default", + "google_monitoring_notification_channel.default"), + ), + }, + }, + }) +} + +func TestAccDataSourceGoogleMonitoringNotificationChannel_UserLabel(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleMonitoringNotificationChannel_byTypeAndUserLabel(acctest.RandomWithPrefix("tf-test")), + Check: resource.ComposeTestCheckFunc( + checkDataSourceStateMatchesResourceState( + "data.google_monitoring_notification_channel.default", + "google_monitoring_notification_channel.default"), ), }, }, @@ -52,41 +69,55 @@ func TestAccDataSourceGoogleMonitoringNotificationChannel_byDisplayNameAndType(t Config: testAccDataSourceGoogleMonitoringNotificationChannel_byDisplayNameAndType(acctest.RandomWithPrefix("tf-test")), Check: resource.ComposeTestCheckFunc( checkDataSourceStateMatchesResourceState( - "data.google_monitoring_notification_channel.my", - "google_monitoring_notification_channel.myemail"), + "data.google_monitoring_notification_channel.email", + "google_monitoring_notification_channel.email"), ), }, }, }) } -func TestAccDataSourceGoogleMonitoringNotificationChannel_NotFound(t *testing.T) { +func TestAccDataSourceGoogleMonitoringNotificationChannel_ErrorNoDisplayNameOrType(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleMonitoringNotificationChannel_NoDisplayNameOrType(), + ExpectError: regexp.MustCompile("At least one of display_name or type must be provided"), + }, + }, + }) +} + +func TestAccDataSourceGoogleMonitoringNotificationChannel_ErrorNotFound(t *testing.T) { displayName := acctest.RandomWithPrefix("tf-test") + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { Config: testAccDataSourceGoogleMonitoringNotificationChannel_NotFound(displayName), - ExpectError: regexp.MustCompile(fmt.Sprintf("No NotificationChannel found using filter=display_name=\"%s\"", displayName)), + ExpectError: regexp.MustCompile(fmt.Sprintf(`No NotificationChannel found using filter: display_name="%s"`, displayName)), }, }, }) } -func TestAccDataSourceGoogleMonitoringNotificationChannel_NotUnique(t *testing.T) { +func TestAccDataSourceGoogleMonitoringNotificationChannel_ErrorNotUnique(t *testing.T) { displayName := acctest.RandomWithPrefix("tf-test") resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - PreventPostDestroyRefresh: true, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, Steps: []resource.TestStep{ { Config: testAccDataSourceGoogleMonitoringNotificationChannel_NotUnique(displayName), }, { - Config: testAccDataSourceGoogleMonitoringNotificationChannel_NotUniqueDS(displayName), - ExpectError: regexp.MustCompile(fmt.Sprintf("More than one matching NotificationChannel found using filter=display_name=\"%s\"", displayName)), + Config: testAccDataSourceGoogleMonitoringNotificationChannel_NotUniqueWithData(displayName), + ExpectError: regexp.MustCompile(fmt.Sprintf( + `Found more than one 1 NotificationChannel matching specified filter: display_name="%s"`, displayName)), }, }, }) @@ -94,99 +125,133 @@ func TestAccDataSourceGoogleMonitoringNotificationChannel_NotUnique(t *testing.T func testAccDataSourceGoogleMonitoringNotificationChannel_byDisplayName(displayName string) string { return fmt.Sprintf(` -resource "google_monitoring_notification_channel" "my" { +resource "google_monitoring_notification_channel" "default" { display_name = "%s" type = "webhook_tokenauth" labels = { - url = "http://www.acme.org" + url = "http://www.google.com" } } -data "google_monitoring_notification_channel" "my" { - display_name = google_monitoring_notification_channel.my.display_name +data "google_monitoring_notification_channel" "default" { + display_name = google_monitoring_notification_channel.default.display_name } `, displayName) } -func testAccDataSourceGoogleMonitoringNotificationChannel_byType(displayName string) string { +// Include label so we don't fail on dangling resources +func testAccDataSourceGoogleMonitoringNotificationChannel_byTypeAndLabel(displayName string) string { return fmt.Sprintf(` -resource "google_monitoring_notification_channel" "my" { +resource "google_monitoring_notification_channel" "default" { display_name = "%s" - type = "sms" + type = "email" labels = { - number = "+1555" + email_address = "%s@google.com" } } -data "google_monitoring_notification_channel" "my" { - type = google_monitoring_notification_channel.my.type +data "google_monitoring_notification_channel" "default" { + type = google_monitoring_notification_channel.default.type + labels = google_monitoring_notification_channel.default.labels } -`, displayName) +`, displayName, displayName) +} + +func testAccDataSourceGoogleMonitoringNotificationChannel_byTypeAndUserLabel(displayName string) string { + return fmt.Sprintf(` +resource "google_monitoring_notification_channel" "default" { + display_name = "%s" + type = "email" + + user_labels = { + testname = "%s" + } +} + +data "google_monitoring_notification_channel" "default" { + type = google_monitoring_notification_channel.default.type + user_labels = google_monitoring_notification_channel.default.user_labels +} +`, displayName, displayName) } func testAccDataSourceGoogleMonitoringNotificationChannel_byDisplayNameAndType(displayName string) string { return fmt.Sprintf(` -resource "google_monitoring_notification_channel" "mywebhook" { +resource "google_monitoring_notification_channel" "webhook" { display_name = "%s" type = "webhook_tokenauth" labels = { - url = "http://www.acme.org" + url = "http://www.google.com" } } -resource "google_monitoring_notification_channel" "myemail" { - display_name = google_monitoring_notification_channel.mywebhook.display_name +resource "google_monitoring_notification_channel" "email" { + display_name = "%s" type = "email" labels = { - email_address = "mailme@acme.org" + email_address = "%s@google.com" } } -data "google_monitoring_notification_channel" "my" { - display_name = google_monitoring_notification_channel.myemail.display_name - type = google_monitoring_notification_channel.myemail.type +data "google_monitoring_notification_channel" "email" { + display_name = google_monitoring_notification_channel.email.display_name + type = google_monitoring_notification_channel.email.type } -`, displayName) +`, displayName, displayName, displayName) } func testAccDataSourceGoogleMonitoringNotificationChannel_NotFound(displayName string) string { return fmt.Sprintf(` -data "google_monitoring_notification_channel" "my" { +data "google_monitoring_notification_channel" "default" { display_name = "%s" } `, displayName) } +func testAccDataSourceGoogleMonitoringNotificationChannel_NoDisplayNameOrType() string { + return ` +data "google_monitoring_notification_channel" "default" { + labels = { + email = "doesntmatter@google.com'" + } + user_labels = { + foo = "bar" + } +} +` +} + func testAccDataSourceGoogleMonitoringNotificationChannel_NotUnique(displayName string) string { return fmt.Sprintf(` -resource "google_monitoring_notification_channel" "default" { - display_name = "%s" +resource "google_monitoring_notification_channel" "channel-1" { + display_name = "%[1]s" type = "webhook_tokenauth" labels = { - url = "http://www.acme1.org" + url = "http://%[1]s.google.com" } } -resource "google_monitoring_notification_channel" "default2" { - display_name = google_monitoring_notification_channel.default.display_name +resource "google_monitoring_notification_channel" "channel-2" { + display_name = google_monitoring_notification_channel.channel-1.display_name type = "webhook_tokenauth" labels = { - url = "http://www.acme2.org" + url = "http://%[1]s-copy.google.org" } } `, displayName) } -func testAccDataSourceGoogleMonitoringNotificationChannel_NotUniqueDS(displayName string) string { - return fmt.Sprintf(` -data "google_monitoring_notification_channel" "my" { - display_name = "%s" +func testAccDataSourceGoogleMonitoringNotificationChannel_NotUniqueWithData(displayName string) string { + return testAccDataSourceGoogleMonitoringNotificationChannel_NotUnique(displayName) + ` + +data "google_monitoring_notification_channel" "ds" { + display_name = google_monitoring_notification_channel.channel-2.display_name } -`, displayName) +` } diff --git a/third_party/terraform/website/docs/d/datasource_monitoring_notification_channel.html.markdown b/third_party/terraform/website/docs/d/datasource_monitoring_notification_channel.html.markdown index 619148c00a71..fa8abbf52af1 100644 --- a/third_party/terraform/website/docs/d/datasource_monitoring_notification_channel.html.markdown +++ b/third_party/terraform/website/docs/d/datasource_monitoring_notification_channel.html.markdown @@ -56,29 +56,30 @@ resource "google_monitoring_alert_policy" "alert_policy" { The arguments of this data source act as filters for querying the available notification channels. The given filters must match exactly one notification channel whose data will be exported as attributes. The following arguments are supported: +One of the following fields must be specified: * `display_name` - (Optional) The display name for this notification channel. -* `type` - - (Optional) - The type of the notification channel. - -~> **NOTE:** One of `display_name` or `type` must be specified. +* `type` - (Optional) The type of the notification channel. - - - +Other optional fields include: + +* `labels` - (Optional) Labels (corresponding to the + NotificationChannelDescriptor schema) to filter the notification channels by. + +* `user_labels` - (Optional) User-provided key-value labels to filter by. * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. - ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: - * `name` - The full REST resource name for this channel. The syntax is: `projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID]`. From ebe099fb694c2615c465f1bf46ac80fd609e8715 Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Wed, 22 Jan 2020 23:43:56 +0000 Subject: [PATCH 2/2] Update tracked submodules -> HEAD on Wed Jan 22 23:43:56 UTC 2020 Tracked submodules are build/terraform-beta build/terraform-mapper build/terraform build/ansible build/inspec. --- build/terraform | 2 +- build/terraform-beta | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/terraform b/build/terraform index 4315c89629d2..fef24138a615 160000 --- a/build/terraform +++ b/build/terraform @@ -1 +1 @@ -Subproject commit 4315c89629d2542026fe759e67e42f4bded15a08 +Subproject commit fef24138a6158b7fa7bd06156dc3a89c6ce233de diff --git a/build/terraform-beta b/build/terraform-beta index ebdead1a6214..2ded434045c5 160000 --- a/build/terraform-beta +++ b/build/terraform-beta @@ -1 +1 @@ -Subproject commit ebdead1a6214733f90d332b03885583d30a68924 +Subproject commit 2ded434045c553c49ca3068d442b7b2d7c5bf0af