diff --git a/google/data_source_monitoring_notification_channel.go b/google/data_source_monitoring_notification_channel.go new file mode 100644 index 00000000000..995ad75f5fb --- /dev/null +++ b/google/data_source_monitoring_notification_channel.go @@ -0,0 +1,99 @@ +package google + +import ( + "errors" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func dataSourceMonitoringNotificationChannel() *schema.Resource { + dsSchema := datasourceSchemaFromResourceSchema(resourceMonitoringNotificationChannel().Schema) + + // Set 'Optional' schema elements + addOptionalFieldsToSchema(dsSchema, "display_name") + addOptionalFieldsToSchema(dsSchema, "project") + addOptionalFieldsToSchema(dsSchema, "type") + + return &schema.Resource{ + Read: dataSourceMonitoringNotificationChannelRead, + Schema: dsSchema, + } +} + +func dataSourceMonitoringNotificationChannelRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + url, err := replaceVars(d, config, "{{MonitoringBasePath}}projects/{{project}}/notificationChannels") + if err != nil { + return err + } + + displayName := d.Get("display_name").(string) + channelType := d.Get("type").(string) + + if displayName == "" && channelType == "" { + return errors.New("Must at least provide either `display_name` or `type`") + } + + filter := "" + if displayName != "" { + filter = 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 + } + } + + params := make(map[string]string) + params["filter"] = filter + + url, err = addQueryParams(url, params) + if err != nil { + return err + } + + project, err := getProject(d, config) + if err != nil { + return err + } + + response, err := sendRequest(config, "GET", project, url, nil) + if err != nil { + return fmt.Errorf("Error retrieving NotificationChannels: %s", err) + } + + var pageMonitoringNotificationChannels []interface{} + if v, ok := response["notificationChannels"]; ok { + pageMonitoringNotificationChannels = v.([]interface{}) + } + + if len(pageMonitoringNotificationChannels) == 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) + } + + res := pageMonitoringNotificationChannels[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 +} diff --git a/google/data_source_monitoring_notification_channel_test.go b/google/data_source_monitoring_notification_channel_test.go new file mode 100644 index 00000000000..2d8ecbd7ff1 --- /dev/null +++ b/google/data_source_monitoring_notification_channel_test.go @@ -0,0 +1,192 @@ +package google + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccDataSourceGoogleMonitoringNotificationChannel_byDisplayName(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleMonitoringNotificationChannel_byDisplayName(acctest.RandomWithPrefix("tf-test")), + Check: resource.ComposeTestCheckFunc( + checkDataSourceStateMatchesResourceState( + "data.google_monitoring_notification_channel.my", + "google_monitoring_notification_channel.my"), + ), + }, + }, + }) +} + +func TestAccDataSourceGoogleMonitoringNotificationChannel_byType(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleMonitoringNotificationChannel_byType(acctest.RandomWithPrefix("tf-test")), + Check: resource.ComposeTestCheckFunc( + checkDataSourceStateMatchesResourceState( + "data.google_monitoring_notification_channel.my", + "google_monitoring_notification_channel.my"), + ), + }, + }, + }) +} + +func TestAccDataSourceGoogleMonitoringNotificationChannel_byDisplayNameAndType(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleMonitoringNotificationChannel_byDisplayNameAndType(acctest.RandomWithPrefix("tf-test")), + Check: resource.ComposeTestCheckFunc( + checkDataSourceStateMatchesResourceState( + "data.google_monitoring_notification_channel.my", + "google_monitoring_notification_channel.myemail"), + ), + }, + }, + }) +} + +func TestAccDataSourceGoogleMonitoringNotificationChannel_NotFound(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)), + }, + }, + }) +} + +func TestAccDataSourceGoogleMonitoringNotificationChannel_NotUnique(t *testing.T) { + displayName := acctest.RandomWithPrefix("tf-test") + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + PreventPostDestroyRefresh: true, + 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)), + }, + }, + }) +} + +func testAccDataSourceGoogleMonitoringNotificationChannel_byDisplayName(displayName string) string { + return fmt.Sprintf(` +resource "google_monitoring_notification_channel" "my" { + display_name = "%s" + type = "webhook_tokenauth" + + labels = { + url = "http://www.acme.org" + } +} + +data "google_monitoring_notification_channel" "my" { + display_name = google_monitoring_notification_channel.my.display_name +} +`, displayName) +} + +func testAccDataSourceGoogleMonitoringNotificationChannel_byType(displayName string) string { + return fmt.Sprintf(` +resource "google_monitoring_notification_channel" "my" { + display_name = "%s" + type = "sms" + + labels = { + number = "+1555" + } +} + +data "google_monitoring_notification_channel" "my" { + type = google_monitoring_notification_channel.my.type +} +`, displayName) +} + +func testAccDataSourceGoogleMonitoringNotificationChannel_byDisplayNameAndType(displayName string) string { + return fmt.Sprintf(` +resource "google_monitoring_notification_channel" "mywebhook" { + display_name = "%s" + type = "webhook_tokenauth" + + labels = { + url = "http://www.acme.org" + } +} + +resource "google_monitoring_notification_channel" "myemail" { + display_name = google_monitoring_notification_channel.mywebhook.display_name + type = "email" + + labels = { + email_address = "mailme@acme.org" + } +} + +data "google_monitoring_notification_channel" "my" { + display_name = google_monitoring_notification_channel.myemail.display_name + type = google_monitoring_notification_channel.myemail.type +} +`, displayName) +} + +func testAccDataSourceGoogleMonitoringNotificationChannel_NotFound(displayName string) string { + return fmt.Sprintf(` +data "google_monitoring_notification_channel" "my" { + display_name = "%s" +} +`, displayName) +} + +func testAccDataSourceGoogleMonitoringNotificationChannel_NotUnique(displayName string) string { + return fmt.Sprintf(` +resource "google_monitoring_notification_channel" "default" { + display_name = "%s" + type = "webhook_tokenauth" + + labels = { + url = "http://www.acme1.org" + } +} + +resource "google_monitoring_notification_channel" "default2" { + display_name = google_monitoring_notification_channel.default.display_name + type = "webhook_tokenauth" + + labels = { + url = "http://www.acme2.org" + } +} +`, displayName) +} + +func testAccDataSourceGoogleMonitoringNotificationChannel_NotUniqueDS(displayName string) string { + return fmt.Sprintf(` +data "google_monitoring_notification_channel" "my" { + display_name = "%s" +} +`, displayName) +} diff --git a/google/provider.go b/google/provider.go index b95f77c44f2..198a1d1adce 100644 --- a/google/provider.go +++ b/google/provider.go @@ -445,6 +445,7 @@ func Provider() terraform.ResourceProvider { "google_kms_secret_ciphertext": dataSourceGoogleKmsSecretCiphertext(), "google_folder": dataSourceGoogleFolder(), "google_folder_organization_policy": dataSourceGoogleFolderOrganizationPolicy(), + "google_monitoring_notification_channel": dataSourceMonitoringNotificationChannel(), "google_netblock_ip_ranges": dataSourceGoogleNetblockIpRanges(), "google_organization": dataSourceGoogleOrganization(), "google_project": dataSourceGoogleProject(), diff --git a/website/docs/d/datasource_monitoring_notification_channel.html.markdown b/website/docs/d/datasource_monitoring_notification_channel.html.markdown new file mode 100644 index 00000000000..619148c00a7 --- /dev/null +++ b/website/docs/d/datasource_monitoring_notification_channel.html.markdown @@ -0,0 +1,99 @@ +--- +subcategory: "Stackdriver Monitoring" +layout: "google" +page_title: "Google: google_monitoring_notification_channel" +sidebar_current: "docs-google-datasource-monitoring-notification-channel" +description: |- + A NotificationChannel is a medium through which an alert is delivered + when a policy violation is detected. +--- + +# google\_monitoring\_notification\_channel + +A NotificationChannel is a medium through which an alert is delivered +when a policy violation is detected. Examples of channels include email, SMS, +and third-party messaging applications. Fields containing sensitive information +like authentication tokens or contact info are only partially populated on retrieval. + + +To get more information about NotificationChannel, see: + +* [API documentation](https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.notificationChannels) +* How-to Guides + * [Notification Options](https://cloud.google.com/monitoring/support/notification-options) + * [Monitoring API Documentation](https://cloud.google.com/monitoring/api/v3/) + + +## Example Usage - Notification Channel Basic + + +```hcl +data "google_monitoring_notification_channel" "basic" { + display_name = "Test Notification Channel" +} + +resource "google_monitoring_alert_policy" "alert_policy" { + display_name = "My Alert Policy" + notification_channels = [data.google_monitoring_notification_channel.basic.name] + combiner = "OR" + conditions { + display_name = "test condition" + condition_threshold { + filter = "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"" + duration = "60s" + comparison = "COMPARISON_GT" + aggregations { + alignment_period = "60s" + per_series_aligner = "ALIGN_RATE" + } + } + } +} + +``` + +## Argument Reference + +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: + + +* `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. + +- - - + + +* `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]`. + +* `verification_status` - + Indicates whether this channel has been verified or not. + +* `labels` - + Configuration fields that define the channel and its behavior. + +* `user_labels` - + User-supplied key/value data that does not need to conform to the corresponding NotificationChannelDescriptor's schema, unlike the labels field. + +* `description` - + An optional human-readable description of this notification channel. + +* `enabled` - + Whether notifications are forwarded to the described channel. diff --git a/website/google.erb b/website/google.erb index f2dfcf7e0d8..cfa19e9d7bb 100644 --- a/website/google.erb +++ b/website/google.erb @@ -153,6 +153,9 @@