Skip to main content

Business Unit Module (terraform-platform-create-business-unit)

The business unit module orchestrates the creation of all infrastructure needed for a new business unit within the Badal Foundations platform. It provisions GCP folders across environments, a shared WIF host project, a GitHub repository pre-populated with scaffold code, and a Terraform Cloud workspace.

What It Creates​

When you invoke this module, it provisions the following resources:

  1. GCP folders for each configured environment (e.g., fldr-development, fldr-non-production, fldr-production) placed under the corresponding foundation environment folders
  2. A common folder ({business_unit}-{suffix}) under fldr-common containing a WIF host project (wif-host-{suffix})
  3. A GitHub repository (bu-{name}-{suffix}) pre-populated with scaffold Terraform files
  4. A TFC project and workspace configured with VCS integration to the new repo

Resource Relationship Diagram​

create-business-unit module
├── google_folder.environment_folders (per env)
│ └── e.g., data-80r13 under fldr-development
├── google_folder.common_folder
│ └── wif-host-{suffix} (GCP project via project-factory)
├── module.repository (integrated_repository/github)
│ ├── GitHub repo: bu-{name}-{suffix}
│ ├── TFC project + workspace
│ └── WIF + cross-env service account
└── github_repository_file (scaffold files)
├── backstage-manifest.json
├── terraform/main.tf
├── terraform/variables.tf
├── terraform/outputs.tf
├── terraform/shared.tf
├── terraform/gar.tf (conditional)
└── terraform/tenants/main.tf

Naming Convention​

All resources use a randomly generated 5-character alphanumeric suffix to ensure uniqueness:

ResourceNaming PatternExample
GitHub repositorybu-{business_unit}-{suffix}bu-data-80r13
Environment folders{business_unit}-{suffix}data-80r13
Common folder{business_unit}-{suffix}data-80r13
WIF host projectwif-host-{suffix}wif-host-80r13
TFC workspacebu-{business_unit}-c-{suffix}bu-data-c-80r13

The suffix is generated via random_string (lowercase letters + digits, 5 characters).

Key Variables​

VariableTypeRequiredDefaultDescription
business_unitstringYes-Business unit name (1-20 chars, lowercase, starts with letter)
environmentsmap(object)Yes-Map of environments to GCP folder configuration. Each entry requires org_id, billing_account_id, parent_folder_id, and optional vpc_subnet_project_id
single_workspaceobjectYes-Configuration for the shared WIF host project: org_id, billing_account_id, parent_folder_id, service_account_roles
gh_orgstringYes-GitHub organization name
gh_appobjectYes-GitHub App credentials: id, installation_id, private_key
tfcobjectYes-Terraform Cloud config: org_id, gh_app_oauth_id, token, enable (optional, default true)
garobjectNo{ enable = false }Google Artifact Registry config: enable, location (default us-central1), artifact_types (DOCKER, MAVEN, NPM, PYTHON, APT, YUM, GO)
templateobjectNo{ owner = "badal-io", repository = "Business-Unit-Template" }Template repository for scaffold code
shared_tenant_templateobjectNonullTemplate repository for the shared tenant created by the BU
teamsmap(object)No{}GitHub teams to grant permissions (admin, write, triage, maintain, read)
topicslist(string)No[]Additional GitHub topics (merged with business-unit, backstage-catalog)
foundations_accessobjectNo{ enable = false }Access to foundation remote state: enable, bucket_name, enable_shared_vpc_subnets

Key Outputs​

OutputDescription
environment_foldersGCP folders created for each environment (folder ID, display name)
common_folderThe shared GCP folder containing the WIF host project
repositoryGitHub repository details (name, URL, default branch)
terraform_projectTFC project details (sensitive)
terraform_workspacesTFC workspace details (single workspace mode)
environmentsEnvironment configuration including WIF provider and service account
wif_host_projectWIF host project details (project_id, project_number, project_name)

WIF Architecture (Cross-Environment)​

Business units use a single workspace / cross-environment WIF pattern. This means:

  • One WIF host project is created in the common folder
  • One service account has access to all environment folders plus the common folder
  • The single TFC workspace uses this SA to manage resources across all environments
  • Roles specified in single_workspace.service_account_roles are granted on each environment folder and the common folder

