Skip to content

Terraform & GitHub Actions — Beginner Guide (raas-azure-terraform-v2)

A plain‑English tour of the repo you shared. This explains what each part does , how config flows into Terraform , and how the GitHub Actions pipeline runs — with tips for first‑time users.


0) Big Picture

  • Goal: Provision and manage customer infrastructure on Azure using Terraform.

  • Inputs: Customer config files under configs/ (per tenant and per customer), plus environment tfvars.

  • Engine: Terraform modules (some included here; others are Git submodules) that create Azure resources.

  • Automation: GitHub Actions workflows to plan/apply/destroy per customer & environment.


1) Repository Layout (high level)

raas-azure-terraform-v2
├─ configs/                # Where customer/tenant configs live (this drives deployments)
│  ├─ m42/                 # Multi-tenant examples
│  ├─ raas/                # Multi-tenant examples
│  ├─ mubadala/            # Example customer folder (env json + tfvars)
│  └─ ...
├─ base-vpn/               # Example module (others are submodules)
├─ base-account/           # (submodule)
├─ base-connectivity/      # (submodule)
├─ base-core/              # (submodule)
├─ base-counter/           # (submodule)
├─ base-cifs/              # (submodule)
├─ env-raas/               # (submodule)
├─ env-snapshots/          # (submodule)
├─ scripts/                # Helper scripts (e.g., Cosmos DB query)
└─ .github/workflows/      # Plan/Apply/Destroy workflows + security checks

Many base-* and env-* directories are Git submodules. The repo pins them via .gitmodules, and your config files choose which branch/commit to consume.


2) How Configuration Works

2.1 Customer folders

There are two patterns:

  • Multi‑tenant (RaaS/M42): configs/{raas|m42}/<customer>/

  • Edge: configs/<customer>/

Each customer folder usually contains:

  • tenant.json — Base module map and shared settings.

  • dev.json, prod.json — Environment‑specific module pins/overrides.

  • dev.tfvars, prod.tfvars — Variables wired into Terraform for that env (no secrets committed).

2.2 Example (redacted)

  • tenant.json (module selection & pinning):

    { "modules": [ { "directory": "base-account", "branch": "main", "commit": "416ed5c4-*-*", "repo_name": "raas-azure-terraform-base-account" } ] }

  • dev.json (env‑specific modules):

    { "modules": [ { "directory": "base-counter", "branch": "main", "commit": "b0755039-*-*", "repo_name": "raas-azure-terraform-counter" }, { "directory": "base-core", "branch": "m42/mubadala", "commit": "ebabd9ea--**", "repo_name": "raas-azure-terraform-core" }, { "directory": "env-raas", "branch": "m42/mubadala", "commit": "1bd77c18--**", "repo_name": "raas-azure-terraform-env-raas" }, { "directory": "base-cifs", "branch": "main", "commit": "0abb7eb1--**", "repo_name": "raas-azure-terraform-cifs" }, { "directory": "env-snapshots", "branch": "main", "commit": "68d4f2be--**" } ] }

  • dev.tfvars (variables the modules consume):

    customer_az_subscription = "2ff7467a-*-*" location = "" CI_PROJECT_NAME = "ansible-raas-v2.x" ssh_public_key = "ssh-rsa AAAAB3..." admin_username = "adminuser" raas_user = "rhapsody" RaaSS3 = { IAM_USER_CREDS_KV = "S3Creds", AWS_REGION = "us-east-2" } raas_config = { number_of_instances = 1 rules = { / NSG rules per env (keys must be unique) / } asgs = { / VM sizing and disks per env / } } vpns = { / IPSec peer definitions / }

    Snapshot automation (example)

    runbook_name = "Nightly-DataDiskSnapshots" schedule_name = "NightlyAt2AM" schedule_start_time = "2025-04-26T02:00:00Z" schedule_timezone = "America/Phoenix" snapshot_retention_days = 7


3) The GitHub Actions Pipeline (what runs when)

There are dedicated workflows for plan/apply/destroy , both per‑customer and all‑customers.

3.1 Terraform Plan Single (manual trigger)

  • Inputs: TENANT_NAME (e.g., m42), CLIENT_NAME (customer folder), DEVOPS_ENV (dev/prod), MODULE (base-core, ALL, etc.).

  • Key steps:

    1. fetch-azure-credentials (composite action) — queries Cosmos DB for the customer/tenant, exports values into env, logs into Azure via OIDC.

    2. terraform-init — sets backend to an Azure Storage Account (rhapsody-tfstate-<env> container) and uses a state key like <customer>/<region>/<module>.tfstate.

    3. terraform-plan — points Terraform at the tfvars file from configs/<tenant>/<customer>/<env>.tfvars and runs plan.

3.2 Terraform Apply Single

  • Same inputs; runs terraform apply against the same module + var‑file after init. Gate with manual reviewer if required.

3.3 All‑customer workflows

  • Iterate across customers under a tenant path using a strategy/matrix and call the same composite actions.

3.4 Security & scanning

  • A separate workflow callable-security-scan.yml can be invoked for IaC checks.

How it fits: Composite actions keep the workflows short and consistent. The pipeline ensures every customer+env combination can be planned/applied/destroyed in a controlled way.


4) Workflow Swimlanes

(Section removed as requested. Previously contained swimlane diagrams; can be re-added later if needed.)