238 lines
11 KiB
Markdown
238 lines
11 KiB
Markdown
|
# Billing Account Module
|
||
|
|
||
|
This module allows managing resources and policies related to a billing account:
|
||
|
|
||
|
- IAM bindings
|
||
|
- log sinks
|
||
|
- billing budgets and their notifications
|
||
|
|
||
|
Managing billing-related resources via application default credentials [requires a billing project to be set](https://cloud.google.com/docs/authentication/troubleshoot-adc#user-creds-client-based). To configure one via Terraform you can use a snippet similar to this one:
|
||
|
|
||
|
```hcl
|
||
|
provider "google" {
|
||
|
billing_project = "my-project"
|
||
|
user_project_override = true
|
||
|
}
|
||
|
# tftest skip
|
||
|
```
|
||
|
|
||
|
<!-- BEGIN TOC -->
|
||
|
- [Examples](#examples)
|
||
|
- [IAM bindings](#iam-bindings)
|
||
|
- [Log sinks](#log-sinks)
|
||
|
- [Billing budgets](#billing-budgets)
|
||
|
- [PubSub update rules](#pubsub-update-rules)
|
||
|
- [Monitoring channels](#monitoring-channels)
|
||
|
- [Variables](#variables)
|
||
|
- [Outputs](#outputs)
|
||
|
<!-- END TOC -->
|
||
|
|
||
|
## Examples
|
||
|
|
||
|
### IAM bindings
|
||
|
|
||
|
Billing account IAM bindings implement [the same interface](../__docs/20230816-iam-refactor.md) used for all other modules.
|
||
|
|
||
|
```hcl
|
||
|
module "billing-account" {
|
||
|
source = "./fabric/modules/billing-account"
|
||
|
id = "012345-ABCDEF-012345"
|
||
|
group_iam = {
|
||
|
"billing-admins@example.org" = ["roles/billing.admin"]
|
||
|
}
|
||
|
iam = {
|
||
|
"roles/billing.admin" = [
|
||
|
"serviceAccount:foo@myprj.iam.gserviceaccount.com"
|
||
|
]
|
||
|
}
|
||
|
iam_bindings = {
|
||
|
conditional-admin = {
|
||
|
members = [
|
||
|
"serviceAccount:pf-dev@myprj.iam.gserviceaccount.com"
|
||
|
]
|
||
|
role = "roles/billing.admin"
|
||
|
condition = {
|
||
|
title = "pf-dev-conditional-billing-admin"
|
||
|
expression = (
|
||
|
"resource.matchTag('123456/environment', 'development')"
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
iam_bindings_additive = {
|
||
|
sa-net-iac-user = {
|
||
|
member = "serviceAccount:net-iac-0@myprj.iam.gserviceaccount.com"
|
||
|
role = "roles/billing.user"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
# tftest modules=1 resources=3 inventory=iam.yaml
|
||
|
```
|
||
|
|
||
|
### Log sinks
|
||
|
|
||
|
Billing account log sinks use the same format used for log sinks in the resource manager modules (organization, folder, project).
|
||
|
|
||
|
```hcl
|
||
|
module "log-bucket-all" {
|
||
|
source = "./fabric/modules/logging-bucket"
|
||
|
parent_type = "project"
|
||
|
parent = "myprj"
|
||
|
id = "billing-account-all"
|
||
|
}
|
||
|
|
||
|
module "billing-account" {
|
||
|
source = "./fabric/modules/billing-account"
|
||
|
id = "012345-ABCDEF-012345"
|
||
|
logging_sinks = {
|
||
|
all = {
|
||
|
destination = module.log-bucket-all.id
|
||
|
type = "logging"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
# tftest modules=2 resources=3 inventory=logging.yaml
|
||
|
```
|
||
|
|
||
|
### Billing budgets
|
||
|
|
||
|
Billing budgets expose all the attributes of the underlying resource, and allow using external notification channels, or creating them via this same module.
|
||
|
|
||
|
```hcl
|
||
|
module "billing-account" {
|
||
|
source = "./fabric/modules/billing-account"
|
||
|
id = "012345-ABCDEF-012345"
|
||
|
budgets = {
|
||
|
folder-net-month-current-100 = {
|
||
|
display_name = "100 dollars in current spend"
|
||
|
amount = {
|
||
|
units = 100
|
||
|
}
|
||
|
filter = {
|
||
|
period = {
|
||
|
calendar = "MONTH"
|
||
|
}
|
||
|
resource_ancestors = ["folders/1234567890"]
|
||
|
}
|
||
|
threshold_rules = [
|
||
|
{ percent = 0.5 },
|
||
|
{ percent = 0.75 }
|
||
|
]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
# tftest modules=1 resources=1 inventory=budget-simple.yaml
|
||
|
```
|
||
|
|
||
|
#### PubSub update rules
|
||
|
|
||
|
Update rules can notify pubsub topics.
|
||
|
|
||
|
```hcl
|
||
|
module "pubsub-billing-topic" {
|
||
|
source = "./fabric/modules/pubsub"
|
||
|
project_id = "my-prj"
|
||
|
name = "budget-default"
|
||
|
}
|
||
|
|
||
|
module "billing-account" {
|
||
|
source = "./fabric/modules/billing-account"
|
||
|
id = "012345-ABCDEF-012345"
|
||
|
budgets = {
|
||
|
folder-net-month-current-100 = {
|
||
|
display_name = "100 dollars in current spend"
|
||
|
amount = {
|
||
|
units = 100
|
||
|
}
|
||
|
filter = {
|
||
|
period = {
|
||
|
calendar = "MONTH"
|
||
|
}
|
||
|
resource_ancestors = ["folders/1234567890"]
|
||
|
}
|
||
|
threshold_rules = [
|
||
|
{ percent = 0.5 },
|
||
|
{ percent = 0.75 }
|
||
|
]
|
||
|
update_rules = {
|
||
|
default = {
|
||
|
pubsub_topic = module.pubsub-billing-topic.id
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
# tftest modules=2 resources=2 inventory=budget-pubsub.yaml
|
||
|
```
|
||
|
|
||
|
#### Monitoring channels
|
||
|
|
||
|
Monitoring channels can be referenced in update rules either by passing in an existing channel id, or by using a reference to a key in the `budget_notification_channels` variable, that allows managing ad hoc monitoring channels.
|
||
|
|
||
|
<!-- markdownlint-disable MD034 -->
|
||
|
|
||
|
```hcl
|
||
|
module "billing-account" {
|
||
|
source = "./fabric/modules/billing-account"
|
||
|
id = "012345-ABCDEF-012345"
|
||
|
budget_notification_channels = {
|
||
|
billing-default = {
|
||
|
project_id = "tf-playground-simple"
|
||
|
type = "email"
|
||
|
labels = {
|
||
|
email_address = "gcp-billing-admins@example.com"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
budgets = {
|
||
|
folder-net-month-current-100 = {
|
||
|
display_name = "100 dollars in current spend"
|
||
|
amount = {
|
||
|
units = 100
|
||
|
}
|
||
|
filter = {
|
||
|
period = {
|
||
|
calendar = "MONTH"
|
||
|
}
|
||
|
resource_ancestors = ["folders/1234567890"]
|
||
|
}
|
||
|
threshold_rules = [
|
||
|
{ percent = 0.5 },
|
||
|
{ percent = 0.75 }
|
||
|
]
|
||
|
update_rules = {
|
||
|
default = {
|
||
|
disable_default_iam_recipients = true
|
||
|
monitoring_notification_channels = ["billing-default"]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
# tftest modules=1 resources=2 inventory=budget-monitoring-channel.yaml
|
||
|
```
|
||
|
|
||
|
<!-- markdownlint-enable -->
|
||
|
<!-- BEGIN TFDOC -->
|
||
|
## Variables
|
||
|
|
||
|
| name | description | type | required | default |
|
||
|
|---|---|:---:|:---:|:---:|
|
||
|
| [id](variables.tf#L165) | Billing account id. | <code>string</code> | ✓ | |
|
||
|
| [budget_notification_channels](variables.tf#L17) | Notification channels used by budget alerts. | <code title="map(object({ project_id = string type = string description = optional(string) display_name = optional(string) enabled = optional(bool, true) force_delete = optional(bool) labels = optional(map(string)) sensitive_labels = optional(list(object({ auth_token = optional(string) password = optional(string) service_key = optional(string) }))) user_labels = optional(map(string)) }))">map(object({…}))</code> | | <code>{}</code> |
|
||
|
| [budgets](variables.tf#L47) | Billing budgets. Notification channels are either keys in corresponding variable, or external ids. | <code title="map(object({ amount = object({ currency_code = optional(string) nanos = optional(number) units = optional(number) use_last_period = optional(bool) }) display_name = optional(string) filter = optional(object({ credit_types_treatment = optional(object({ exclude_all = optional(bool) include_specified = optional(list(string)) })) label = optional(object({ key = string value = string })) period = optional(object({ calendar = optional(string) custom = optional(object({ start_date = object({ day = number month = number year = number }) end_date = optional(object({ day = number month = number year = number })) })) })) projects = optional(list(string)) resource_ancestors = optional(list(string)) services = optional(list(string)) subaccounts = optional(list(string)) })) threshold_rules = optional(list(object({ percent = number forecasted_spend = optional(bool) })), []) update_rules = optional(map(object({ disable_default_iam_recipients = optional(bool) monitoring_notification_channels = optional(list(string)) pubsub_topic = optional(string) })), {}) }))">map(object({…}))</code> | | <code>{}</code> |
|
||
|
| [group_iam](variables.tf#L121) | Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||
|
| [iam](variables.tf#L128) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||
|
| [iam_bindings](variables.tf#L135) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | <code title="map(object({ members = list(string) role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||
|
| [iam_bindings_additive](variables.tf#L150) | Individual additive IAM bindings. Keys are arbitrary. | <code title="map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||
|
| [logging_sinks](variables.tf#L170) | Logging sinks to create for the organization. | <code title="map(object({ destination = string type = string bq_partitioned_table = optional(bool) description = optional(string) disabled = optional(bool, false) exclusions = optional(map(object({ filter = string description = optional(string) disabled = optional(bool) })), {}) filter = optional(string) }))">map(object({…}))</code> | | <code>{}</code> |
|
||
|
| [projects](variables.tf#L203) | Projects associated with this billing account. | <code>list(string)</code> | | <code>[]</code> |
|
||
|
|
||
|
## Outputs
|
||
|
|
||
|
| name | description | sensitive |
|
||
|
|---|---|:---:|
|
||
|
| [billing_budget_ids](outputs.tf#L17) | Billing budget ids. | |
|
||
|
| [monitoring_notification_channel_ids](outputs.tf#L25) | Monitoring notification channel ids. | |
|
||
|
<!-- END TFDOC -->
|