diff --git a/5_analytics-bigdata/event-hub/README.md b/5_analytics-bigdata/event-hub/README.md index 63462c0..3b2bc5c 100644 --- a/5_analytics-bigdata/event-hub/README.md +++ b/5_analytics-bigdata/event-hub/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-16 +Last updated: 2026-02-17 ------------------------------------------ @@ -78,3 +78,10 @@ Last updated: 2026-02-16 ```sh terraform apply -auto-approve ``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/5_analytics-bigdata/fabric/README.md b/5_analytics-bigdata/fabric/README.md index 6d3c624..0519f55 100644 --- a/5_analytics-bigdata/fabric/README.md +++ b/5_analytics-bigdata/fabric/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-16 +Last updated: 2026-02-17 ------------------------------------------ @@ -83,3 +83,10 @@ Last updated: 2026-02-16 ```sh terraform apply -auto-approve ``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/6_monitoring-management/advisor/README.md b/6_monitoring-management/advisor/README.md index f346da9..4f37a8f 100644 --- a/6_monitoring-management/advisor/README.md +++ b/6_monitoring-management/advisor/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-16 +Last updated: 2026-02-17 ------------------------------------------ @@ -25,3 +25,10 @@ terraform validate terraform plan terraform apply -auto-approve ``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/6_monitoring-management/automation/README.md b/6_monitoring-management/automation/README.md index 6e03c82..0f52f58 100644 --- a/6_monitoring-management/automation/README.md +++ b/6_monitoring-management/automation/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-16 +Last updated: 2026-02-17 ------------------------------------------ @@ -32,3 +32,10 @@ terraform validate terraform plan terraform apply -auto-approve ``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/6_monitoring-management/log-analytics/README.md b/6_monitoring-management/log-analytics/README.md index cc4fd10..af82fd4 100644 --- a/6_monitoring-management/log-analytics/README.md +++ b/6_monitoring-management/log-analytics/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-16 +Last updated: 2026-02-17 ------------------------------------------ @@ -49,3 +49,10 @@ terraform validate terraform plan terraform apply -auto-approve ``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/6_monitoring-management/monitor/README.md b/6_monitoring-management/monitor/README.md index 4fe8344..e3f430c 100644 --- a/6_monitoring-management/monitor/README.md +++ b/6_monitoring-management/monitor/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-16 +Last updated: 2026-02-17 ------------------------------------------ @@ -22,3 +22,10 @@ terraform validate terraform plan terraform apply -auto-approve ``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/8_ai-ml/README.md b/8_ai-ml/README.md index e678608..4a3e54a 100644 --- a/8_ai-ml/README.md +++ b/8_ai-ml/README.md @@ -5,13 +5,20 @@ 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-09 +Last updated: 2026-02-16 ------------------------------------------ > [!IMPORTANT] > This folder contains sample Terraform templates for Azure AI and machine learning services. These templates are starting points and should be customized based on your application needs. +## Templates available + +- [Azure Machine Learning (Workspace)](./machine-learning) +- [Azure AI Search (Search Service)](./ai-search) +- [Azure AI Services (Cognitive Services Account)](./ai-services) +- [Microsoft Foundry (Azure AI Foundry Account + Project)](./ai-foundry) +
Total views diff --git a/8_ai-ml/ai-foundry/README.md b/8_ai-ml/ai-foundry/README.md new file mode 100644 index 0000000..83fb52b --- /dev/null +++ b/8_ai-ml/ai-foundry/README.md @@ -0,0 +1,35 @@ +# Terraform Template - Microsoft Foundry (Azure AI Foundry) + +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-17 + +------------------------------------------ + +> This template creates a Microsoft Foundry account (Cognitive Services account kind `AIServices`) and an optional Foundry project. + +image + +image + +image + +## Usage + +```sh +az login +terraform init -upgrade +terraform validate +terraform plan +terraform apply -auto-approve +``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/8_ai-ml/ai-foundry/main.tf b/8_ai-ml/ai-foundry/main.tf new file mode 100644 index 0000000..5f01dd7 --- /dev/null +++ b/8_ai-ml/ai-foundry/main.tf @@ -0,0 +1,124 @@ +data "azurerm_client_config" "current" {} + +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 + base_name = var.foundry_account_name + sku = var.sku_name + allow_project_management = tostring(var.allow_project_management) + public_network_access = tostring(var.public_network_access_enabled) + } +} + +locals { + suffix = var.append_random_suffix ? random_string.suffix.result : "" + name_raw = var.append_random_suffix ? "${var.foundry_account_name}-${local.suffix}" : var.foundry_account_name + + custom_subdomain_name_effective = ( + (var.custom_subdomain_name != null ? trimspace(var.custom_subdomain_name) : "") != "" + ? trimspace(var.custom_subdomain_name) + : "cog-${replace(lower(local.name_raw), "_", "-")}" # best-effort derivation + ) + + project_name_effective = ( + (var.project_name != null ? trimspace(var.project_name) : "") != "" + ? trimspace(var.project_name) + : substr(replace(local.name_raw, "-", ""), 0, 64) + ) + + project_display_name_effective = ( + (var.project_display_name != null ? trimspace(var.project_display_name) : "") != "" + ? trimspace(var.project_display_name) + : "project-${local.name_raw}" + ) + + public_network_access = var.public_network_access_enabled ? "Enabled" : "Disabled" +} + +resource "azapi_resource" "foundry_account" { + # Use the newer api-version so Foundry-specific properties (like allowProjectManagement) + # are recognized by the resource provider. Schema validation is disabled to avoid + # AzAPI embedded schema lagging the service. + type = "Microsoft.CognitiveServices/accounts@2025-06-01" + schema_validation_enabled = false + name = local.name_raw + location = var.location + parent_id = azapi_resource.resource_group.id + + identity { + type = var.enable_system_assigned_identity ? "SystemAssigned" : "None" + } + + body = jsonencode({ + kind = "AIServices" + properties = { + allowProjectManagement = var.allow_project_management + customSubDomainName = local.custom_subdomain_name_effective + publicNetworkAccess = local.public_network_access + disableLocalAuth = false + dynamicThrottlingEnabled = false + restrictOutboundNetworkAccess = false + } + sku = { + name = var.sku_name + } + tags = var.tags + }) + + response_export_values = ["*"] + + depends_on = [ + azapi_resource.resource_group + ] +} + +resource "azapi_resource" "foundry_project" { + count = var.create_project ? 1 : 0 + + # The projects subresource may not have schema coverage in AzAPI; disable schema validation. + type = "Microsoft.CognitiveServices/accounts/projects@2025-06-01" + schema_validation_enabled = false + name = local.project_name_effective + location = var.location + parent_id = azapi_resource.foundry_account.id + + identity { + type = "SystemAssigned" + } + + body = jsonencode({ + properties = { + displayName = local.project_display_name_effective + description = var.project_description + } + tags = var.tags + }) + + response_export_values = ["*"] + + depends_on = [ + azapi_resource.foundry_account + ] +} diff --git a/8_ai-ml/ai-foundry/outputs.tf b/8_ai-ml/ai-foundry/outputs.tf new file mode 100644 index 0000000..d2f3394 --- /dev/null +++ b/8_ai-ml/ai-foundry/outputs.tf @@ -0,0 +1,29 @@ +output "resource_group_id" { + description = "The resource ID of the Resource Group." + value = azapi_resource.resource_group.id +} + +output "foundry_account_id" { + description = "The resource ID of the Foundry account (Cognitive Services account kind AIServices)." + value = azapi_resource.foundry_account.id +} + +output "foundry_account_name" { + description = "The name of the Foundry account." + value = azapi_resource.foundry_account.name +} + +output "foundry_account_endpoint" { + description = "The endpoint of the Foundry account (when available in the resource properties)." + value = try(jsondecode(azapi_resource.foundry_account.output).properties.endpoint, null) +} + +output "foundry_project_id" { + description = "The resource ID of the Foundry project (if created)." + value = try(azapi_resource.foundry_project[0].id, null) +} + +output "foundry_project_name" { + description = "The name of the Foundry project (if created)." + value = try(azapi_resource.foundry_project[0].name, null) +} diff --git a/8_ai-ml/ai-foundry/provider.tf b/8_ai-ml/ai-foundry/provider.tf new file mode 100644 index 0000000..e3a2be8 --- /dev/null +++ b/8_ai-ml/ai-foundry/provider.tf @@ -0,0 +1,35 @@ +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" + } + } +} + +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) +} diff --git a/8_ai-ml/ai-foundry/terraform.tfvars b/8_ai-ml/ai-foundry/terraform.tfvars new file mode 100644 index 0000000..e92491a --- /dev/null +++ b/8_ai-ml/ai-foundry/terraform.tfvars @@ -0,0 +1,20 @@ +resource_group_name = "rg-ai-foundry-dev" +location = "eastus" + +append_random_suffix = true +random_suffix_length = 6 + +foundry_account_name = "aifoundry-dev" +sku_name = "S0" +allow_project_management = true +public_network_access_enabled = true +enable_system_assigned_identity = true + +create_project = true +project_description = "" + +tags = { + env = "dev" + area = "ai-ml" + iac = "terraform" +} diff --git a/8_ai-ml/ai-foundry/variables.tf b/8_ai-ml/ai-foundry/variables.tf new file mode 100644 index 0000000..54a06c5 --- /dev/null +++ b/8_ai-ml/ai-foundry/variables.tf @@ -0,0 +1,106 @@ +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 for the deployment." + 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 names to reduce naming 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 "foundry_account_name" { + description = "Base name for the Microsoft Foundry account (Cognitive Services account kind 'AIServices'). If append_random_suffix is true, the final name will be '-'." + type = string + + validation { + condition = length(trimspace(var.foundry_account_name)) >= 2 && length(var.foundry_account_name) <= 48 + error_message = "foundry_account_name must be between 2 and 48 characters to leave room for optional '-'." + } +} + +variable "sku_name" { + description = "SKU name (for example: S0)." + type = string + default = "S0" +} + +variable "allow_project_management" { + description = "Enable/Disable project management for Foundry. Must be true to create projects under the account." + type = bool + default = true +} + +variable "custom_subdomain_name" { + description = "Optional custom subdomain for token-based auth. Some configurations require this. If null, a default value is derived from the account name." + type = string + default = null +} + +variable "public_network_access_enabled" { + description = "Whether public network access is enabled for the Foundry account." + type = bool + default = true +} + +variable "create_project" { + description = "Whether to create a Foundry project under the account." + type = bool + default = true +} + +variable "project_name" { + description = "Name of the Foundry project resource (2-64, pattern: ^[a-zA-Z0-9][a-zA-Z0-9_.-]*$). If null and create_project is true, a default value is derived." + type = string + default = null +} + +variable "project_display_name" { + description = "Display name for the project." + type = string + default = null +} + +variable "project_description" { + description = "Description for the project." + type = string + default = "" +} + +variable "enable_system_assigned_identity" { + description = "Whether to enable a System Assigned Managed Identity on the Foundry account." + type = bool + default = true +} + +variable "tags" { + description = "A map of tags to assign to resources." + type = map(string) + default = {} +} diff --git a/8_ai-ml/ai-search/README.md b/8_ai-ml/ai-search/README.md new file mode 100644 index 0000000..7107c4d --- /dev/null +++ b/8_ai-ml/ai-search/README.md @@ -0,0 +1,33 @@ +# Terraform Template - Azure AI Search + +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-17 + +------------------------------------------ + +> This template creates an Azure AI Search service. + +image + +image + +## Usage + +```sh +az login +terraform init -upgrade +terraform validate +terraform plan +terraform apply -auto-approve +``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/8_ai-ml/ai-search/main.tf b/8_ai-ml/ai-search/main.tf new file mode 100644 index 0000000..666f148 --- /dev/null +++ b/8_ai-ml/ai-search/main.tf @@ -0,0 +1,56 @@ +data "azurerm_client_config" "current" {} + +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 + base_name = var.search_service_name + sku = var.sku + } +} + +locals { + suffix = var.append_random_suffix ? random_string.suffix.result : "" + name_raw = lower(var.append_random_suffix ? "${var.search_service_name}-${local.suffix}" : var.search_service_name) + name_sanitized = substr(join("", regexall("[a-z0-9-]", local.name_raw)), 0, 60) +} + +resource "azurerm_search_service" "search" { + name = local.name_sanitized + resource_group_name = var.resource_group_name + location = var.location + + sku = var.sku + replica_count = var.replica_count + partition_count = var.partition_count + + public_network_access_enabled = var.public_network_access_enabled + local_authentication_enabled = var.local_authentication_enabled + + tags = var.tags + + depends_on = [ + azapi_resource.resource_group + ] +} diff --git a/8_ai-ml/ai-search/outputs.tf b/8_ai-ml/ai-search/outputs.tf new file mode 100644 index 0000000..4f88cdd --- /dev/null +++ b/8_ai-ml/ai-search/outputs.tf @@ -0,0 +1,19 @@ +output "resource_group_id" { + description = "The resource ID of the Resource Group." + value = azapi_resource.resource_group.id +} + +output "search_service_id" { + description = "The resource ID of the Azure AI Search service." + value = azurerm_search_service.search.id +} + +output "search_service_name" { + description = "The name of the Azure AI Search service." + value = azurerm_search_service.search.name +} + +output "search_service_endpoint" { + description = "The endpoint of the Azure AI Search service." + value = "https://${azurerm_search_service.search.name}.search.windows.net" +} diff --git a/8_ai-ml/ai-search/provider.tf b/8_ai-ml/ai-search/provider.tf new file mode 100644 index 0000000..e3a2be8 --- /dev/null +++ b/8_ai-ml/ai-search/provider.tf @@ -0,0 +1,35 @@ +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" + } + } +} + +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) +} diff --git a/8_ai-ml/ai-search/terraform.tfvars b/8_ai-ml/ai-search/terraform.tfvars new file mode 100644 index 0000000..01b471a --- /dev/null +++ b/8_ai-ml/ai-search/terraform.tfvars @@ -0,0 +1,19 @@ +resource_group_name = "rg-ai-search-dev" +location = "eastus" + +append_random_suffix = true +random_suffix_length = 6 + +search_service_name = "srch-dev" +sku = "basic" +replica_count = 1 +partition_count = 1 + +public_network_access_enabled = true +local_authentication_enabled = true + +tags = { + env = "dev" + area = "ai-ml" + iac = "terraform" +} diff --git a/8_ai-ml/ai-search/variables.tf b/8_ai-ml/ai-search/variables.tf new file mode 100644 index 0000000..4a16a36 --- /dev/null +++ b/8_ai-ml/ai-search/variables.tf @@ -0,0 +1,82 @@ +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 for the deployment." + 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 service name to reduce naming 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 "search_service_name" { + description = "Base name for the Azure AI Search service. If append_random_suffix is true, the final name will be '-' (then sanitized to lowercase letters/numbers/hyphens)." + type = string + + validation { + condition = length(trimspace(var.search_service_name)) >= 2 && length(var.search_service_name) <= 48 + error_message = "search_service_name must be between 2 and 48 characters to leave room for optional '-'." + } +} + +variable "sku" { + description = "Azure AI Search SKU (for example: basic, standard, standard2, standard3)." + type = string + default = "basic" +} + +variable "replica_count" { + description = "Number of replicas." + type = number + default = 1 +} + +variable "partition_count" { + description = "Number of partitions." + type = number + default = 1 +} + +variable "public_network_access_enabled" { + description = "Whether public network access is enabled." + type = bool + default = true +} + +variable "local_authentication_enabled" { + description = "Whether local API key auth is enabled." + type = bool + default = true +} + +variable "tags" { + description = "A map of tags to assign to resources." + type = map(string) + default = {} +} diff --git a/8_ai-ml/ai-services/README.md b/8_ai-ml/ai-services/README.md new file mode 100644 index 0000000..4234859 --- /dev/null +++ b/8_ai-ml/ai-services/README.md @@ -0,0 +1,29 @@ +# Terraform Template - Azure AI Services (Cognitive Services Account) + +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-17 + +------------------------------------------ + +> This template creates a Cognitive Services account (Azure AI Services). Configure `kind` for your workload (for example OpenAI, SpeechServices, TextAnalytics). + +## Usage + +```sh +az login +terraform init -upgrade +terraform validate +terraform plan +terraform apply -auto-approve +``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/8_ai-ml/ai-services/main.tf b/8_ai-ml/ai-services/main.tf new file mode 100644 index 0000000..02f15e1 --- /dev/null +++ b/8_ai-ml/ai-services/main.tf @@ -0,0 +1,62 @@ +data "azurerm_client_config" "current" {} + +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 + base_name = var.cognitive_account_name + kind = var.kind + sku = var.sku_name + } +} + +locals { + suffix = var.append_random_suffix ? random_string.suffix.result : "" + name_raw = var.append_random_suffix ? "${var.cognitive_account_name}-${local.suffix}" : var.cognitive_account_name +} + +resource "azurerm_cognitive_account" "cog" { + name = local.name_raw + location = var.location + resource_group_name = var.resource_group_name + + kind = var.kind + sku_name = var.sku_name + + custom_subdomain_name = var.custom_subdomain_name + public_network_access_enabled = var.public_network_access_enabled + + dynamic "identity" { + for_each = var.enable_system_assigned_identity ? [1] : [] + content { + type = "SystemAssigned" + } + } + + tags = var.tags + + depends_on = [ + azapi_resource.resource_group + ] +} diff --git a/8_ai-ml/ai-services/outputs.tf b/8_ai-ml/ai-services/outputs.tf new file mode 100644 index 0000000..68a86a1 --- /dev/null +++ b/8_ai-ml/ai-services/outputs.tf @@ -0,0 +1,19 @@ +output "resource_group_id" { + description = "The resource ID of the Resource Group." + value = azapi_resource.resource_group.id +} + +output "cognitive_account_id" { + description = "The resource ID of the Cognitive Services account." + value = azurerm_cognitive_account.cog.id +} + +output "cognitive_account_name" { + description = "The name of the Cognitive Services account." + value = azurerm_cognitive_account.cog.name +} + +output "cognitive_account_endpoint" { + description = "The endpoint of the Cognitive Services account." + value = azurerm_cognitive_account.cog.endpoint +} diff --git a/8_ai-ml/ai-services/provider.tf b/8_ai-ml/ai-services/provider.tf new file mode 100644 index 0000000..e3a2be8 --- /dev/null +++ b/8_ai-ml/ai-services/provider.tf @@ -0,0 +1,35 @@ +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" + } + } +} + +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) +} diff --git a/8_ai-ml/ai-services/terraform.tfvars b/8_ai-ml/ai-services/terraform.tfvars new file mode 100644 index 0000000..8b24152 --- /dev/null +++ b/8_ai-ml/ai-services/terraform.tfvars @@ -0,0 +1,21 @@ +resource_group_name = "rg-ai-services-dev" +location = "eastus" + +append_random_suffix = true +random_suffix_length = 6 + +cognitive_account_name = "aiservices-dev" +kind = "CognitiveServices" +sku_name = "S0" + +public_network_access_enabled = true +enable_system_assigned_identity = true + +# Optional +# custom_subdomain_name = "myaiservicesdev" + +tags = { + env = "dev" + area = "ai-ml" + iac = "terraform" +} diff --git a/8_ai-ml/ai-services/variables.tf b/8_ai-ml/ai-services/variables.tf new file mode 100644 index 0000000..4cd39c7 --- /dev/null +++ b/8_ai-ml/ai-services/variables.tf @@ -0,0 +1,82 @@ +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 for the deployment." + 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 account name to reduce naming 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 "cognitive_account_name" { + description = "Base name for the Azure AI Services (Cognitive Services) account. If append_random_suffix is true, the final name will be '-'." + type = string + + validation { + condition = length(trimspace(var.cognitive_account_name)) >= 2 && length(var.cognitive_account_name) <= 48 + error_message = "cognitive_account_name must be between 2 and 48 characters to leave room for optional '-'." + } +} + +variable "kind" { + description = "Cognitive Services kind (examples: CognitiveServices, OpenAI, SpeechServices, TextAnalytics, ComputerVision)." + type = string + default = "CognitiveServices" +} + +variable "sku_name" { + description = "SKU name (for example: S0)." + type = string + default = "S0" +} + +variable "custom_subdomain_name" { + description = "Optional custom subdomain for token-based auth. Some configurations (like private endpoints/network ACLs) require this." + type = string + default = null +} + +variable "public_network_access_enabled" { + description = "Whether public network access is enabled." + type = bool + default = true +} + +variable "enable_system_assigned_identity" { + description = "Whether to enable a System Assigned Managed Identity on the account." + type = bool + default = true +} + +variable "tags" { + description = "A map of tags to assign to resources." + type = map(string) + default = {} +} diff --git a/8_ai-ml/machine-learning/README.md b/8_ai-ml/machine-learning/README.md index cd09652..7a0ae34 100644 --- a/8_ai-ml/machine-learning/README.md +++ b/8_ai-ml/machine-learning/README.md @@ -26,3 +26,10 @@ terraform validate terraform plan terraform apply -auto-approve ``` + + +
+ Total views +

Refresh Date: 2026-02-17

+
+ diff --git a/README.md b/README.md index 3c46772..96d6989 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,10 @@ Last updated: 2026-02-16 AI and ML (Click to expand) - [AI and ML](./8_ai-ml) + - [Azure Machine Learning (Workspace)](./8_ai-ml/machine-learning) + - [Azure AI Search (Search Service)](./8_ai-ml/ai-search) + - [Azure AI Services (Cognitive Services Account)](./8_ai-ml/ai-services) + - [Microsoft Foundry (Azure AI Foundry)](./8_ai-ml/ai-foundry)