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
[](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
```
+
+
+

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
+
+[](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.
+
+

+
+

+
+

+
+## Usage
+
+```sh
+az login
+terraform init -upgrade
+terraform validate
+terraform plan
+terraform apply -auto-approve
+```
+
+
+
+

+
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
+
+[](https://github.com/)
+[brown9804](https://github.com/brown9804)
+
+Last updated: 2026-02-17
+
+------------------------------------------
+
+> This template creates an Azure AI Search service.
+
+
+
+
+
+## Usage
+
+```sh
+az login
+terraform init -upgrade
+terraform validate
+terraform plan
+terraform apply -auto-approve
+```
+
+
+
+

+
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
+
+[](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
+```
+
+
+
+

+
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
```
+
+
+
+

+
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)