Skip to content

Commit eb00c82

Browse files
feat: improve deployment stack names (#124)
* feat: improve deployment stack names * ensure MG name uniqueness * fix what if check * fix what if * white space
1 parent d6b9bce commit eb00c82

15 files changed

Lines changed: 74 additions & 232 deletions

File tree

alz/azuredevops/locals.tf

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ locals {
3434
}
3535

3636
locals {
37-
target_subscriptions_legacy = distinct([var.subscription_id_connectivity, var.subscription_id_identity, var.subscription_id_management])
38-
target_subscriptions = length(var.subscription_ids) > 0 ? distinct(values(var.subscription_ids)) : local.target_subscriptions_legacy
37+
target_subscriptions = distinct(values(var.subscription_ids))
3938
}
4039

4140
locals {

alz/azuredevops/pipelines/bicep/templates/cd-template.yaml

Lines changed: 9 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -54,34 +54,15 @@ stages:
5454
parameters:
5555
serviceConnection: '${service_connection_name_plan}'
5656

57-
- task: AzurePowerShell@5
58-
displayName: 'Check for First Deployment'
59-
inputs:
60-
azureSubscription: '${service_connection_name_plan}'
61-
pwsh: true
62-
azurePowerShellVersion: LatestVersion
63-
ScriptType: "InlineScript"
64-
Inline: |
65-
$intRootMgId = "$(INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID)"
66-
67-
$managementGroups = Get-AzManagementGroup
68-
$intRootMg = $managementGroups | Where-Object { $_.Name -eq $intRootMgId }
69-
70-
$firstDeployment = $true
71-
72-
if($intRootMg -eq $null) {
73-
Write-Warning "Cannot find the $intRootMgId Management Group, so assuming this is the first deployment. We must skip what-if for some deployments since their dependent resources do not exist yet."
74-
} else {
75-
Write-Host "Found the $intRootMgId Management Group, so assuming this is not the first deployment."
76-
$firstDeployment = $false
77-
}
78-
79-
Write-Host "##vso[task.setvariable variable=FIRST_DEPLOYMENT;]$firstDeployment"
57+
- template: ./helpers/bicep-first-deployment-check.yaml
58+
parameters:
59+
serviceConnection: '${service_connection_name_plan}'
8060

8161
%{ for script_file in script_files ~}
8262
- $${{ if eq(parameters['${script_file.name}'], true) }}:
8363
- template: ./helpers/bicep-deploy.yaml
8464
parameters:
65+
name: '${script_file.name}'
8566
displayName: '${script_file.displayName}'
8667
serviceConnection: '${service_connection_name_plan}'
8768
templateFilePath: '${script_file.templateFilePath}'
@@ -130,38 +111,19 @@ stages:
130111
parameters:
131112
parametersFileName: $(PARAMETERS_FILE_NAME)
132113

133-
- task: AzurePowerShell@5
134-
displayName: 'Check for First Deployment'
135-
inputs:
136-
azureSubscription: '${service_connection_name_apply}'
137-
pwsh: true
138-
azurePowerShellVersion: LatestVersion
139-
ScriptType: "InlineScript"
140-
Inline: |
141-
$intRootMgId = "$(INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID)"
142-
143-
$managementGroups = Get-AzManagementGroup
144-
$intRootMg = $managementGroups | Where-Object { $_.Name -eq $intRootMgId }
145-
146-
$firstDeployment = $true
147-
148-
if($intRootMg -eq $null) {
149-
Write-Warning "Cannot find the $intRootMgId Management Group, so assuming this is the first deployment."
150-
} else {
151-
Write-Host "Found the $intRootMgId Management Group, so assuming this is not the first deployment."
152-
$firstDeployment = $false
153-
}
154-
155-
Write-Host "##vso[task.setvariable variable=FIRST_DEPLOYMENT;]$firstDeployment"
156-
157114
- template: ./helpers/bicep-installer.yaml
158115
parameters:
159116
serviceConnection: '${service_connection_name_apply}'
160117

118+
- template: ./helpers/bicep-first-deployment-check.yaml
119+
parameters:
120+
serviceConnection: '${service_connection_name_apply}'
121+
161122
%{ for script_file in script_files ~}
162123
- $${{ if eq(parameters['${script_file.name}'], true) }}:
163124
- template: ./helpers/bicep-deploy.yaml
164125
parameters:
126+
name: '${script_file.name}'
165127
displayName: '${script_file.displayName}'
166128
serviceConnection: '${service_connection_name_apply}'
167129
templateFilePath: '${script_file.templateFilePath}'

alz/azuredevops/pipelines/bicep/templates/ci-template.yaml

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -70,33 +70,14 @@ stages:
7070
parameters:
7171
serviceConnection: '${service_connection_name_plan}'
7272

73-
- task: AzurePowerShell@5
74-
displayName: 'Check for First Deployment'
75-
inputs:
76-
azureSubscription: '${service_connection_name_plan}'
77-
pwsh: true
78-
azurePowerShellVersion: LatestVersion
79-
ScriptType: "InlineScript"
80-
Inline: |
81-
$intRootMgId = "$(INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID)"
82-
83-
$managementGroups = Get-AzManagementGroup
84-
$intRootMg = $managementGroups | Where-Object { $_.Name -eq $intRootMgId }
85-
86-
$firstDeployment = $true
87-
88-
if($intRootMg -eq $null) {
89-
Write-Warning "Cannot find the $intRootMgId Management Group, so assuming this is the first deployment. We must skip what-if for some deployments since their dependent resources do not exist yet."
90-
} else {
91-
Write-Host "Found the $intRootMgId Management Group, so assuming this is not the first deployment."
92-
$firstDeployment = $false
93-
}
94-
95-
Write-Host "##vso[task.setvariable variable=FIRST_DEPLOYMENT;]$firstDeployment"
73+
- template: ./helpers/bicep-first-deployment-check.yaml
74+
parameters:
75+
serviceConnection: '${service_connection_name_plan}'
9676

9777
%{ for script_file in script_files ~}
9878
- template: ./helpers/bicep-deploy.yaml
9979
parameters:
80+
name: '${script_file.name}'
10081
displayName: '${script_file.displayName}'
10182
serviceConnection: '${service_connection_name_plan}'
10283
templateFilePath: '${script_file.templateFilePath}'

alz/azuredevops/pipelines/bicep/templates/helpers/bicep-deploy.yaml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
---
22
parameters:
3+
- name: name
4+
type: string
35
- name: displayName
46
type: string
57
- name: serviceConnection
@@ -68,18 +70,13 @@ steps:
6870
Write-Host ""
6971
}
7072
71-
# Generate deployment name without timestamp for consistent deployment stack names
72-
$deploymentPrefix = "alz"
73-
74-
$deploymentNameBase = "$${{ parameters.displayName }}".Replace(" ", "-")
75-
$deploymentNameBase = "$deploymentNameBase-$($env:TIME_STAMP)"
76-
73+
# Generate deployment stack name
74+
$deploymentPrefix = $env:MANAGEMENT_GROUP_ID_PREFIX + $env:INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID + $env:MANAGEMENT_GROUP_ID_POSTFIX
75+
$deploymentNameBase = "$${{ parameters.name }}".Replace(" ", "-")
7776
$deploymentNameMaxLength = 64 - $deploymentPrefix.Length - 1
78-
7977
if ($deploymentNameBase.Length -gt $deploymentNameMaxLength) {
8078
$deploymentNameBase = $deploymentNameBase.Substring(0, $deploymentNameMaxLength)
8179
}
82-
8380
$deploymentName = "$deploymentPrefix-$deploymentNameBase"
8481
8582
$modeText = if ($whatIfEnabled) { "What-If" } else { "Deployment Stack" }
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
parameters:
3+
- name: serviceConnection
4+
type: string
5+
6+
steps:
7+
- task: AzurePowerShell@5
8+
displayName: 'Check for First Deployment'
9+
inputs:
10+
azureSubscription: $${{ parameters.serviceConnection }}
11+
pwsh: true
12+
azurePowerShellVersion: LatestVersion
13+
ScriptType: "InlineScript"
14+
Inline: |
15+
$intRootMgId = "$(MANAGEMENT_GROUP_ID_PREFIX)$(INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID)$(MANAGEMENT_GROUP_ID_POSTFIX)"
16+
17+
$managementGroups = Get-AzManagementGroup
18+
$intRootMg = $managementGroups | Where-Object { $_.Name -eq $intRootMgId }
19+
20+
$firstDeployment = $true
21+
22+
if($intRootMg -eq $null) {
23+
Write-Warning "Cannot find the $intRootMgId Management Group, so assuming this is the first deployment."
24+
} else {
25+
Write-Host "Found the $intRootMgId Management Group, so assuming this is not the first deployment."
26+
$firstDeployment = $false
27+
}
28+
29+
Write-Host "##vso[task.setvariable variable=FIRST_DEPLOYMENT;]$firstDeployment"

alz/azuredevops/variables.tf

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -45,54 +45,16 @@ variable "subscription_ids" {
4545
default = {}
4646
nullable = false
4747
validation {
48-
condition = length(var.subscription_ids) == 0 || alltrue([for id in values(var.subscription_ids) : can(regex("^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$", id))])
48+
condition = alltrue([for id in values(var.subscription_ids) : can(regex("^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$", id))])
4949
error_message = "All subscription IDs must be valid GUIDs"
5050
}
5151
validation {
52-
condition = length(var.subscription_ids) == 0 || alltrue([for id in keys(var.subscription_ids) : contains(["management", "connectivity", "identity", "security"], id)])
52+
condition = alltrue([for id in keys(var.subscription_ids) : contains(["management", "connectivity", "identity", "security"], id)])
5353
error_message = "The keys of the subscription_ids map must be one of 'management', 'connectivity', 'identity' or 'security'"
5454
}
55-
}
56-
57-
variable "subscription_id_connectivity" {
58-
description = <<-EOT
59-
**(Optional, default: `null`)** **DEPRECATED** (use subscription_ids instead)
60-
61-
The identifier of the Connectivity Subscription.
62-
EOT
63-
type = string
64-
default = null
65-
validation {
66-
condition = var.subscription_id_connectivity == null || can(regex("^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$", var.subscription_id_connectivity))
67-
error_message = "The subscription ID must be a valid GUID"
68-
}
69-
}
70-
71-
variable "subscription_id_identity" {
72-
description = <<-EOT
73-
**(Optional, default: `null`)** **DEPRECATED** (use subscription_ids instead)
74-
75-
The identifier of the Identity Subscription.
76-
EOT
77-
type = string
78-
default = null
79-
validation {
80-
condition = var.subscription_id_identity == null || can(regex("^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$", var.subscription_id_identity))
81-
error_message = "The subscription ID must be a valid GUID"
82-
}
83-
}
84-
85-
variable "subscription_id_management" {
86-
description = <<-EOT
87-
**(Optional, default: `null`)** **DEPRECATED** (use subscription_ids instead)
88-
89-
The identifier of the Management Subscription.
90-
EOT
91-
type = string
92-
default = null
9355
validation {
94-
condition = var.subscription_id_management == null || can(regex("^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$", var.subscription_id_management))
95-
error_message = "The subscription ID must be a valid GUID"
56+
condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") && contains(keys(var.subscription_ids), "identity")
57+
error_message = "You must provide subscription IDs for: 'management', 'connectivity', and 'identity'"
9658
}
9759
}
9860

alz/github/actions/bicep/templates/actions/bicep-deploy/action.yaml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
name: Run Bicep Deploy with Deployment Stack
33
description: Run Bicep Deployment using Azure Deployment Stacks
44
inputs:
5+
name:
6+
description: 'Name'
7+
required: true
58
displayName:
69
description: 'Display Name'
710
required: true
@@ -62,16 +65,13 @@ runs:
6265
exit 0
6366
}
6467
65-
# Generate deployment name without timestamp for consistent deployment stack names
66-
$deploymentPrefix = "alz"
67-
$deploymentNameBase = "$($env:DISPLAY_NAME.Replace(" ", "-"))-$($env:TIME_STAMP)"
68-
68+
# Generate deployment stack name
69+
$deploymentPrefix = $env:MANAGEMENT_GROUP_ID_PREFIX + $env:INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID + $env:MANAGEMENT_GROUP_ID_POSTFIX
70+
$deploymentNameBase = ($env:NAME).Replace(" ", "-")
6971
$deploymentNameMaxLength = 64 - $deploymentPrefix.Length - 1
70-
7172
if ($deploymentNameBase.Length -gt $deploymentNameMaxLength) {
7273
$deploymentNameBase = $deploymentNameBase.Substring(0, $deploymentNameMaxLength)
7374
}
74-
7575
$deploymentName = "$deploymentPrefix-$deploymentNameBase"
7676
7777
$modeText = if ($whatIfEnabled) { "What-If" } else { "Deployment Stack" }
@@ -336,6 +336,7 @@ runs:
336336
}
337337
}
338338
env:
339+
NAME: $${{ inputs.name }}
339340
DISPLAY_NAME: $${{ inputs.displayName }}
340341
TEMPLATE_FILE_PATH: $${{ inputs.templateFilePath }}
341342
TEMPLATE_PARAMETERS_FILE_PATH: $${{ inputs.templateParametersFilePath }}

