Skip to content

Commit

Permalink
Merge pull request #58 from GoogleCloudPlatform/billing-budget-alert
Browse files Browse the repository at this point in the history
RAD Lab Module to create GCP Projects with Billing budgets
  • Loading branch information
debakkerb authored May 17, 2022
2 parents 36c4923 + 577ae85 commit 1fa93ee
Show file tree
Hide file tree
Showing 6 changed files with 357 additions and 0 deletions.
Binary file added docs/images/V7_Billing_Budget.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 69 additions & 0 deletions modules/billing_budget/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# RAD Lab Billing Budget Module

This module creates a simple GCP project, enables APIs, adds users to the project and also creates a Billing Budget for the Project.

## GCP Products/Services

* GCP Project
* APIs & Services
* Billing Budget

## Reference Architecture Diagram

Below Architechture Diagram is the base representation of what will be created as a part of [RAD Lab Launcher](../../radlab-launcher/radlab.py).

![](../../docs/images/V7_Billing_Budget.png)

## API Prerequisites

In the RAD Lab Management Project make sure that _Cloud Billing Budget API (`billingbudgets.googleapis.com`)_ is enabled.

## IAM Permissions Prerequisites

Create a Terraform Service Account in RAD Lab Management Project to execute / deploy the RAD Lab module. Ensure that the Service Account has the following IAM permissions, **when creating the project** (`create_project` = true):

- Parent: `roles/resourcemanager.projectCreator`
- Parent: `roles/billing.user`
- Parent: `roles/billing.costsManager`

The User, Group, or Service Account who will be deploying the module should have access to impersonate and grant it the roles, `roles/iam.serviceAccountTokenCreator` on the **Terraform Service Account’s IAM Policy**.

Note: This is not a Project IAM Binding; this is a **Service Account** IAM Binding.

NOTE: Additional [permissions](../../radlab-launcher/README.md#iam-permissions-prerequisites) are required when deploying the RAD Lab modules via [RAD Lab Launcher](../../radlab-launcher). Use `--disable-perm-check` or `-dc` arguments when using RAD lab Launcher for the module deployment.

_Usage:_

```python3 radlab.py --disable-perm-check```


<!-- BEGIN TFDOC -->
## Variables

| name | description | type | required | default |
|---|---|:---: |:---:|:---:|
| billing_account_id | Billing Account associated to the GCP Resources | <code title="">string</code> || |
| *apis* | The list of GCP apis to enable. | <code title="set&#40;string&#41;">set(string)</code> | | <code title="">["compute.googleapis.com","bigquery.googleapis.com","bigquerystorage.googleapis.com"]</code> |
| *billing_budget_alert_spend_basis* | The type of basis used to determine if spend has passed the threshold | <code title="">string</code> | | <code title="">CURRENT_SPEND</code> |
| *billing_budget_alert_spent_percents* | A list of percentages of the budget to alert on when threshold is exceeded | <code title="list&#40;number&#41;">list(number)</code> | | <code title="">[0.5,0.7,1]</code> |
| *billing_budget_amount* | The amount to use as the budget in USD | <code title="">number</code> | | <code title="">1000</code> |
| *billing_budget_credit_types_treatment* | Specifies how credits should be treated when determining spend for threshold calculations | <code title="">string</code> | | <code title="">INCLUDE_ALL_CREDITS</code> |
| *billing_budget_labels* | A single label and value pair specifying that usage from only this set of labeled resources should be included in the budget. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="&#123;&#125;&#10;validation &#123;&#10;condition &#61; length&#40;var.billing_budget_labels&#41; &#60;&#61; 1&#10;error_message &#61; &#34;Only 0 or 1 labels may be supplied for the budget filter.&#34;&#10;&#125;">...</code> |
| *billing_budget_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/ | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">null</code> |
| *create_project* | Set to true if the module has to create a project. If you want to deploy in an existing project, set this variable to false. | <code title="">bool</code> | | <code title="">true</code> |
| *enable_services* | Enable the necessary APIs on the project. When using an existing project, this can be set to false. | <code title="">bool</code> | | <code title="">true</code> |
| *folder_id* | Folder ID where the project should be created. It can be skipped if already setting organization_id. Leave blank if the project should be created directly underneath the Organization node. | <code title="">string</code> | | <code title=""></code> |
| *organization_id* | Organization ID where GCP Resources need to get spin up. It can be skipped if already setting folder_id | <code title="">string</code> | | <code title=""></code> |
| *project_name* | Project name or ID, if it's an existing project. | <code title="">string</code> | | <code title="">radlab-billing-budget</code> |
| *random_id* | Adds a suffix of 4 random characters to the `project_id` | <code title="">string</code> | | <code title="">null</code> |
| *resource_creator_identity* | Terraform Service Account which will be creating the GCP resources | <code title="">string</code> | | <code title=""></code> |
| *trusted_users* | The list of trusted users who will be assigned Editor role on the project | <code title="set&#40;string&#41;">set(string)</code> | | <code title="">[]</code> |

## Outputs

| name | description | sensitive |
|---|---|:---:|
| billing_budget_budgetId | Resource name of the budget. Values are of the form `billingAccounts/{billingAccountId}/budgets/{budgetId}` | |
| deployment_id | RADLab Module Deployment ID | |
| project-radlab-billing-budget-id | GCP Project ID | |
<!-- END TFDOC -->
120 changes: 120 additions & 0 deletions modules/billing_budget/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


provider "google" {
alias = "impersonated"
scopes = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email"
]
}

