Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion 5_analytics-bigdata/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Costa Rica
[![GitHub](https://img.shields.io/badge/--181717?logo=github&logoColor=ffffff)](https://github.com/)
[brown9804](https://github.com/brown9804)

Last updated: 2026-02-12
Last updated: 2026-02-16

------------------------------------------

Expand All @@ -16,6 +16,8 @@ Last updated: 2026-02-12

- [Azure Data Factory](./data-factory)
- [Azure Databricks (Workspace)](./databricks)
- [Azure Event Hubs](./event-hub)
- [Microsoft Fabric (Capacity)](./fabric)
- [Azure Synapse Analytics (Workspace)](./synapse-analytics)

<!-- START BADGE -->
Expand Down
85 changes: 85 additions & 0 deletions 5_analytics-bigdata/fabric/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Terraform Template - Microsoft Fabric (Capacity)

Costa Rica

[![GitHub](https://img.shields.io/badge/--181717?logo=github&logoColor=ffffff)](https://github.com/)
[brown9804](https://github.com/brown9804)

Last updated: 2026-02-16

------------------------------------------

> This template contains Terraform configurations to create a Microsoft Fabric capacity in Azure.

> [!IMPORTANT]
> Fabric capacity creation requires at least one admin member.
>
> - Option A (recommended): set `use_current_user_as_admin = true` and let Terraform resolve the current user UPN.
> - Option B: set `admin_members` explicitly to one or more UPNs like `user@domain.com`.
> To avoid committing identities, prefer environment variables:
> - PowerShell: `$env:TF_VAR_admin_members='["user@domain.com"]'`
> - PowerShell (auto): keep `use_current_user_as_admin = true` and omit `admin_members`.

> [!NOTE]
>
> - The Fabric capacity resource is created via the AzAPI provider using the ARM resource type `Microsoft.Fabric/capacities@2023-11-01`.
> - The Resource Group is created via AzAPI (idempotent ARM PUT) to align with other templates in this repository.

<img width="650" alt="image" src="https://github.com/user-attachments/assets/fb74b695-b13d-4ca1-aae6-d5386e67660a" />

<img width="650" alt="image" src="https://github.com/user-attachments/assets/8bb7c264-8a8f-4c8e-b7d3-62e54d464b62" />

<img width="650" alt="image" src="https://github.com/user-attachments/assets/799fc378-a49a-4c0d-bc6d-3fde6361f5d7" />

## File Descriptions

- **main.tf**: Creates the Resource Group and the Fabric capacity (AzAPI).
- **variables.tf**: Defines the input variables used in the Terraform configuration.
- **provider.tf**: Configures the AzureRM + AzAPI providers.
- **terraform.tfvars**: Example values for the variables defined in `variables.tf`.
- **output.tf**: Defines outputs such as Fabric capacity resource ID.

## Variables

| Variable Name | Description | Type | Example Value |
| --- | --- | --- | --- |
| `resource_group_name` | Resource Group name to create/deploy into. | string | `"rg-analytics-dev-fabric"` |
| `location` | Azure region for the deployment. | string | `"eastus"` |
| `capacity_name` | Base capacity name. If suffix enabled, final is `<base>-<suffix>`. | string | `"fabric-capacity-dev"` |
| `use_current_user_as_admin` | Auto-resolve current user as admin when `admin_members` is empty. | bool | `true` |
| `admin_members` | Optional explicit Fabric capacity admins (UPNs). Overrides auto mode. | list(string) | `[]` |
| `sku_name` | Capacity SKU (for example `F2`, `F4`, `F8`, ...). | string | `"F2"` |
| `sku_tier` | Capacity SKU tier. | string | `"Fabric"` |
| `append_random_suffix` | Append a random suffix to avoid collisions. | bool | `true` |
| `random_suffix_length` | Length of the random suffix when enabled. | number | `6` |
| `tags` | Tags applied to resources. | map(string) | `{ "env": "dev" }` |

## Usage

1. Authenticate:

```sh
az login
az account show
# If needed:
az account set --subscription "<subscription-id-or-name>"
```

2. Initialize:

```sh
terraform init -upgrade
```

3. Validate and plan:

```sh
terraform validate
terraform plan
```

4. Apply:

```sh
terraform apply -auto-approve
```
96 changes: 96 additions & 0 deletions 5_analytics-bigdata/fabric/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
data "azurerm_client_config" "current" {}

data "azuread_client_config" "current" {}

data "azuread_user" "current" {
object_id = data.azuread_client_config.current.object_id
}

# Resource group creation is idempotent in ARM (PUT). This will create the RG if it doesn't exist,
# or update tags if it already exists.
resource "azapi_resource" "resource_group" {
type = "Microsoft.Resources/resourceGroups@2022-09-01"
name = var.resource_group_name
location = var.location
parent_id = "/subscriptions/${data.azurerm_client_config.current.subscription_id}"

body = jsonencode({
tags = var.tags
})

response_export_values = [
"id",
"name"
]
}

resource "random_string" "suffix" {
length = var.random_suffix_length
upper = false
special = false
numeric = true

keepers = {
resource_group_name = var.resource_group_name
location = var.location
capacity_base = var.capacity_name
sku_name = var.sku_name
sku_tier = var.sku_tier
}
}

locals {
rg_id = azapi_resource.resource_group.id
suffix = var.append_random_suffix ? random_string.suffix.result : ""
capacity_name = var.append_random_suffix ? "${var.capacity_name}-${local.suffix}" : var.capacity_name

# AzAPI schema validation for Microsoft.Fabric/capacities currently enforces a strict name pattern:
# ^[a-z][a-z0-9]*$
# To keep tfvars friendly (allowing '-' etc.), we sanitize the requested name for the ARM resource name.
capacity_name_sanitized_raw = join("", regexall("[a-z0-9]", lower(local.capacity_name)))
capacity_name_sanitized = can(regex("^[a-z]", local.capacity_name_sanitized_raw)) ? local.capacity_name_sanitized_raw : "fc${local.capacity_name_sanitized_raw}"

admin_members_effective = (
length(var.admin_members) > 0
? var.admin_members
: (var.use_current_user_as_admin ? [data.azuread_user.current.user_principal_name] : [])
)
}

# Microsoft Fabric capacity (ARM resource provider: Microsoft.Fabric)
# API version reference: https://learn.microsoft.com/azure/templates/Microsoft.Fabric/2023-11-01/capacities
resource "azapi_resource" "fabric_capacity" {
type = "Microsoft.Fabric/capacities@2023-11-01"
name = local.capacity_name_sanitized
location = var.location
parent_id = local.rg_id

lifecycle {
precondition {
condition = length(local.admin_members_effective) > 0
error_message = "No Fabric admins configured. Set admin_members (list of UPNs) or enable use_current_user_as_admin to auto-resolve the current user."
}
}

body = jsonencode({
sku = {
name = var.sku_name
tier = var.sku_tier
}
properties = {
administration = {
members = local.admin_members_effective
}
}
tags = var.tags
})

response_export_values = [
"id",
"name"
]

depends_on = [
azapi_resource.resource_group
]
}
24 changes: 24 additions & 0 deletions 5_analytics-bigdata/fabric/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
output "resource_group_id" {
description = "The resource ID of the Resource Group."
value = azapi_resource.resource_group.id
}

output "fabric_capacity_id" {
description = "The resource ID of the Fabric capacity."
value = azapi_resource.fabric_capacity.id
}

output "fabric_capacity_name" {
description = "The name of the Fabric capacity (sanitized ARM resource name)."
value = azapi_resource.fabric_capacity.name
}

output "fabric_capacity_name_requested" {
description = "The requested capacity_name value after suffixing (before sanitization)."
value = local.capacity_name
}

output "fabric_capacity_location" {
description = "The Azure region the Fabric capacity is deployed into."
value = var.location
}
48 changes: 48 additions & 0 deletions 5_analytics-bigdata/fabric/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# provider.tf
# This file configures the Azure provider to interact with Azure resources.
# It specifies the required provider and its version, along with provider-specific configurations.

terraform {
required_version = ">= 1.8, < 2.0"

required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.116"
}

azapi = {
source = "Azure/azapi"
version = "~> 1.13"
}

random = {
source = "hashicorp/random"
version = "~> 3.6"
}

azuread = {
source = "hashicorp/azuread"
version = "~> 3.0"
}
}
}

provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}

# Uses the current Azure CLI context (az login + az account set)
skip_provider_registration = false
}

provider "azapi" {
# Uses the current Azure CLI context (az login + az account set)
}

provider "azuread" {
# Uses the current Azure CLI context (az login + az account set)
}
23 changes: 23 additions & 0 deletions 5_analytics-bigdata/fabric/terraform.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
resource_group_name = "rg-analytics-dev-fabric"
location = "eastus"

append_random_suffix = true
random_suffix_length = 6

capacity_name = "fabric-capacity-dev"

use_current_user_as_admin = true

# Optional override (UPNs):
# admin_members = [
# "user@domain.com"
# ]

sku_name = "F2"
sku_tier = "Fabric"

tags = {
env = "dev"
area = "analytics-bigdata"
iac = "terraform"
}
80 changes: 80 additions & 0 deletions 5_analytics-bigdata/fabric/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
variable "resource_group_name" {
description = "The name of the Azure Resource Group to deploy into. This template will create the RG if it does not exist (idempotent ARM PUT)."
type = string

validation {
condition = length(trimspace(var.resource_group_name)) > 0
error_message = "resource_group_name must not be empty."
}
}

variable "location" {
description = "The Azure region where the Resource Group and Fabric capacity will be created."
type = string

validation {
condition = length(trimspace(var.location)) > 0
error_message = "location must not be empty."
}
}

variable "append_random_suffix" {
description = "Whether to append a random suffix to the capacity name to avoid collisions."
type = bool
default = true
}

variable "random_suffix_length" {
description = "Length of the random suffix appended when append_random_suffix is true."
type = number
default = 6

validation {
condition = var.random_suffix_length >= 4 && var.random_suffix_length <= 16
error_message = "random_suffix_length must be between 4 and 16."
}
}

variable "capacity_name" {
description = "Base name of the Fabric capacity. If append_random_suffix is true, the final name will be '<base>-<suffix>'."
type = string

validation {
condition = (
length(trimspace(var.capacity_name)) > 0
&& length(var.capacity_name) <= (var.append_random_suffix ? (63 - 1 - var.random_suffix_length) : 63)
&& length(join("", regexall("[a-z0-9]", lower(var.capacity_name)))) > 0
)
error_message = "capacity_name must be 1-63 chars and must contain at least one letter or digit (Terraform will sanitize the name to meet Azure resource naming constraints)."
}
}

variable "admin_members" {
description = "Optional list of Fabric capacity admin members (UPNs). If empty and use_current_user_as_admin is true, Terraform will resolve the current user and use that UPN."
type = list(string)
default = []
}

variable "use_current_user_as_admin" {
description = "When true and admin_members is empty, resolve the currently authenticated Entra ID user and set them as the Fabric capacity admin. Requires AzureAD (Microsoft Graph) read permissions to resolve the UPN."
type = bool
default = true
}

variable "sku_name" {
description = "SKU name for the Fabric capacity (for example: F2, F4, F8, F16, F32, F64, F128, F256, F512, F1024, F2048)."
type = string
default = "F2"
}

variable "sku_tier" {
description = "SKU tier for the Fabric capacity."
type = string
default = "Fabric"
}

variable "tags" {
description = "A map of tags to assign to the resources."
type = map(string)
default = {}
}
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Costa Rica
[![GitHub](https://img.shields.io/badge/--181717?logo=github&logoColor=ffffff)](https://github.com/)
[brown9804](https://github.com/brown9804)

Last updated: 2026-02-12
Last updated: 2026-02-16

----------

Expand Down Expand Up @@ -107,6 +107,8 @@ Last updated: 2026-02-12
- [Analytics and Big Data](./5_analytics-bigdata)
- [Azure Data Factory](./5_analytics-bigdata/data-factory)
- [Azure Databricks (Workspace)](./5_analytics-bigdata/databricks)
- [Azure Event Hubs](./5_analytics-bigdata/event-hub)
- [Microsoft Fabric (Capacity)](./5_analytics-bigdata/fabric)
- [Azure Synapse Analytics (Workspace)](./5_analytics-bigdata/synapse-analytics)

</details>
Expand Down