alz/github/actions/bicep/templates/actions/bicep-first-deployment-check/action.yaml

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,7 @@ runs:
1515
with:
1616
azPSVersion: 'latest'
1717
inlineScript: |
18-
# Read the int-root management group name from the bicepparam file
19-
$intRootParamFile = "templates/core/governance/mgmt-groups/int-root/main.bicepparam"
20-
if (Test-Path $intRootParamFile) {
21-
$paramContent = Get-Content $intRootParamFile -Raw
22-
if ($paramContent -match 'managementGroupName:\s*[''"](\w+)[''"]+') {
23-
$intRootMgId = $matches[1]
24-
Write-Host "Found int-root management group name in param file: $intRootMgId"
25-
} else {
26-
Write-Warning "Could not parse managementGroupName from $intRootParamFile, using default 'alz'"
27-
$intRootMgId = "alz"
28-
}
29-
} else {
30-
Write-Warning "Int-root param file not found at $intRootParamFile, using default 'alz'"
31-
$intRootMgId = "alz"
32-
}
18+
$intRootMgId = $env:MANAGEMENT_GROUP_ID_PREFIX + $env:INTERMEDIATE_ROOT_MANAGEMENT_GROUP_ID + $env:MANAGEMENT_GROUP_ID_POSTFIX
3319
3420
$managementGroups = Get-AzManagementGroup
3521
$intRootMg = $managementGroups | Where-Object { $_.Name -eq $intRootMgId }