This differs from tenants, which use per-environment WIF with separate service accounts.

Scaffold Files​

The module pushes the following files into the newly created GitHub repository:

backstage-manifest.json​

Machine-readable metadata used by Backstage to discover and catalog the business unit. Contains repository info, WIF configuration, folder IDs, environment mappings, and GAR settings.

terraform/main.tf​

Pre-configured Terraform root module with the suffix, environment folder IDs, and GAR settings baked in. Used as the entry point for managing tenants.

terraform/variables.tf​

Variable declarations matching the scaffolded main.tf, including environment-specific folder and org configurations.

terraform/outputs.tf​

Output declarations for tenant information and optional GAR repository details.

terraform/shared.tf​

Shared tenant configuration including the shared tenant template and team permissions.

terraform/gar.tf (conditional)​

Only created when gar.enable = true and artifact_types is non-empty. Configures BU-level virtual repositories that aggregate tenant GAR repositories.

terraform/tenants/main.tf​

Entry point for defining individual tenants within the business unit. This is where teams add create-tenant module calls.

terraform/tenants/variables.tf​

Variable definitions for tenant creation, pre-populated with the BU suffix and environment configuration.

terraform/tenants/remote.tf (conditional)​

Only created when foundations_access.enable = true. Provides remote state access to foundation layers for reading VPC subnets and other shared infrastructure.

GAR Configuration​

When GAR is enabled, the module creates virtual repositories at the BU level that aggregate tenant-level standard repositories via upstream policies.

gar = {
enable = true
location = "us-central1"
artifact_types = ["DOCKER", "NPM"]
}

Supported artifact types: DOCKER, MAVEN, NPM, PYTHON, APT, YUM, GO.

The tiered GAR architecture works as follows:

  1. Tenant-level: Standard repositories per environment per artifact type (created by the tenant module)
  2. BU-level standard repos: In the shared tenant project, standard repositories for BU-wide artifacts
  3. BU-level virtual repos: Virtual repositories that aggregate all tenant + shared repos via upstream policies, providing a single pull endpoint

Usage Example​

module "business_unit" {
source = "app.terraform.io/Badal_devex/create-business-unit/platform"
version = "~> 1.0"

business_unit = "data"
gh_org = "badal-io"

environments = {
development = {
org_id = "758951886862"
billing_account_id = "01DEF7-F9833E-AD765A"
parent_folder_id = "folders/123456789" # fldr-development
}
non-production = {
org_id = "758951886862"
billing_account_id = "01DEF7-F9833E-AD765A"
parent_folder_id = "folders/234567890" # fldr-non-production
}
production = {
org_id = "758951886862"
billing_account_id = "01DEF7-F9833E-AD765A"
parent_folder_id = "folders/345678901" # fldr-production
}
}

single_workspace = {
org_id = "758951886862"
billing_account_id = "01DEF7-F9833E-AD765A"
parent_folder_id = "folders/456789012" # fldr-common
service_account_roles = ["roles/resourcemanager.folderAdmin"]
}

tfc = {
org_id = "Badal_devex"
gh_app_oauth_id = "ot-xxxxxxxxxxxxx"
token = var.tfc_token
}

gh_app = {
id = "123456"
installation_id = "12345678"
private_key = var.github_app_private_key
}

gar = {
enable = true
location = "us-central1"
artifact_types = ["DOCKER", "PYTHON"]
}
}

Deployed Business Units​

Business UnitSuffixRepoEnvironmentsGAR
data80r13bu-data-80r13dev, non-prod, prodDOCKER, PYTHON
devex9c9dlbu-devex-9c9dlnon-prod, prodDOCKER, NPM
platform0r4dpbu-platform-0r4dpdev, non-prod, prodNone

Data BU (80r13)​

The data business unit is the largest, with 346 TFC-managed resources. It has GAR enabled for Docker and Python artifacts, and hosts tenants including governance and template.

DevEx BU (9c9dl)​

The developer experience business unit runs in non-production and production only (no development environment). It has GAR for Docker and NPM, supporting the Backstage portal and related tooling.

Platform BU (0r4dp)​

The platform business unit manages foundational platform services including the GKE ArgoCD tenant. It does not use GAR.