{"id":50670989,"url":"https://github.com/cloudandthings/terraform-azurerm-fabric-platform","last_synced_at":"2026-06-08T11:03:17.540Z","repository":{"id":301518455,"uuid":"960380482","full_name":"cloudandthings/terraform-azurerm-fabric-platform","owner":"cloudandthings","description":"A composable Terraform module for provisioning Microsoft Fabric capacities, domains, and workspaces — with built-in cost controls.","archived":false,"fork":false,"pushed_at":"2026-05-22T13:37:18.000Z","size":65,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-22T16:48:05.674Z","etag":null,"topics":["azure","fabric","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloudandthings.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-04-04T10:36:35.000Z","updated_at":"2026-05-22T13:32:03.000Z","dependencies_parsed_at":"2025-06-27T09:42:28.266Z","dependency_job_id":null,"html_url":"https://github.com/cloudandthings/terraform-azurerm-fabric-platform","commit_stats":null,"previous_names":["cloudandthings/cat-terraform-fabric-workspaces","cloudandthings/terraform-fabric-workspaces","cloudandthings/terraform-azurerm-fabric-platform"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/cloudandthings/terraform-azurerm-fabric-platform","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudandthings%2Fterraform-azurerm-fabric-platform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudandthings%2Fterraform-azurerm-fabric-platform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudandthings%2Fterraform-azurerm-fabric-platform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudandthings%2Fterraform-azurerm-fabric-platform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudandthings","download_url":"https://codeload.github.com/cloudandthings/terraform-azurerm-fabric-platform/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudandthings%2Fterraform-azurerm-fabric-platform/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34059157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","fabric","terraform"],"created_at":"2026-06-08T11:03:16.763Z","updated_at":"2026-06-08T11:03:17.528Z","avatar_url":"https://github.com/cloudandthings.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Terraform Azure Fabric Platform\n\n**A composable Terraform module for provisioning Microsoft Fabric capacities, domains, and workspaces — with built-in cost controls.**\n\n[![Terraform Registry](https://img.shields.io/badge/Terraform_Registry-published-844FBA?logo=terraform\u0026logoColor=white)](https://registry.terraform.io/modules/cloudandthings/fabric-platform/azurerm/latest)\n[![Terraform](https://img.shields.io/badge/Terraform-%E2%89%A5_1.7.0-844FBA?logo=terraform\u0026logoColor=white)](https://www.terraform.io/)\n[![Fabric Provider](https://img.shields.io/badge/microsoft%2Ffabric-1.10.0-0078D4?logo=microsoftazure\u0026logoColor=white)](https://registry.terraform.io/providers/microsoft/fabric/latest)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit\u0026logoColor=white)](https://pre-commit.com/)\n\n---\n\n## ✨ Features\n\n- 🏗️ **Composable design** — use the full root module or pick individual sub-modules\n- 💸 **Scheduled pause/resume** — automate weekly capacity downtime to cut costs\n- 🛌 **Usage-based auto-pause** — suspend idle capacities based on Fabric job activity\n- 🌐 **Domain \u0026 workspace management** — organize Fabric resources at scale\n- 🔐 **Managed-identity workflow** — no secrets stored in Terraform state\n- ✅ **Pre-commit \u0026 CI ready** — fmt, validate, tflint, checkov out of the box\n\n## 📑 Table of Contents\n\n- [Quick Start](#-quick-start)\n- [Requirements](#-requirements)\n- [Providers](#-providers)\n- [Usage](#-usage)\n  - [Root module](#root-module-all-resources)\n  - [Sub-modules in isolation](#sub-modules-in-isolation)\n- [Modules](#-modules)\n- [Inputs](#-inputs)\n- [Outputs](#-outputs)\n- [Capacity Scheduler](#-capacity-scheduler)\n- [Usage-based Auto-pause](#-usage-based-auto-pause-autostop)\n- [Architecture](#-architecture)\n- [Notes \u0026 Caveats](#-notes--caveats)\n- [Contributing](#-contributing)\n- [License](#-license)\n\n---\n\n## 🚀 Quick Start\n\n\u003e **Tip:** This module is published to the [Terraform Registry](https://registry.terraform.io/modules/cloudandthings/fabric-platform/azurerm/latest). Pin to a released version in production.\n\n```hcl\nmodule \"fabric\" {\n  source  = \"cloudandthings/fabric-platform/azurerm\"\n  version = \"~\u003e 1.0\"\n\n  fabric_capacities = {\n    \"prod-capacity\" = {\n      location     = \"eastus2\"\n      sku          = \"F2\"\n      admin_emails = [\"admin@yourdomain.com\"]\n    }\n  }\n\n  domains = {\n    \"analytics\" = {\n      description = \"Analytics domain\"\n      admin_principals = [{ id = \"00000000-0000-0000-0000-000000000000\", type = \"User\" }]\n    }\n  }\n\n  workspaces = {\n    \"sales-bi\" = {\n      capacity_basename = \"prod-capacity\"\n      domain_name       = \"analytics\"\n    }\n  }\n\n  providers = {\n    fabric  = fabric\n    azurerm = azurerm\n    azuread = azuread\n    time    = time\n  }\n}\n```\n\n---\n\n## 📋 Requirements\n\n| Tool | Version |\n|---|---|\n| [Terraform](https://www.terraform.io/) | `\u003e= 1.7.0` |\n| [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/) | latest (for `az login` authentication) |\n| Microsoft Fabric tenant | with appropriate admin permissions |\n| Azure subscription | with permissions to create Fabric capacities |\n\n## 🔌 Providers\n\nConfigure these providers in your own root module and pass them to this module via the `providers` argument:\n\n| Provider | Version | Required by |\n|---|---|---|\n| [`microsoft/fabric`](https://registry.terraform.io/providers/microsoft/fabric/latest) | `1.10.0` | `fabric_domain`, `fabric_workspace` |\n| [`hashicorp/azurerm`](https://registry.terraform.io/providers/hashicorp/azurerm/latest) | `\u003e= 3.98.0` | `fabric_capacity` |\n| [`hashicorp/azuread`](https://registry.terraform.io/providers/hashicorp/azuread/latest) | `\u003e= 2.47.0` | `fabric_capacity` |\n| [`hashicorp/time`](https://registry.terraform.io/providers/hashicorp/time/latest) | `\u003e= 0.9.0` | `fabric_capacity` |\n\nAuthenticate with `az login` before running `terraform apply`.\n\n\u003e **Important:** The `fabric` provider must be configured with `preview = true` to enable Fabric preview features used by this module.\n\n---\n\n## 📦 Usage\n\n### Root module (all resources)\n\n```hcl\n# provider.tf\nprovider \"fabric\" {\n  tenant_id = \"00000000-0000-0000-0000-000000000000\"\n  use_cli   = true\n  preview   = true\n}\n\nprovider \"azurerm\" {\n  features {}\n  subscription_id = \"00000000-0000-0000-0000-000000000000\"\n}\n\nprovider \"azuread\" {\n  tenant_id = \"00000000-0000-0000-0000-000000000000\"\n}\n```\n\n```hcl\n# main.tf\nmodule \"fabric\" {\n  source  = \"cloudandthings/fabric-platform/azurerm\"\n  version = \"~\u003e 1.0\"\n\n  fabric_capacities = {\n    \"test001\" = {\n      location     = \"eastus2\"\n      sku          = \"F2\"\n      admin_emails = [\"admin@yourdomain.com\"]\n\n      scheduler = {\n        pause_time  = \"20:00\"\n        resume_time = \"07:00\"\n        pause_days  = [\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\"]\n        resume_days = [\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\"]\n      }\n\n      usage_autostop = {\n        check_interval_hours  = 1\n        idle_threshold_checks = 2\n      }\n    }\n  }\n\n  domains = {\n    \"test-domain\" = {\n      description = \"This is a test domain\"\n      admin_principals = [\n        { id = \"user-object-id-here\", type = \"User\" }\n      ]\n    }\n  }\n\n  workspaces = {\n    \"test-workspace\" = {\n      description       = \"This is a test workspace\"\n      capacity_basename = \"test001\"\n      domain_name       = \"test-domain\"\n    }\n  }\n\n  providers = {\n    fabric  = fabric\n    azurerm = azurerm\n    azuread = azuread\n    time    = time\n  }\n}\n```\n\n### Sub-modules in isolation\n\n**Capacity only** — no `fabric` provider required\n\n```hcl\nmodule \"my_capacity\" {\n  source  = \"cloudandthings/fabric-platform/azurerm//modules/fabric_capacity\"\n  version = \"~\u003e 1.0\"\n\n  basename     = \"my-capacity\"\n  location     = \"eastus2\"\n  sku          = \"F2\"\n  admin_emails = [\"admin@yourdomain.com\"]\n\n  providers = {\n    azurerm = azurerm\n    azuread = azuread\n    time    = time\n  }\n}\n```\n\n**Domain only**\n\n```hcl\nmodule \"my_domain\" {\n  source  = \"cloudandthings/fabric-platform/azurerm//modules/fabric_domain\"\n  version = \"~\u003e 1.0\"\n\n  display_name = \"my-domain\"\n  description  = \"My Fabric domain\"\n  admin_principals = [\n    { id = \"user-object-id-here\", type = \"User\" }\n  ]\n\n  providers = {\n    fabric = fabric\n  }\n}\n```\n\n**Workspace only**\n\n```hcl\nmodule \"my_workspace\" {\n  source  = \"cloudandthings/fabric-platform/azurerm//modules/fabric_workspace\"\n  version = \"~\u003e 1.0\"\n\n  display_name = \"my-workspace\"\n  capacity_id  = \"/subscriptions/.../resourceGroups/.../providers/Microsoft.Fabric/capacities/my-capacity\"\n\n  providers = {\n    fabric = fabric\n  }\n}\n```\n\n---\n\n## 🧩 Modules\n\n| Module | Description | Required providers |\n|---|---|---|\n| [`fabric_capacity`](modules/fabric_capacity) | Azure Fabric capacity + optional cost-control automation | `azurerm`, `azuread`, `time` |\n| [`fabric_domain`](modules/fabric_domain) | Fabric domain with admin role assignments | `fabric` |\n| [`fabric_workspace`](modules/fabric_workspace) | Fabric workspace bound to a capacity (and optionally a domain) | `fabric` |\n\n---\n\n## 📥 Inputs\n\n### Root module\n\n| Name | Description | Type | Required |\n|---|---|---|:---:|\n| `fabric_capacities` | Map of Fabric capacities to create, keyed by capacity name. See [capacity attributes](#capacity-attributes). | `map(object)` | yes |\n| `domains` | Map of Fabric domains, keyed by domain name. See [domain attributes](#domain-attributes). | `map(object)` | yes |\n| `workspaces` | Map of Fabric workspaces, keyed by workspace name. See [workspace attributes](#workspace-attributes). | `map(object)` | yes |\n\n#### Capacity attributes\n\n| Attribute | Description | Type | Default |\n|---|---|---|---|\n| `location` | Azure region for the capacity. | `string` | — |\n| `sku` | Fabric capacity SKU (e.g. `F2`, `F32`, `F64`, `F128`). | `string` | — |\n| `admin_emails` | Administrator email addresses. | `list(string)` | — |\n| `scheduler` | Optional weekly pause/resume schedule. See [Capacity Scheduler](#-capacity-scheduler). | `object` | `null` |\n| `scheduler.pause_time` | Pause time in `HH:MM` UTC format. | `string` | — |\n| `scheduler.resume_time` | Resume time in `HH:MM` UTC format. | `string` | — |\n| `scheduler.pause_days` | Weekdays on which to pause. | `list(string)` | all days |\n| `scheduler.resume_days` | Weekdays on which to resume. | `list(string)` | all days |\n| `usage_autostop` | Optional usage-based auto-pause. See [Usage-based Auto-pause](#-usage-based-auto-pause-autostop). | `object` | `null` |\n| `usage_autostop.check_interval_hours` | Poll frequency (1–24 hours). | `number` | `1` |\n| `usage_autostop.idle_threshold_checks` | Consecutive idle polls before suspending. | `number` | `2` |\n\n#### Domain attributes\n\n| Attribute | Description | Type | Default |\n|---|---|---|---|\n| `description` | Description of the domain. | `string` | `\"\"` |\n| `parent_domain_id` | ID of the parent domain (for nested domains). | `string` | `\"\"` |\n| `admin_principals` | `[{ id, type }]` — Azure AD principal object IDs and type (`User` or `Group`). | `list(object)` | — |\n\n#### Workspace attributes\n\n| Attribute | Description | Type | Default |\n|---|---|---|---|\n| `description` | Description of the workspace. | `string` | `\"\"` |\n| `capacity_basename` | Key into `fabric_capacities` that this workspace binds to. | `string` | — |\n| `domain_name` | Key into `domains`. Omit to skip domain assignment. | `string` | `\"\"` |\n\n### Sub-module: `fabric_capacity`\n\n| Name | Description | Type | Default |\n|---|---|---|---|\n| `basename` | Base name used for resource group, capacity, and automation resources. | `string` | — |\n| `location` | Azure region. | `string` | `\"North Europe\"` |\n| `sku` | Fabric capacity SKU. | `string` | `\"F2\"` |\n| `admin_emails` | Administrator email addresses. | `list(string)` | — |\n| `scheduler` | See [capacity attributes](#capacity-attributes). | `object` | `null` |\n| `usage_autostop` | See [capacity attributes](#capacity-attributes). | `object` | `null` |\n\n### Sub-module: `fabric_domain`\n\n| Name | Description | Type | Default |\n|---|---|---|---|\n| `display_name` | Display name of the Fabric domain. | `string` | — |\n| `description` | Description of the domain. | `string` | `\"\"` |\n| `parent_domain_id` | Parent domain ID for nested domains. | `string` | `\"\"` |\n| `admin_principals` | `[{ id, type }]` admin principals. | `list(object)` | — |\n\n### Sub-module: `fabric_workspace`\n\n| Name | Description | Type | Default |\n|---|---|---|---|\n| `display_name` | Workspace display name. | `string` | — |\n| `description` | Workspace description. | `string` | `\"\"` |\n| `capacity_id` | Azure resource ID of the Fabric capacity to bind to. | `string` | — |\n| `fabric_domain_id` | ID of the Fabric domain to assign to. | `string` | `null` |\n| `assign_to_domain` | Whether to assign the workspace to a domain. | `bool` | `false` |\n| `monitor_principal_id` | Managed identity principal ID to add as workspace `Member` (typically from `fabric_capacity.monitor_principal_id`). | `string` | `null` |\n\n---\n\n## 📤 Outputs\n\n### Sub-module: `fabric_capacity`\n\n| Name | Description |\n|---|---|\n| `id` | Azure resource ID of the Fabric capacity. |\n| `automation_account_id` | Azure resource ID of the Automation Account. `null` when both `scheduler` and `usage_autostop` are disabled. |\n| `monitor_principal_id` | Principal ID of the Automation Account's managed identity. `null` when `usage_autostop` is disabled. |\n\n### Sub-module: `fabric_domain`\n\n| Name | Description |\n|---|---|\n| `id` | ID of the Fabric domain. |\n\n---\n\n## ⏰ Capacity Scheduler\n\nWhen `scheduler` is configured, the `fabric_capacity` module provisions Azure resources to automate capacity cost management:\n\n- 🤖 **Azure Automation Account** with a System-Assigned Managed Identity\n- 🔑 **Role Assignment** — `Contributor` access on the Fabric Capacity\n- 📜 **PowerShell 7.2 Runbook** ([`capacity_scheduler.ps1`](modules/fabric_capacity/scripts/capacity_scheduler.ps1)) — authenticates via Managed Identity and calls the Azure Management API\n- 📅 **Two weekly schedules** — one to pause, one to resume\n\n\u003e **Note:** The runbook is idempotent — it checks the current capacity state before acting and skips the API call if the capacity is already in the target state.\n\n## 🛌 Usage-based Auto-pause (autostop)\n\nWhen `usage_autostop` is configured, the module deploys an additional runbook ([`capacity_autostop.ps1`](modules/fabric_capacity/scripts/capacity_autostop.ps1)) that polls accessible Fabric workspaces for active job instances and suspends the capacity after sustained idle time.\n\n\u003e **Warning:** The Fabric Jobs API only reports **scheduled or triggered job instances**. Interactive and continuous workloads are invisible to this API and will **not** prevent suspension.\n\n**Detected activity** (will prevent suspension)\n\n| Workload | Activity |\n|---|---|\n| Data Factory | Data pipeline runs, Dataflow Gen2 refreshes, Copy Job runs |\n| Data Engineering | Notebook runs (scheduled / triggered), Spark Job Definition runs, Lakehouse table maintenance (OPTIMIZE / VACUUM) |\n| Data Science | ML Experiment / ML Model training jobs (when triggered as jobs) |\n| Data Warehouse | Semantic model (dataset) refreshes |\n| Real-Time Intelligence | KQL Database commands triggered as job instances, Mirrored Database initial snapshots (where exposed as jobs) |\n\n**NOT detected activity** (capacity may be suspended while in use)\n\n| Workload | Activity |\n|---|---|\n| Data Warehouse / SQL | Interactive SQL queries against Fabric Warehouses; queries against the Lakehouse SQL analytics endpoint |\n| Real-Time Intelligence | Interactive KQL queries against Eventhouses, KQL Databases, KQL Querysets; Eventstream continuous ingestion; Activator (Reflex) rule evaluation; Real-Time Dashboards |\n| Data Engineering | Interactive notebook sessions; Spark interactive sessions / Livy endpoint usage |\n| Power BI / Data Science | Power BI report rendering, DirectQuery / Direct Lake reads, paginated reports; interactive ML Experiment exploration |\n| Mirrored Database | Continuous change-data replication |\n\n\u003e **Tip:** For workloads dominated by interactive SQL, KQL, Power BI, or streaming usage, the `scheduler` option is safer — it pauses at predictable off-hours rather than relying on incomplete activity detection.\n\nThe managed identity must be a **Member** of every Fabric workspace it monitors. Workspaces created by this module are added automatically; any others must be added manually via the Fabric Admin Portal.\n\n---\n\n## 🏛️ Architecture\n\n```\nAzure Resource Group\n├── Fabric Capacity\n└── Automation Account\n    ├── Managed Identity ──(Contributor)──► Fabric Capacity\n    ├── Scheduler Runbook ──(Pause/Resume on schedule)──► Fabric Capacity\n    └── Autostop Runbook  ──(Suspend when idle)──► Fabric Capacity\n\nFabric Domain\n└── Fabric Workspace ◄──(capacity_id)── Fabric Capacity\n                     ◄──(Workspace Member)── Automation Account\n```\n\nThe solution creates a hierarchical structure:\n\n1. **Azure Resource Groups** — container for Azure resources\n2. **Fabric Capacities** — compute resources for Fabric workloads\n3. **Fabric Domains** — organizational units for governance\n4. **Fabric Workspaces** — development environments bound to capacities and domains\n\n**Dependency order:** domains and capacities are created independently; workspaces depend on both.\n\n---\n\n## 📝 Notes \u0026 Caveats\n\n- 🔐 The `fabric` provider should be configured with `preview = true` to enable preview features\n- 👥 Admin emails and principal IDs must exist as valid users/groups in your Azure AD tenant\n- 🌍 Fabric capacities are only available in [specific Azure regions](https://learn.microsoft.com/en-us/fabric/admin/region-availability)\n- 🏷️ The `fabric_workspace` module extracts capacity names from Azure resource IDs for Fabric provider compatibility\n\n---\n\n## 🤝 Contributing\n\n\u003e This section applies to **contributors only**. End users do not need to clone the repo.\n\n### Prerequisites\n\n- [mise](https://mise.jdx.dev/) — manages all required tools (Terraform, tflint, Azure CLI, pre-commit, checkov)\n\n### Setup\n\n```bash\nmise run setup\n```\n\nThis installs all required tools at the correct versions and activates the pre-commit hooks.\n\n### Pre-commit Hooks\n\nHooks run automatically on every `git commit` via [pre-commit-terraform](https://github.com/antonbabenko/pre-commit-terraform):\n\n| Hook | Purpose |\n|---|---|\n| `terraform_fmt` | Formats all `.tf` files |\n| `terraform_validate` | Validates Terraform configuration |\n| `terraform_tflint` | Lints with tflint |\n| `terraform_checkov` | Static security analysis |\n\nRun all hooks manually:\n\n```bash\npre-commit run --all-files\n```\n\n### Project Structure\n\n```\n.\n├── main.tf                     # Root module: wires fabric_capacity, fabric_domain, fabric_workspace\n├── variables.tf                # Root module variable definitions\n├── locals.tf                   # Root module locals (domain ID lookup)\n├── provider.tf                 # required_providers declaration\n├── modules/\n│   ├── fabric_capacity/        # Azure Fabric capacity module\n│   │   └── scripts/            # PowerShell runbooks for scheduler \u0026 autostop\n│   ├── fabric_domain/          # Microsoft Fabric domain module\n│   └── fabric_workspace/       # Microsoft Fabric workspace module\n└── README.md\n```\n\n---\n\n## 📄 License\n\nLicensed under the [Apache License 2.0](LICENSE). See the [LICENSE](LICENSE) file for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudandthings%2Fterraform-azurerm-fabric-platform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudandthings%2Fterraform-azurerm-fabric-platform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudandthings%2Fterraform-azurerm-fabric-platform/lists"}