From 9bc317e763f767d5666f6876fdae91b3e9a6b200 Mon Sep 17 00:00:00 2001
From: David Holsgrove <davidholsgrove@users.noreply.github.com>
Date: Wed, 23 Sep 2020 10:03:43 +1000
Subject: [PATCH] feat: Add budget notification channel (#456)

---
 README.md                   |  1 +
 main.tf                     | 11 ++++++-----
 modules/budget/README.md    |  1 +
 modules/budget/main.tf      | 12 +++++++-----
 modules/budget/variables.tf |  6 ++++++
 variables.tf                |  6 ++++++
 6 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 6524759c..8b1db234 100644
--- a/README.md
+++ b/README.md
@@ -120,6 +120,7 @@ determining that location is as follows:
 | budget\_alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` | string | `"null"` | no |
 | budget\_alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | list(number) | `<list>` | no |
 | budget\_amount | The amount to use for a budget alert | number | `"null"` | no |
+| budget\_monitoring\_notification\_channels | A list of monitoring notification channels in the form `[projects/{project_id}/notificationChannels/{channel_id}]`. A maximum of 5 channels are allowed. | list(string) | `<list>` | no |
 | credentials\_path | Path to a service account credentials file with rights to run the Project Factory. If this file is absent Terraform will fall back to Application Default Credentials. | string | `""` | no |
 | default\_service\_account | Project default service account setting: can be one of `delete`, `deprivilege`, `disable`, or `keep`. | string | `"disable"` | no |
 | disable\_dependent\_services | Whether services that are enabled and which depend on this service should also be disabled when this service is destroyed. | bool | `"true"` | no |
diff --git a/main.tf b/main.tf
index 640324ac..8f5c6137 100644
--- a/main.tf
+++ b/main.tf
@@ -72,9 +72,10 @@ module "budget" {
   source        = "./modules/budget"
   create_budget = var.budget_amount != null
 
-  projects             = [module.project-factory.project_id]
-  billing_account      = var.billing_account
-  amount               = var.budget_amount
-  alert_spent_percents = var.budget_alert_spent_percents
-  alert_pubsub_topic   = var.budget_alert_pubsub_topic
+  projects                         = [module.project-factory.project_id]
+  billing_account                  = var.billing_account
+  amount                           = var.budget_amount
+  alert_spent_percents             = var.budget_alert_spent_percents
+  alert_pubsub_topic               = var.budget_alert_pubsub_topic
+  monitoring_notification_channels = var.budget_monitoring_notification_channels
 }
diff --git a/modules/budget/README.md b/modules/budget/README.md
index 06f5031a..b4de9630 100644
--- a/modules/budget/README.md
+++ b/modules/budget/README.md
@@ -27,6 +27,7 @@ module "project_myproject" {
 | create\_budget | If the budget should be created | bool | `"true"` | no |
 | credit\_types\_treatment | Specifies how credits should be treated when determining spend for threshold calculations | string | `"INCLUDE_ALL_CREDITS"` | no |
 | display\_name | The display name of the budget. If not set defaults to `Budget For <projects[0]|All Projects>` | string | `"null"` | no |
+| monitoring\_notification\_channels | A list of monitoring notification channels in the form `[projects/{project_id}/notificationChannels/{channel_id}]`. A maximum of 5 channels are allowed. | list(string) | `<list>` | no |
 | projects | The project ids to include in this budget. If empty budget will include all projects | list(string) | n/a | yes |
 | services | A list of services ids to be included in the budget. If omitted, all services will be included in the budget. Service ids can be found at https://cloud.google.com/skus/ | list(string) | `"null"` | no |
 
diff --git a/modules/budget/main.tf b/modules/budget/main.tf
index b151baa0..45bad8b3 100644
--- a/modules/budget/main.tf
+++ b/modules/budget/main.tf
@@ -15,9 +15,10 @@
  */
 
 locals {
-  project_name  = length(var.projects) == 0 ? "All Projects" : var.projects[0]
-  display_name  = var.display_name == null ? "Budget For ${local.project_name}" : var.display_name
-  pubsub_topics = var.alert_pubsub_topic == null ? [] : [var.alert_pubsub_topic]
+  project_name     = length(var.projects) == 0 ? "All Projects" : var.projects[0]
+  display_name     = var.display_name == null ? "Budget For ${local.project_name}" : var.display_name
+  all_updates_rule = var.alert_pubsub_topic == null && var.monitoring_notification_channels == null ? [] : ["1"]
+
   projects = length(var.projects) == 0 ? null : [
     for id in var.projects :
     "projects/${id}"
@@ -55,9 +56,10 @@ resource "google_billing_budget" "budget" {
   }
 
   dynamic "all_updates_rule" {
-    for_each = local.pubsub_topics
+    for_each = local.all_updates_rule
     content {
-      pubsub_topic = all_updates_rule.value
+      pubsub_topic                     = var.alert_pubsub_topic
+      monitoring_notification_channels = var.monitoring_notification_channels
     }
   }
 }
diff --git a/modules/budget/variables.tf b/modules/budget/variables.tf
index fb89b232..0112bbcc 100644
--- a/modules/budget/variables.tf
+++ b/modules/budget/variables.tf
@@ -64,3 +64,9 @@ variable "alert_pubsub_topic" {
   type        = string
   default     = null
 }
+
+variable "monitoring_notification_channels" {
+  description = "A list of monitoring notification channels in the form `[projects/{project_id}/notificationChannels/{channel_id}]`. A maximum of 5 channels are allowed."
+  type        = list(string)
+  default     = []
+}
diff --git a/variables.tf b/variables.tf
index 7956d5fb..93f46178 100644
--- a/variables.tf
+++ b/variables.tf
@@ -212,6 +212,12 @@ variable "budget_alert_pubsub_topic" {
   default     = null
 }
 
+variable "budget_monitoring_notification_channels" {
+  description = "A list of monitoring notification channels in the form `[projects/{project_id}/notificationChannels/{channel_id}]`. A maximum of 5 channels are allowed."
+  type        = list(string)
+  default     = []
+}
+
 variable "budget_alert_spent_percents" {
   description = "A list of percentages of the budget to alert on when threshold is exceeded"
   type        = list(number)