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.