From acd865213bf296c638f44154260e76f07fbf6778 Mon Sep 17 00:00:00 2001 From: emily Date: Wed, 22 Jan 2020 22:25:50 +0000 Subject: [PATCH] Add user labels and labels to monitoring notification channel DS Signed-off-by: Modular Magician --- ..._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/google-beta/data_source_monitoring_notification_channel.go b/google-beta/data_source_monitoring_notification_channel.go index 995ad75f5f..645f108105 100644 --- a/google-beta/data_source_monitoring_notification_channel.go +++ b/google-beta/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/google-beta/data_source_monitoring_notification_channel_test.go b/google-beta/data_source_monitoring_notification_channel_test.go index 2d8ecbd7ff..18d47f2dd1 100644 --- a/google-beta/data_source_monitoring_notification_channel_test.go +++ b/google-beta/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/website/docs/d/datasource_monitoring_notification_channel.html.markdown b/website/docs/d/datasource_monitoring_notification_channel.html.markdown index 619148c00a..fa8abbf52a 100644 --- a/website/docs/d/datasource_monitoring_notification_channel.html.markdown +++ b/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]`.