Skip to content
Open
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
1 change: 1 addition & 0 deletions src/000-cloud/031-fabric/terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Contains all the resources needed for Fabric based resources.
| [terraform_data.defer_fabric_capacity_created](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
| [terraform_data.defer_fabric_capacity_existing](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
| [terraform_data.defer_fabric_workspace](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
| [terraform_data.validate_inputs](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
| [fabric_capacity.created](https://registry.terraform.io/providers/microsoft/fabric/1.10.0/docs/data-sources/capacity) | data source |
| [fabric_capacity.existing](https://registry.terraform.io/providers/microsoft/fabric/1.10.0/docs/data-sources/capacity) | data source |
| [fabric_workspace.existing](https://registry.terraform.io/providers/microsoft/fabric/1.10.0/docs/data-sources/workspace) | data source |
Expand Down
14 changes: 14 additions & 0 deletions src/000-cloud/031-fabric/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ locals {
workspace_id = try(module.fabric_workspace[0].workspace.id, data.fabric_workspace.existing[0].id, null)
}

/*
* Input Validation
*/

// Validates rules that span multiple input variables.
resource "terraform_data" "validate_inputs" {
lifecycle {
precondition {
condition = !var.should_create_fabric_capacity || length(var.fabric_capacity_admins) > 0
error_message = "At least one administrator must be specified for Fabric capacity when creating a capacity."
}
}
}

// Defer computation to prevent `data` objects from querying for state on `terraform plan`.
// Needed for testing and build system compatibility.
resource "terraform_data" "defer_fabric_capacity_created" {
Expand Down
2 changes: 1 addition & 1 deletion src/000-cloud/031-fabric/terraform/tests/base.tftest.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,6 @@ run "create_capacity_without_admins" {
}

expect_failures = [
var.fabric_capacity_admins,
terraform_data.validate_inputs,
]
}
4 changes: 0 additions & 4 deletions src/000-cloud/031-fabric/terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ variable "fabric_capacity_admins" {
EOT
type = list(string)
default = []
validation {
condition = !var.should_create_fabric_capacity || length(var.fabric_capacity_admins) > 0
error_message = "At least one administrator must be specified for Fabric capacity when creating a capacity."
}
}

variable "fabric_capacity_sku" {
Expand Down
7 changes: 4 additions & 3 deletions src/000-cloud/036-managed-redis/terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ Supports Microsoft Entra ID authentication and customer-managed key encryption.

## Resources

| Name | Type |
|----------------------------------------------------------------------------------------------------------------|----------|
| [terraform_data.defer](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
| Name | Type |
|--------------------------------------------------------------------------------------------------------------------------|----------|
| [terraform_data.defer](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |
| [terraform_data.validate_inputs](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |

## Modules

Expand Down
19 changes: 18 additions & 1 deletion src/000-cloud/036-managed-redis/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ locals {
redis_name = "redis-${var.resource_prefix}-${var.environment}-${var.instance}"
}

/*
* Input Validation
*/

// Validates rules that span multiple input variables.
resource "terraform_data" "validate_inputs" {
lifecycle {
precondition {
condition = var.should_enable_private_endpoint ? var.private_endpoint_subnet != null : true
error_message = "private_endpoint_subnet is required when should_enable_private_endpoint is true."
}
}
}

/*
* Azure Managed Redis Cache
*/
Expand All @@ -17,6 +31,9 @@ module "managed_redis" {
count = var.should_deploy_redis ? 1 : 0
source = "./modules/managed-redis"

// Keeps the input precondition in targeted plans. The module has no data sources, so this defers no reads.
depends_on = [terraform_data.validate_inputs]

// Core Configuration
location = var.location
name = local.redis_name
Expand All @@ -36,7 +53,7 @@ module "managed_redis" {
private_endpoint_subnet_id = try(var.private_endpoint_subnet.id, null)
private_dns_zone_id = var.private_dns_zone_id
should_create_private_dns_zone = var.should_create_private_dns_zone
should_enable_private_endpoint = var.should_enable_private_endpoint
should_enable_private_endpoint = var.should_enable_private_endpoint && var.private_endpoint_subnet != null
virtual_network_id = try(var.virtual_network.id, null)
}

Expand Down
5 changes: 0 additions & 5 deletions src/000-cloud/036-managed-redis/terraform/variables.deps.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ variable "private_endpoint_subnet" {
id = string
})
default = null

validation {
condition = var.should_enable_private_endpoint ? var.private_endpoint_subnet != null : true
error_message = "private_endpoint_subnet is required when should_enable_private_endpoint is true."
}
}

variable "resource_group" {
Expand Down
40 changes: 34 additions & 6 deletions src/000-cloud/080-azureml/terraform/main.tf
Comment thread
ShivamSharma43 marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,32 @@
* existing cloud infrastructure including Key Vault, Storage Account, Application Insights, and networking.
*/

data "azurerm_client_config" "current" {}
/*
* Input Validation
*/

// Validates rules that span multiple input variables.
// On a data source rather than a managed resource, so it adds no planned changes.
data "azurerm_client_config" "current" {
lifecycle {
precondition {
condition = !var.should_assign_ml_workload_identity_roles || var.ml_workload_identity != null
error_message = "ml_workload_identity must be provided when should_assign_ml_workload_identity_roles is true."
}
precondition {
condition = !var.should_associate_network_security_group || var.network_security_group != null
error_message = "network_security_group must be provided when should_associate_network_security_group is true."
}
precondition {
condition = !var.should_enable_nat_gateway || var.nat_gateway != null
error_message = "nat_gateway must be provided when should_enable_nat_gateway is true."
}
precondition {
condition = var.compute_cluster_min_nodes <= var.compute_cluster_max_nodes
error_message = "Minimum node count must be less than or equal to compute_cluster_max_nodes."
}
}
}

/*
* Network Module for Azure ML Compute Cluster
Expand All @@ -17,6 +42,9 @@ module "network" {

source = "./modules/network"

// Keeps the input preconditions in targeted plans (workspace and inference integration inherit it).
depends_on = [data.azurerm_client_config.current]

// Resource dependencies first
resource_group = var.resource_group
network_security_group = var.network_security_group
Expand All @@ -29,9 +57,9 @@ module "network" {

// Optional parameters
default_outbound_access_enabled = var.default_outbound_access_enabled
should_associate_network_security_group = var.should_associate_network_security_group
should_enable_nat_gateway = var.should_enable_nat_gateway
nat_gateway_id = var.should_enable_nat_gateway ? var.nat_gateway.id : null
should_associate_network_security_group = var.should_associate_network_security_group && var.network_security_group != null
Comment thread
ShivamSharma43 marked this conversation as resolved.
should_enable_nat_gateway = var.should_enable_nat_gateway && var.nat_gateway != null
nat_gateway_id = try(var.nat_gateway.id, null)
subnet_address_prefixes_azureml = var.subnet_address_prefixes_azureml
}

Expand All @@ -57,7 +85,7 @@ module "workspace" {
should_assign_current_user_workspace_roles = var.should_assign_current_user_workspace_roles
current_user_object_id = var.should_assign_current_user_workspace_roles ? data.azurerm_client_config.current.object_id : null
ml_workload_identity = var.ml_workload_identity
should_assign_ml_workload_identity_roles = var.should_assign_ml_workload_identity_roles
should_assign_ml_workload_identity_roles = var.should_assign_ml_workload_identity_roles && var.ml_workload_identity != null

// Role assignment configuration
should_assign_workspace_managed_identity_roles = var.should_assign_workspace_managed_identity_roles
Expand Down Expand Up @@ -171,7 +199,7 @@ module "inference_cluster_integration" {

ml_workload_identity = var.ml_workload_identity
ml_workload_subjects = var.ml_workload_subjects
should_configure_ml_workload_identity = var.should_assign_ml_workload_identity_roles
should_configure_ml_workload_identity = var.should_assign_ml_workload_identity_roles && var.ml_workload_identity != null

// App Configuration integration for volcano scheduler
volcano_scheduler_configmap_name = try(var.kubernetes.app_configuration_configmap_name, null)
Expand Down
151 changes: 151 additions & 0 deletions src/000-cloud/080-azureml/terraform/tests/base.tftest.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,154 @@ run "reject_invalid_resource_prefix" {
var.resource_prefix,
]
}

# Test 8: NAT gateway association requires a NAT gateway object
run "reject_nat_gateway_enabled_without_nat_gateway" {
command = plan

variables {
resource_prefix = run.setup_tests.resource_prefix
environment = "test"
location = run.setup_tests.location
resource_group = run.setup_tests.resource_group
application_insights = run.setup_tests.application_insights
key_vault = run.setup_tests.key_vault
storage_account = run.setup_tests.storage_account
acr = run.setup_tests.acr
virtual_network = run.setup_tests.virtual_network

should_enable_nat_gateway = true
}

expect_failures = [
data.azurerm_client_config.current,
]
}

# Test 9: A plan targeting only the network module still enforces the NAT gateway rule
run "reject_nat_gateway_enabled_without_nat_gateway_targeted" {
command = plan

plan_options {
target = [module.network]
}

variables {
resource_prefix = run.setup_tests.resource_prefix
environment = "test"
location = run.setup_tests.location
resource_group = run.setup_tests.resource_group
application_insights = run.setup_tests.application_insights
key_vault = run.setup_tests.key_vault
storage_account = run.setup_tests.storage_account
acr = run.setup_tests.acr
virtual_network = run.setup_tests.virtual_network

should_enable_nat_gateway = true
}

expect_failures = [
data.azurerm_client_config.current,
]
}

# Test 10: A plan targeting only the network module still enforces the NSG rule
run "reject_nsg_association_without_nsg_targeted" {
command = plan

plan_options {
target = [module.network]
}

variables {
resource_prefix = run.setup_tests.resource_prefix
environment = "test"
location = run.setup_tests.location
resource_group = run.setup_tests.resource_group
application_insights = run.setup_tests.application_insights
key_vault = run.setup_tests.key_vault
storage_account = run.setup_tests.storage_account
acr = run.setup_tests.acr
virtual_network = run.setup_tests.virtual_network

should_associate_network_security_group = true
}

expect_failures = [
data.azurerm_client_config.current,
]
}

# Test 11: Workload identity role assignment requires a workload identity object
run "reject_workload_identity_roles_without_identity" {
command = plan

variables {
resource_prefix = run.setup_tests.resource_prefix
environment = "test"
location = run.setup_tests.location
resource_group = run.setup_tests.resource_group
application_insights = run.setup_tests.application_insights
key_vault = run.setup_tests.key_vault
storage_account = run.setup_tests.storage_account
acr = run.setup_tests.acr
virtual_network = run.setup_tests.virtual_network

should_assign_ml_workload_identity_roles = true
}

expect_failures = [
data.azurerm_client_config.current,
]
}

# Test 12: A plan targeting only the workspace module still enforces the workload identity rule
run "reject_workload_identity_roles_without_identity_targeted" {
command = plan

plan_options {
target = [module.workspace]
}

variables {
resource_prefix = run.setup_tests.resource_prefix
environment = "test"
location = run.setup_tests.location
resource_group = run.setup_tests.resource_group
application_insights = run.setup_tests.application_insights
key_vault = run.setup_tests.key_vault
storage_account = run.setup_tests.storage_account
acr = run.setup_tests.acr
virtual_network = run.setup_tests.virtual_network

should_assign_ml_workload_identity_roles = true
}

expect_failures = [
data.azurerm_client_config.current,
]
}

# Test 13: Minimum node count cannot exceed the maximum node count
run "reject_min_nodes_above_max_nodes" {
command = plan

variables {
resource_prefix = run.setup_tests.resource_prefix
environment = "test"
location = run.setup_tests.location
resource_group = run.setup_tests.resource_group
application_insights = run.setup_tests.application_insights
key_vault = run.setup_tests.key_vault
storage_account = run.setup_tests.storage_account
acr = run.setup_tests.acr
virtual_network = run.setup_tests.virtual_network

compute_cluster_min_nodes = 3
compute_cluster_max_nodes = 2
}

expect_failures = [
data.azurerm_client_config.current,
]
}
12 changes: 0 additions & 12 deletions src/000-cloud/080-azureml/terraform/variables.deps.tf
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ variable "ml_workload_identity" {
})
description = "AzureML workload managed identity object from security identity containing id and principal_id."
default = null
validation {
condition = (!var.should_assign_ml_workload_identity_roles) || (var.ml_workload_identity != null)
error_message = "ml_workload_identity must be provided when should_assign_ml_workload_identity_roles is true."
}
}

variable "network_security_group" {
Expand All @@ -86,10 +82,6 @@ variable "network_security_group" {
})
description = "Network security group from 050-networking component."
default = null
validation {
condition = (!var.should_associate_network_security_group) || (var.network_security_group != null)
error_message = "network_security_group must be provided when should_associate_network_security_group is true."
}
}

variable "virtual_network" {
Expand All @@ -108,8 +100,4 @@ variable "nat_gateway" {
})
description = "NAT gateway object from the networking component for managed outbound access."
default = null
validation {
condition = (!var.should_enable_nat_gateway) || (var.nat_gateway != null)
error_message = "nat_gateway must be provided when should_enable_nat_gateway is true."
}
}
4 changes: 2 additions & 2 deletions src/000-cloud/080-azureml/terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ variable "compute_cluster_min_nodes" {
default = 0

validation {
condition = var.compute_cluster_min_nodes >= 0 && var.compute_cluster_min_nodes <= var.compute_cluster_max_nodes
error_message = "Minimum node count must be greater than or equal to 0 and less than or equal to compute_cluster_max_nodes."
condition = var.compute_cluster_min_nodes >= 0
error_message = "Minimum node count must be greater than or equal to 0."
}
}

Expand Down
Loading