Purpose of this file
Compute shared naming values once, and create the resource group that holds every other resource in this project.
In Azure, a resource group is a container used to organize related resources and manage them as one unit — deleting a resource group deletes everything inside it. Every resource this project creates (the database, the web app, the deployment identity) belongs to the one resource group defined here, which is what makes a full teardown with terraform destroy clean and complete.
The full file code sample
terraform/main.tflocals {
prefix = "expeditors-${var.user_name}-metals"
db_user = "metalsadmin"
db_name = "metals"
oidc_subject = coalesce(var.github_federated_subject, "repo:${var.github_subject_repository}:environment:${replace(var.github_environment, ":", "%3A")}")
}
resource "azurerm_resource_group" "metals" {
name = "${local.prefix}-rg"
location = var.location
}
The locals block shared values
A locals block computes named values once, so the rest of the project can reuse them instead of repeating the same expression — and risking a typo that makes two “identical” values quietly drift apart.
prefix = "expeditors-${var.user_name}-metals"
Builds a string like "expeditors-dzierzon-metals" by interpolating var.user_name into the middle of a fixed template using ${...} syntax. Every other file appends its own suffix to this same prefix — -rg for the resource group here, -pg for the database, -api for the web app — so all resources in one deployment are instantly recognizable as belonging together, and two different people running this project never collide on the same resource names.
Plain constants — the PostgreSQL administrator username ("metalsadmin") and database name ("metals"). They're declared once here rather than in database.tf because app_service.tf also needs both values, to build the API's database connection string.
oidc_subject = coalesce(
var.github_federated_subject,
"repo:${var.github_subject_repository}:environment:${replace(var.github_environment, ":", "%3A")}"
)
This builds the exact text string GitHub Actions must present to prove its identity (used in github_oidc.tf). Reading it from the inside out: replace(...) URL-encodes any colon inside the environment name, then the surrounding string stitches together the fixed "repo:" and ":environment:" text with the repository and environment values. coalesce() picks the first argument that isn't null — so if var.github_federated_subject was explicitly set, it's used as-is instead; otherwise the computed value is used.
The resource group the first real resource
resource "azurerm_resource_group" "metals" {
name = "${local.prefix}-rg"
location = var.location
}
resource— the keyword that tells Terraform this block describes something to actually create."azurerm_resource_group"— the Azure resource type, defined by the azurerm provider."metals"— the local name other blocks use to refer to this resource inside Terraform, as azurerm_resource_group.metals. It never appears in Azure itself.name— the actual name Azure will show, built from local.prefix plus -rg.location— which Azure region, taken straight from var.location.
Every other resource in this project (see database.tf, app_service.tf, and github_oidc.tf) references azurerm_resource_group.metals.name and .location rather than repeating local.prefix or var.location directly — one more example of defining a value once and reusing it everywhere.
Key terms for beginners
- Resource group
- An Azure container for organizing related resources and managing their lifecycle together — deleting the group deletes everything inside it.
- Local value
- A named expression computed once inside a
localsblock and reused elsewhere aslocal.<name>, similar in spirit to a variable but computed rather than supplied as input. - String interpolation
- Embedding a value inside a string with
${...}, like"expeditors-${var.user_name}-metals", instead of concatenating pieces manually. - Resource type vs. local name
- A resource block always has two labels: the Azure resource type (fixed by the provider) and a local name you choose, used only within Terraform to reference that resource elsewhere.