From 82d3d65c7627776e71dd08a91a5b7cc1bbb8ae9f Mon Sep 17 00:00:00 2001 From: brown9804 Date: Mon, 16 Feb 2026 11:51:45 -0600 Subject: [PATCH 1/3] Fabric template --- 5_analytics-bigdata/README.md | 4 +- 5_analytics-bigdata/fabric/README.md | 79 +++++++++++++++++ 5_analytics-bigdata/fabric/main.tf | 96 +++++++++++++++++++++ 5_analytics-bigdata/fabric/output.tf | 24 ++++++ 5_analytics-bigdata/fabric/provider.tf | 48 +++++++++++ 5_analytics-bigdata/fabric/terraform.tfvars | 23 +++++ 5_analytics-bigdata/fabric/variables.tf | 80 +++++++++++++++++ README.md | 4 +- 8 files changed, 356 insertions(+), 2 deletions(-) create mode 100644 5_analytics-bigdata/fabric/README.md create mode 100644 5_analytics-bigdata/fabric/main.tf create mode 100644 5_analytics-bigdata/fabric/output.tf create mode 100644 5_analytics-bigdata/fabric/provider.tf create mode 100644 5_analytics-bigdata/fabric/terraform.tfvars create mode 100644 5_analytics-bigdata/fabric/variables.tf diff --git a/5_analytics-bigdata/README.md b/5_analytics-bigdata/README.md index bf7179a..e9f6942 100644 --- a/5_analytics-bigdata/README.md +++ b/5_analytics-bigdata/README.md @@ -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 ------------------------------------------ @@ -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) diff --git a/5_analytics-bigdata/fabric/README.md b/5_analytics-bigdata/fabric/README.md new file mode 100644 index 0000000..115a1f0 --- /dev/null +++ b/5_analytics-bigdata/fabric/README.md @@ -0,0 +1,79 @@ +# 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`. + +> [!TIP] +> 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. + +## 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 `-`. | 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 "" + ``` + +2. Initialize: + + ```sh + terraform init -upgrade + ``` + +3. Validate and plan: + + ```sh + terraform validate + terraform plan + ``` + +4. Apply: + + ```sh + terraform apply -auto-approve + ``` diff --git a/5_analytics-bigdata/fabric/main.tf b/5_analytics-bigdata/fabric/main.tf new file mode 100644 index 0000000..7478bfa --- /dev/null +++ b/5_analytics-bigdata/fabric/main.tf @@ -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 + ] +} diff --git a/5_analytics-bigdata/fabric/output.tf b/5_analytics-bigdata/fabric/output.tf new file mode 100644 index 0000000..ccd8ef4 --- /dev/null +++ b/5_analytics-bigdata/fabric/output.tf @@ -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 +} diff --git a/5_analytics-bigdata/fabric/provider.tf b/5_analytics-bigdata/fabric/provider.tf new file mode 100644 index 0000000..78dd546 --- /dev/null +++ b/5_analytics-bigdata/fabric/provider.tf @@ -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) +} diff --git a/5_analytics-bigdata/fabric/terraform.tfvars b/5_analytics-bigdata/fabric/terraform.tfvars new file mode 100644 index 0000000..085ed29 --- /dev/null +++ b/5_analytics-bigdata/fabric/terraform.tfvars @@ -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" +} diff --git a/5_analytics-bigdata/fabric/variables.tf b/5_analytics-bigdata/fabric/variables.tf new file mode 100644 index 0000000..7b0a30f --- /dev/null +++ b/5_analytics-bigdata/fabric/variables.tf @@ -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 '-'." + 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 = {} +} diff --git a/README.md b/README.md index 2f852e9..0919611 100644 --- a/README.md +++ b/README.md @@ -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 ---------- @@ -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) From f9023e29c5cd8a3084388f8399e6e53308b1eef7 Mon Sep 17 00:00:00 2001 From: Timna Brown <24630902+brown9804@users.noreply.github.com> Date: Mon, 16 Feb 2026 11:56:24 -0600 Subject: [PATCH 2/3] Update README with images for Fabric capacity Added images to README for better visualization. --- 5_analytics-bigdata/fabric/README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/5_analytics-bigdata/fabric/README.md b/5_analytics-bigdata/fabric/README.md index 115a1f0..6428ca0 100644 --- a/5_analytics-bigdata/fabric/README.md +++ b/5_analytics-bigdata/fabric/README.md @@ -15,8 +15,6 @@ Last updated: 2026-02-16 > 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`. - -> [!TIP] > 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`. @@ -25,6 +23,13 @@ Last updated: 2026-02-16 > - 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. + +image + +image + +image + ## File Descriptions - **main.tf**: Creates the Resource Group and the Fabric capacity (AzAPI). From a232c34ee77081157fe583ba7fb8c704e0dd9ce2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 16 Feb 2026 17:56:45 +0000 Subject: [PATCH 3/3] Fix Markdown syntax issues --- 5_analytics-bigdata/fabric/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/5_analytics-bigdata/fabric/README.md b/5_analytics-bigdata/fabric/README.md index 6428ca0..6d3c624 100644 --- a/5_analytics-bigdata/fabric/README.md +++ b/5_analytics-bigdata/fabric/README.md @@ -13,6 +13,7 @@ Last updated: 2026-02-16 > [!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: @@ -20,10 +21,10 @@ Last updated: 2026-02-16 > - 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. - image image