data "google_service_account_access_token" "default" {
provider = google.impersonated
scopes = ["userinfo-email", "cloud-platform"]
target_service_account = var.resource_creator_identity
lifetime = "1800s"
}

provider "google" {
access_token = data.google_service_account_access_token.default.access_token
}

provider "google-beta" {
access_token = data.google_service_account_access_token.default.access_token
}


locals {
random_id = var.random_id != null ? var.random_id : random_id.default.hex
project = (var.create_project
? try(module.project_radlab_billing_budget.0, null)
: try(data.google_project.existing_project.0, null)
)

project_services = var.enable_services ? var.apis : []
}

resource "random_id" "default" {
byte_length = 2
}

###############
# GCP PROJECT #
###############

data "google_project" "existing_project" {
count = var.create_project ? 0 : 1
project_id = var.project_name
}

module "project_radlab_billing_budget" {
count = var.create_project ? 1 : 0
source = "terraform-google-modules/project-factory/google"
version = "~> 11.0"

name = format("%s-%s", var.project_name, local.random_id)
random_project_id = false
folder_id = var.folder_id
billing_account = var.billing_account_id
org_id = var.organization_id

activate_apis = []
}


resource "google_project_service" "enabled_services" {
for_each = toset(local.project_services)
project = local.project.project_id
service = each.value
disable_dependent_services = true
disable_on_destroy = true
}

resource "time_sleep" "wait_120_seconds" {
count = var.enable_services ? 1 : 0
create_duration = "120s"

depends_on = [
google_project_service.enabled_services
]
}

module "billing_budget" {
source = "terraform-google-modules/project-factory/google//modules/budget"
display_name = format("RADLab Billing Budget - %s", local.project.project_id)
billing_account = var.billing_account_id
projects = ["${local.project.project_id}"]
amount = var.billing_budget_amount
alert_spend_basis = var.billing_budget_alert_spend_basis
alert_spent_percents = var.billing_budget_alert_spent_percents
credit_types_treatment = var.billing_budget_credit_types_treatment
labels = var.billing_budget_labels
services = var.billing_budget_services

depends_on = [
time_sleep.wait_120_seconds
]

}

resource "google_project_iam_member" "user_role_assignment" {
for_each = var.trusted_users
project = local.project.project_id
member = each.value
role = "roles/editor"
}
30 changes: 30 additions & 0 deletions modules/billing_budget/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

output "deployment_id" {
description = "RADLab Module Deployment ID"
value = local.random_id
}

output "project-radlab-billing-budget-id" {
description = "GCP Project ID"
value = local.project.project_id
}

output "billing_budget_budgetId" {
description = "Resource name of the budget. Values are of the form `billingAccounts/{billingAccountId}/budgets/{budgetId}`"
value = module.billing_budget.name
}
114 changes: 114 additions & 0 deletions modules/billing_budget/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

variable "apis" {
description = "The list of GCP apis to enable."
type = set(string)
default = ["compute.googleapis.com","bigquery.googleapis.com","bigquerystorage.googleapis.com"]
}

variable "billing_account_id" {
description = "Billing Account associated to the GCP Resources"
type = string
}

variable "billing_budget_alert_spend_basis" {
description = "The type of basis used to determine if spend has passed the threshold"
type = string
default = "CURRENT_SPEND"
}

variable "billing_budget_alert_spent_percents" {
description = "A list of percentages of the budget to alert on when threshold is exceeded"
type = list(number)
default = [0.5,0.7,1]
}

variable "billing_budget_amount" {
description = "The amount to use as the budget in USD"
type = number
default = 1000
}

variable "billing_budget_credit_types_treatment" {
description = "Specifies how credits should be treated when determining spend for threshold calculations"
type = string
default = "INCLUDE_ALL_CREDITS"
}

variable "billing_budget_labels" {
description = "A single label and value pair specifying that usage from only this set of labeled resources should be included in the budget."
type = map(string)
default = {}
validation {
condition = length(var.billing_budget_labels) <= 1
error_message = "Only 0 or 1 labels may be supplied for the budget filter."
}
}

variable "billing_budget_services" {
description = "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/"
type = list(string)
default = null
}

variable "create_project" {
description = "Set to true if the module has to create a project. If you want to deploy in an existing project, set this variable to false."
type = bool
default = true
}

variable "enable_services" {
description = "Enable the necessary APIs on the project. When using an existing project, this can be set to false."
type = bool
default = true
}

variable "folder_id" {
description = "Folder ID where the project should be created. It can be skipped if already setting organization_id. Leave blank if the project should be created directly underneath the Organization node. "
type = string
default = ""
}

variable "organization_id" {
description = "Organization ID where GCP Resources need to get spin up. It can be skipped if already setting folder_id"
type = string
default = ""
}

variable "project_name" {
description = "Project name or ID, if it's an existing project."
type = string
default = "radlab-billing-budget"
}

variable "random_id" {
description = "Adds a suffix of 4 random characters to the `project_id`"
type = string
default = null
}

variable "resource_creator_identity" {
description = "Terraform Service Account which will be creating the GCP resources"
type = string
default = ""
}

variable "trusted_users" {
description = "The list of trusted users who will be assigned Editor role on the project"
type = set(string)
default = []
}
24 changes: 24 additions & 0 deletions modules/billing_budget/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

terraform {
required_version = "~> 1.0"

required_providers {
google = ">= 3.87.0"
google-beta = ">= 3.87.0"
}
}

0 comments on commit 1fa93ee

Please sign in to comment.