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
4 changes: 2 additions & 2 deletions .github/tests/scripts/generate-matrix.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ $combinations = [ordered]@{
infrastructureAsCode = @("terraform")
agentType = @("public", "private", "none")
operatingSystem = @("ubuntu")
starterModule = @("test_nested")
starterModule = @("test")
regions = @("multi")
terraformVersion = @("latest")
deployAzureResources = @("true")
Expand All @@ -58,7 +58,7 @@ $combinations = [ordered]@{
infrastructureAsCode = @("terraform")
agentType = @("public", "private", "none")
operatingSystem = @("ubuntu")
starterModule = @("test_nested")
starterModule = @("test")
regions = @("multi")
terraformVersion = @("latest")
deployAzureResources = @("true")
Expand Down
21 changes: 20 additions & 1 deletion .github/workflows/end-to-end-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,21 @@ jobs:
$Inputs["child_management_group_display_name"] = "E2E Test"
$Inputs["resource_group_location"] = $location

# Terraform
if($infrastructureAsCode -eq "terraform") {
$Inputs["resource_name_suffix"] = $uniqueId
$architectureFilePath = "${{ env.STARTER_MODULE_FOLDER }}/templates/$starterModule/lib/architecture_definitions/alz_custom.alz_architecture_definition.yaml"
$architectureFile = Get-Content -Path $architectureFilePath -Raw
$architectureFile = $architectureFile.Replace("- id: child-test", "- id: child-test-$uniqueId")
$architectureFile = $architectureFile.Replace("display_name: Child Test", "display_name: Child Test $uniqueId")
$architectureFile = $architectureFile.Replace("- id: test", "- id: test-$uniqueId")
$architectureFile = $architectureFile.Replace("display_name: Test", "display_name: Test $uniqueId")
$architectureFile = $architectureFile.Replace("parent_id: test", "parent_id: test-$uniqueId")
$architectureFile | Out-File -FilePath $architectureFilePath -Encoding utf8 -Force
Write-Host "Modified Architecture File Content:"
Write-Host $architectureFile
}

# Bicep Classic
if($infrastructureAsCode -eq "bicep-classic") {
$Inputs["Prefix"] = $uniqueId
Expand All @@ -309,7 +324,8 @@ jobs:
# Bicep
if($infrastructureAsCode -eq "bicep") {
$Inputs["network_type"] = "none"
$Inputs["intermediate_root_management_group_id"] = "alz-$uniqueId"
$Inputs["management_group_int_root_id"] = "alz-$uniqueId"
$Inputs["management_group_int_root_name"] = "alz-$uniqueId"
$Inputs["management_group_id_prefix"] = ""
$Inputs["management_group_id_postfix"] = ""
$Inputs["management_group_name_prefix"] = ""
Expand All @@ -319,6 +335,9 @@ jobs:
$json = ConvertTo-Json $Inputs -Depth 100
$json | Out-File -FilePath inputs.json -Encoding utf8 -Force

Write-Host "Inputs File Content:"
Write-Host $json

shell: pwsh

- name: Run ALZ PowerShell
Expand Down
50 changes: 28 additions & 22 deletions alz/azuredevops/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,18 @@ module "azure" {
container_registry_dockerfile_name = var.agent_container_image_dockerfile
container_registry_dockerfile_repository_folder_url = local.agent_container_instance_dockerfile_url
custom_role_definitions = var.iac_type == "terraform" ? local.custom_role_definitions_terraform : (var.iac_type == "bicep" ? local.custom_role_definitions_bicep : local.custom_role_definitions_bicep_classic)
role_assignments = var.iac_type == "terraform" ? var.role_assignments_terraform : var.role_assignments_bicep
role_assignments = var.iac_type == "terraform" ? var.role_assignments_terraform : (var.iac_type == "bicep" ? var.role_assignments_bicep : var.role_assignments_bicep_classic)
storage_account_blob_soft_delete_enabled = var.storage_account_blob_soft_delete_enabled
storage_account_blob_soft_delete_retention_days = var.storage_account_blob_soft_delete_retention_days
storage_account_blob_versioning_enabled = var.storage_account_blob_versioning_enabled
storage_account_container_soft_delete_enabled = var.storage_account_container_soft_delete_enabled
storage_account_container_soft_delete_retention_days = var.storage_account_container_soft_delete_retention_days
tenant_role_assignment_enabled = var.iac_type == "bicep" && var.bicep_tenant_role_assignment_enabled
tenant_role_assignment_role_definition_name = var.bicep_tenant_role_assignment_role_definition_name
intermediate_root_management_group_creation_enabled = var.iac_type != "bicep-classic"
intermediate_root_management_group_id = module.file_manipulation.intermediate_root_management_group_id
intermediate_root_management_group_display_name = module.file_manipulation.intermediate_root_management_group_display_name
move_subscriptions_to_target_management_group = var.iac_type != "bicep-classic"
}

module "azure_devops" {
Expand Down Expand Up @@ -99,25 +103,27 @@ module "azure_devops" {
}

module "file_manipulation" {
source = "../../modules/file_manipulation"
vcs_type = "azuredevops"
files = module.files.files
use_self_hosted_agents_runners = var.use_self_hosted_agents
resource_names = local.resource_names
use_separate_repository_for_templates = var.use_separate_repository_for_templates
iac_type = var.iac_type
module_folder_path = local.starter_module_folder_path
bicep_config_file_path = var.bicep_config_file_path
starter_module_name = var.starter_module_name
project_or_organization_name = var.azure_devops_project_name
root_module_folder_relative_path = var.root_module_folder_relative_path
on_demand_folder_repository = var.on_demand_folder_repository
on_demand_folder_artifact_name = var.on_demand_folder_artifact_name
ci_template_file_name = local.ci_template_file_name
cd_template_file_name = local.cd_template_file_name
pipeline_target_folder_name = local.target_folder_name
bicep_parameters_file_path = var.bicep_parameters_file_path
agent_pool_or_runner_configuration = local.agent_pool_or_runner_configuration
pipeline_files_directory_path = local.pipeline_files_directory_path
pipeline_template_files_directory_path = local.pipeline_template_files_directory_path
source = "../../modules/file_manipulation"
vcs_type = "azuredevops"
files = module.files.files
use_self_hosted_agents_runners = var.use_self_hosted_agents
resource_names = local.resource_names
use_separate_repository_for_templates = var.use_separate_repository_for_templates
iac_type = var.iac_type
module_folder_path = local.starter_module_folder_path
bicep_config_file_path = var.bicep_config_file_path
starter_module_name = var.starter_module_name
project_or_organization_name = var.azure_devops_project_name
root_module_folder_relative_path = var.root_module_folder_relative_path
on_demand_folder_repository = var.on_demand_folder_repository
on_demand_folder_artifact_name = var.on_demand_folder_artifact_name
ci_template_file_name = local.ci_template_file_name
cd_template_file_name = local.cd_template_file_name
pipeline_target_folder_name = local.target_folder_name
bicep_parameters_file_path = var.bicep_parameters_file_path
agent_pool_or_runner_configuration = local.agent_pool_or_runner_configuration
pipeline_files_directory_path = local.pipeline_files_directory_path
pipeline_template_files_directory_path = local.pipeline_template_files_directory_path
terraform_architecture_file_path = var.terraform_architecture_file_path
terraform_intermediate_root_management_group_state_resource_path_for_import = var.terraform_intermediate_root_management_group_state_resource_path_for_import
}
2 changes: 0 additions & 2 deletions alz/azuredevops/pipelines/bicep/templates/cd-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ stages:
serviceConnection: '${service_connection_name_plan}'
templateFilePath: '${script_file.templateFilePath}'
templateParametersFilePath: '${script_file.templateParametersFilePath}'
managementGroupId: '${script_file.managementGroupIdVariable}'
subscriptionId: '${script_file.subscriptionIdVariable}'
resourceGroupName: '${script_file.resourceGroupNameVariable}'
location: '$(LOCATION)'
Expand Down Expand Up @@ -128,7 +127,6 @@ stages:
serviceConnection: '${service_connection_name_apply}'
templateFilePath: '${script_file.templateFilePath}'
templateParametersFilePath: '${script_file.templateParametersFilePath}'
managementGroupId: '${script_file.managementGroupIdVariable}'
subscriptionId: '${script_file.subscriptionIdVariable}'
resourceGroupName: '${script_file.resourceGroupNameVariable}'
location: '$(LOCATION)'
Expand Down
1 change: 0 additions & 1 deletion alz/azuredevops/pipelines/bicep/templates/ci-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ stages:
serviceConnection: '${service_connection_name_plan}'
templateFilePath: '${script_file.templateFilePath}'
templateParametersFilePath: '${script_file.templateParametersFilePath}'
managementGroupId: '${script_file.managementGroupIdVariable}'
subscriptionId: '${script_file.subscriptionIdVariable}'
resourceGroupName: '${script_file.resourceGroupNameVariable}'
location: '$(LOCATION)'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ parameters:
type: string
- name: templateParametersFilePath
type: string
- name: managementGroupId
type: string
default: ''
- name: subscriptionId
type: string
default: ''
Expand Down Expand Up @@ -71,7 +68,8 @@ steps:
}

# Generate deployment stack name
$deploymentPrefix = $env:MANAGEMENT_GROUP_ID_PREFIX + $env:INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID + $env:MANAGEMENT_GROUP_ID_POSTFIX
$intRootMgId = $env:MANAGEMENT_GROUP_ID_PREFIX + $env:INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID + $env:MANAGEMENT_GROUP_ID_POSTFIX
$deploymentPrefix = $intRootMgId
$deploymentNameBase = "$${{ parameters.name }}".Replace(" ", "-")
$deploymentNameMaxLength = 64 - $deploymentPrefix.Length - 1
if ($deploymentNameBase.Length -gt $deploymentNameMaxLength) {
Expand All @@ -89,7 +87,7 @@ steps:
Write-Host "Deployment Name: $deploymentName" -ForegroundColor DarkGray
Write-Host "Template File Path: $${{ parameters.templateFilePath }}" -ForegroundColor DarkGray
Write-Host "Template Parameters File Path: $${{ parameters.templateParametersFilePath }}" -ForegroundColor DarkGray
Write-Host "Management Group Id: $${{ parameters.managementGroupId }}" -ForegroundColor DarkGray
Write-Host "Management Group Id: $intRootMgId" -ForegroundColor DarkGray
Write-Host "Subscription Id: $${{ parameters.subscriptionId }}" -ForegroundColor DarkGray
Write-Host "Resource Group Name: $${{ parameters.resourceGroupName }}" -ForegroundColor DarkGray
Write-Host "Location: $${{ parameters.location }}" -ForegroundColor DarkGray
Expand Down Expand Up @@ -128,14 +126,9 @@ steps:
try {
switch ($deploymentType) {
"managementGroup" {
$targetManagementGroupId = "$${{ parameters.managementGroupId }}"
if ([string]::IsNullOrWhiteSpace($targetManagementGroupId)) {
$targetManagementGroupId = (Get-AzContext).Tenant.TenantId
}

Write-Host "Running Management Group What-If: $deploymentName" -ForegroundColor Cyan
$whatIfParameters.Location = "$${{ parameters.location }}"
$whatIfParameters.ManagementGroupId = $targetManagementGroupId
$whatIfParameters.ManagementGroupId = $intRootMgId
$result = New-AzManagementGroupDeployment @whatIfParameters
}
"subscription" {
Expand Down Expand Up @@ -191,23 +184,18 @@ steps:
try {
switch ($deploymentType) {
"managementGroup" {
$targetManagementGroupId = "$${{ parameters.managementGroupId }}"
if ([string]::IsNullOrWhiteSpace($targetManagementGroupId)) {
$targetManagementGroupId = (Get-AzContext).Tenant.TenantId
}

# Clean up all deployments before each deployment to avoid quota issues
try {
Write-Host "Cleaning up existing deployments in management group..." -ForegroundColor Cyan
$allDeployments = Get-AzManagementGroupDeployment -ManagementGroupId $targetManagementGroupId -ErrorAction SilentlyContinue
$allDeployments = Get-AzManagementGroupDeployment -ManagementGroupId $intRootMgId -ErrorAction SilentlyContinue
if ($allDeployments -and $allDeployments.Count -gt 0) {
Write-Host "Found $($allDeployments.Count) deployment(s) to clean up" -ForegroundColor Yellow
$batchSize = 200
for ($i = 0; $i -lt $allDeployments.Count; $i += $batchSize) {
$batch = $allDeployments | Select-Object -Skip $i -First $batchSize
Write-Host " Deleting batch of $($batch.Count) deployments..." -ForegroundColor Gray
$batch | ForEach-Object -Parallel {
Remove-AzManagementGroupDeployment -ManagementGroupId $using:targetManagementGroupId -Name $_.DeploymentName -ErrorAction SilentlyContinue
Remove-AzManagementGroupDeployment -ManagementGroupId $using:intRootMgId -Name $_.DeploymentName -ErrorAction SilentlyContinue
} -ThrottleLimit 100
}
Write-Host "✓ All deployments cleaned up" -ForegroundColor Green
Expand All @@ -219,7 +207,7 @@ steps:
}

Write-Host "Creating Management Group Deployment Stack: $deploymentName" -ForegroundColor Cyan
$result = New-AzManagementGroupDeploymentStack @stackParameters -ManagementGroupId $targetManagementGroupId -Location "$${{ parameters.location }}"
$result = New-AzManagementGroupDeploymentStack @stackParameters -ManagementGroupId $intRootMgId -Location "$${{ parameters.location }}"
}
"subscription" {
if (-not [string]::IsNullOrWhiteSpace("$${{ parameters.subscriptionId }}")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,21 @@ steps:
Inline: |
$intRootMgId = "$(MANAGEMENT_GROUP_ID_PREFIX)$(INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID)$(MANAGEMENT_GROUP_ID_POSTFIX)"

$managementGroups = Get-AzManagementGroup
$intRootMg = $managementGroups | Where-Object { $_.Name -eq $intRootMgId }
$managementGroup = Get-AzManagementGroup -GroupName $intRootMgId -Expand

$firstDeployment = $true

if($intRootMg -eq $null) {
if($managementGroup -eq $null) {
Write-Warning "Cannot find the $intRootMgId Management Group, so assuming this is the first deployment."
} else {
Write-Host "Found the $intRootMgId Management Group, so assuming this is not the first deployment."
$firstDeployment = $false
Write-Host "Found the $intRootMgId Management Group."
$children = $managementGroup.Children | Where-Object { $_.Type -eq "Microsoft.Management/managementGroups" }
if($children.Count -gt 0) {
Write-Host "The $intRootMgId Management Group has child management groups, so this is NOT the first deployment."
$firstDeployment = $false
} else {
Write-Host "The $intRootMgId Management Group has NO child management groups, so assuming this is the first deployment."
}
}

Write-Host "##vso[task.setvariable variable=FIRST_DEPLOYMENT;]$firstDeployment"
Loading
Loading