-
Notifications
You must be signed in to change notification settings - Fork 708
Start with Required Attributes
It is advisable to first create the directories and files for the new module before developing the module and examples. This page covers the following:
- Directory structure
- Upgrade provider version if needed
- Add Examples
- Connect the files
- Implement the resource with the required attributes
- Integrate the output with the local combined object
The following structure shows all the files that are relevant for this feature. Some of these files already exist in the repository. Essentially the new files and directories that must be created are:
- examples/consumption_budget/100-consumption-budget-rg/configuration.tfvars
- modules/consumption_budget/*
- consumption_budgets.tf
├───.github
│ └───workflows
│ └───standalone-scenarios.json
├───examples
│ |───consumption_budget
│ | └───100-consumption-budget-rg
| | └───configuration.tfvars
│ |───module.tf
│ └───variables.tf
│───modules
│ └───consumption_budget
│ └───resource_group
│ ├───main.tf
│ ├───output.tf
│ ├───resource_group_budget.tf
│ └───variables.tf
│───consumption_budgets.tf
│───main.tf
│───locals.combined_objects.tf
└───locals.tf
In the previous section, it was identified that the azurerm
version needed to be 2.61.0
. This is changed in the main.tf
file at the root level
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 2.61.0"
}
}
}
Start with the examples/consumption_budget/100-consumption-budget-rg/configuration.tfvars
file, implementing only the required attributes for a start. An example is:
global_settings = {
default_region = "region1"
regions = {
region1 = "southeastasia"
}
random_length = 5
}
resource_groups = {
test = {
name = "test"
}
}
consumption_budgets = {
test_budget = {
resource_group = {
# accepts either id or key to get resource group id
# id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1"
key = "test"
}
name = "example"
amount = 1000
time_grain = "Monthly"
time_period = {
# uncomment to customize start_date
# start_date = "2022-06-01T00:00:00Z"
}
notifications = {
contact_email = {
enabled = true
threshold = 90.0
operator = "EqualTo"
contact_emails = [
"foo@example.com",
"bar@example.com",
]
}
}
}
}
Notice that contact_email
is added as an example although it is optional. This is because at apply
time, Terraform produces an error if there isn't an instance of either contact_emails
, contact_groups
, or contact_roles
.
examples
variables.tf
variable "consumption_budgets" {
default = {}
}
- Accepts the variables from the
configuration.tfvars
file defined earlier
module.tf
module "example" {
source = "../.."
# truncated
shared_services = {
consumption_budgets = var.consumption_budgets
# truncated
}
}
root
locals.tf
locals {
# truncated
shared_services = {
consumption_budgets = try(var.shared_services.consumption_budgets, {})
# truncated
}
}
consumption_budgets.tf
module "consumption_budgets" {
source = "./modules/consumption_budget"
for_each = local.shared_services.consumption_budgets
resource_group_id = coalesce(
try(local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][each.value.resource_group.key].id, null),
try(each.value.resource_group.id, null)
)
settings = each.value
}
- The
for_each
iterates through each individualconsumption_budget
inconsumption_budgets
and maps those values tosettings
. Thissettings
is important for referencing individual variables in the resource. - The pattern for
resource_group_id
allows theid
to be retrieved from an attribute calledresource_group.key
orresource_group.id
defined in theconfiguration.tfvars
file
This is done in the modules directory
modules/consumption_budget
variables.tf
variable "settings" {
description = "Configuration object for the consumption budget resource group"
}
variable "resource_group_id" {
description = "The ID of the Resource Group to create the consumption budget for in the form of /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1"
type = string
}
resource_group_budget.tf
resource "azurerm_consumption_budget_resource_group" "this" {
name = var.settings.name
resource_group_id = var.resource_group_id
amount = var.settings.amount
time_grain = var.settings.time_grain
time_period {
start_date = try(var.settings.time_period.start_date, join("", [formatdate("YYYY-MM", timestamp()), "-01T00:00:00Z"]))
end_date = try(var.settings.time_period.end_date, null)
}
dynamic "notification" {
for_each = var.settings.notifications
content {
operator = notification.value.operator
threshold = notification.value.threshold
contact_emails = try(notification.value.contact_emails, [])
contact_roles = try(notification.value.contact_roles, [])
enabled = try(notification.value.enabled, true)
}
}
}
- Implement the attributes that allow the variables from the
configuration.tfvars
file to be injected. The injection comes fromvar.settings
-
time_period
is specified in the Terraform Registry documentation as a single required block. -
notification
is defined as a required block that can have multiple instances
output.tf
output "id" {
description = "The ID of the Resource Group Consumption Budget"
value = azurerm_consumption_budget_resource_group.this.id
}
With the output exported from the modules
directory, export it at the root level as well.
consumption_budgets.tf
output "consumption_budgets_resource_groups" {
value = module.consumption_budgets_resource_groups
}
With that exported, integrate it with locals.combined_objects.tf
locals.combined_objects.tf
locals {
combined_objects_consumption_budgets_resource_groups = merge(tomap({ (local.client_config.landingzone_key) = module.consumption_budgets_resource_groups }), try(var.remote_objects.consumption_budgets_resource_groups, {}))
}