alz/github/actions/bicep/templates/workflows/cd-template.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ jobs:
6161
uses: ${project_or_organization_name}/${repository_name_templates}/.github/actions/bicep-deploy@main
6262
if: $${{ inputs.${script_file.name} }}
6363
with:
64+
name: '${script_file.name}'
6465
displayName: '${script_file.displayName}'
6566
templateFilePath: '${script_file.templateFilePath}'
6667
templateParametersFilePath: '${script_file.templateParametersFilePath}'
@@ -118,6 +119,7 @@ jobs:
118119
uses: ${project_or_organization_name}/${repository_name_templates}/.github/actions/bicep-deploy@main
119120
if: $${{ inputs.${script_file.name} }}
120121
with:
122+
name: '${script_file.name}'
121123
displayName: '${script_file.displayName}'
122124
templateFilePath: '${script_file.templateFilePath}'
123125
templateParametersFilePath: '${script_file.templateParametersFilePath}'

alz/github/actions/bicep/templates/workflows/ci-template.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ jobs:
8181
- name: 'What If: ${script_file.displayName}'
8282
uses: ${project_or_organization_name}/${repository_name_templates}/.github/actions/bicep-deploy@main
8383
with:
84+
name: '${script_file.name}'
8485
displayName: '${script_file.displayName}'
8586
templateFilePath: '${script_file.templateFilePath}'
8687
templateParametersFilePath: '${script_file.templateParametersFilePath}'

0 commit comments

Comments
 (0)