Skip to content

Fixing nested replacement #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 27, 2023
Merged
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
6 changes: 0 additions & 6 deletions actions_bootstrap.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ $null = $modulesToInstall.Add(([PSCustomObject]@{
ModuleVersion = '0.12.0'
}))

# Required dependency of the ALZ module itself.
$null = $modulesToInstall.Add(([PSCustomObject]@{
ModuleName = 'Az.Resources'
ModuleVersion = '6.5.2'
}))

'Installing PowerShell Modules'
foreach ($module in $modulesToInstall) {
$installSplat = @{
Expand Down
7 changes: 1 addition & 6 deletions src/ALZ/ALZ.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,7 @@
# ProcessorArchitecture = ''

# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @(
@{
ModuleName = 'Az.Resources'
ModuleVersion = '6.5.2'
}
)
RequiredModules = @()

# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
Expand Down
203 changes: 171 additions & 32 deletions src/ALZ/Assets/alz-bicep-config/v0.14.0-pre.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,19 @@
"Description": "The prefix that will be added to all resources created by this deployment. (e.g. 'alz')",
"Targets": [
{
"Name": "parTopLevelManagementGroupPrefix",
"Name": "parTopLevelManagementGroupPrefix.value",
"Destination": "Parameters"
},
{
"Name": "parCompanyPrefix",
"Name": "parCompanyPrefix.value",
"Destination": "Parameters"
},
{
"Name": "parTargetManagementGroupId",
"Name": "parTargetManagementGroupId.value",
"Destination": "Parameters"
},
{
"Name": "parAssignableScopeManagementGroupId",
"Name": "parAssignableScopeManagementGroupId.value",
"Destination": "Parameters"
},
{
Expand All @@ -162,7 +162,7 @@
"Description": "The suffix that will be added to all resources created by this deployment. (e.g. 'test')",
"Targets": [
{
"Name": "parTopLevelManagementGroupSuffix",
"Name": "parTopLevelManagementGroupSuffix.value",
"Destination": "Parameters"
}
],
Expand All @@ -176,15 +176,23 @@
"Value": "",
"Targets": [
{
"Name": "parLocation",
"Name": "parLocation.value",
"Destination": "Parameters"
},
{
"Name": "parAutomationAccountLocation",
"Name": "parAutomationAccountLocation.value",
"Destination": "Parameters"
},
{
"Name": "parLogAnalyticsWorkspaceLocation",
"Name": "parLogAnalyticsWorkspaceLocation.value",
"Destination": "Parameters"
},
{
"Name": "parPolicyAssignmentParameters.value.ascExportResourceGroupLocation.value",
"Destination": "Parameters"
},
{
"Name": "parVirtualWanHubs.value.[0].parHubLocation",
"Destination": "Parameters"
},
{
Expand All @@ -194,32 +202,83 @@
],
"AllowedValues": {
"Display": false,
"Description": "Getting Azure deployment locations.",
"Type": "PSScript",
"Script": "Get-AzLocation | Where-Object {$_.RegionType -eq 'Physical'} | Sort-Object Location | Select-Object -ExpandProperty Location",
"Values": []
"Values": [
"australiacentral",
"australiacentral2",
"australiaeast",
"australiasoutheast",
"brazilsouth",
"brazilsoutheast",
"canadacentral",
"canadaeast",
"centralindia",
"centralus",
"centraluseuap",
"eastasia",
"eastus",
"eastus2",
"eastus2euap",
"eastusstg",
"francecentral",
"francesouth",
"germanynorth",
"germanywestcentral",
"japaneast",
"japanwest",
"jioindiacentral",
"jioindiawest",
"koreacentral",
"koreasouth",
"northcentralus",
"northeurope",
"norwayeast",
"norwaywest",
"qatarcentral",
"southafricanorth",
"southafricawest",
"southcentralus",
"southeastasia",
"southindia",
"swedencentral",
"switzerlandnorth",
"switzerlandwest",
"uaecentral",
"uaenorth",
"uksouth",
"ukwest",
"westcentralus",
"westeurope",
"westindia",
"westus",
"westus2",
"westus3"
]
}
},
"Environment": {
"Type": "UserInput",
"Description": "The Type of environment that will be created. (e.g. 'dev', 'test', 'qa', 'staging', 'prod')",
"Description": "The Type of environment that will be created. (e.g. 'live', 'canary')",
"Targets": [
{
"Name": "parEnvironment",
"Name": "parEnvironment.value",
"Destination": "Parameters"
},
{
"Name": "parTags.value.Environment",
"Destination": "Parameters"
}
],
"Value": "",
"DefaultValue": "prod",
"DefaultValue": "live",
"Valid": "^[a-zA-Z0-9]{2,10}$"
},
"IdentitySubscriptionId": {
"Type": "UserInput",
"Description": "The identifier of the Identity Subscription. (e.g '00000000-0000-0000-0000-000000000000')",
"Valid": "^( {){0,1}[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}(}){0,1}$",
"Targets": [
{
"Name": "IdentitySubscriptionId",
{
"Name": "IDENTITY_SUBSCRIPTION_ID",
"Destination": "Environment"
}
],
Expand All @@ -230,10 +289,6 @@
"Description": "The identifier of the Connectivity Subscription. (e.g '00000000-0000-0000-0000-000000000000')",
"Valid": "^( {){0,1}[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}(}){0,1}$",
"Targets": [
{
"Name": "ConnectivitySubscriptionId",
"Destination": "Environment"
},
{
"Name": "CONNECTIVITY_SUBSCRIPTION_ID",
"Destination": "Environment"
Expand All @@ -247,30 +302,114 @@
"Valid": "^( {){0,1}[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}(}){0,1}$",
"Targets": [
{
"Name": "ManagementSubscriptionId",
"Name": "MANAGEMENT_SUBSCRIPTION_ID",
"Destination": "Environment"
}
],
"Value": ""
},
"BillingAccountId": {
"Type": "UserInput",
"Description": "The identifier of the Billing Account. (e.g 00000000-0000-0000-0000-000000000000)",
"Valid": "^( {){0,1}[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}(}){0,1}$",
"Value": ""
},
"EnrollmentAccountId": {
"SecurityContact": {
"Type": "UserInput",
"Description": "The identifier of the Enrollment Account. (e.g 00000000-0000-0000-0000-000000000000)",
"Valid": "^( {){0,1}[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}(}){0,1}$",
"Description": "The email address of the contact for security issues. (e.g. security@contactme.com)",
"Valid": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"Targets": [
{
"Name":"parPolicyAssignmentParameters.value.emailSecurityContact.value",
"Destination": "Parameters"
}
],
"Value": ""
},
"LogAnalyticsResourceId": {
"Type": "Computed",
"Value": "/subscriptions/{%ManagementSubscriptionId%}/resourcegroups/alz-logging/providers/microsoft.operationalinsights/workspaces/alz-log-analytics",
"Targets": [
{
"Name": "parLogAnalyticsWorkspaceResourceId",
"Name": "parLogAnalyticsWorkspaceResourceId.value",
"Destination": "Parameters"
}
]
},
"AllSubscriptionIds": {
"Type": "Computed",
"Value": [
"{%ManagementSubscriptionId%}",
"{%ConnectivitySubscriptionId%}",
"{%IdentitySubscriptionId%}"
],
"Targets": [
{
"Name": "parSubscriptionIds.value",
"Destination": "Parameters"
}
]
},
"VirtualIdToLink": {
"Type": "Computed",
"Value": "",
"Targets": [
{
"Name": "parVirtualNetworkIdToLink.value",
"Destination": "Parameters"
}
]
},
"VirtualWanName":{
"Type": "Computed",
"Value": "alz-vwan-{%Location%}",
"Targets": [
{
"Name": "parVirtualWanName.value",
"Destination": "Parameters"
}
]
},
"FirewallPoliciesName":{
"Type": "Computed",
"Value": "alz-azfwpolicy-{%Location%}",
"Targets": [
{
"Name": "parAzFirewallPoliciesName.value",
"Destination": "Parameters"
}
]
},
"AK8sPrivateLink": {
"Type": "Computed",
"Value": "privatelink.{%Location%}.azmk8s.io",
"Targets": [
{
"Name": "parPrivateDnsZones.value.[0]",
"Destination": "Parameters"
}
]
},
"BatchPrivateLink": {
"Type": "Computed",
"Value": "privatelink.{%Location%}.batch.azure.com",
"Targets": [
{
"Name": "parPrivateDnsZones.value.[1]",
"Destination": "Parameters"
}
]
},
"KustoPrivateLink": {
"Type": "Computed",
"Value": "privatelink.{%Location%}.kusto.windows.net",
"Targets": [
{
"Name": "parPrivateDnsZones.value.[2]",
"Destination": "Parameters"
}
]
},
"BackupPrivateLink": {
"Type": "Computed",
"Value": "privatelink.{%Location%}.backup.windowsazure.com",
"Targets": [
{
"Name": "parPrivateDnsZones.value.[3]",
"Destination": "Parameters"
}
]
Expand Down
55 changes: 50 additions & 5 deletions src/ALZ/Private/Edit-ALZConfigurationFilesInPlace.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,70 @@ function Edit-ALZConfigurationFilesInPlace {
[object] $configuration
)

$locations = @("orchestration", "config", "customization")
$locations = @("config")
$files = @()

foreach ($location in $locations) {
$bicepModules = Join-Path $alzEnvironmentDestination $location
$files += @(Get-ChildItem -Path $bicepModules -Recurse -Filter *.parameters.json)
$files += @(Get-ChildItem -Path $bicepModules -Recurse -Filter *.parameters.*.json)
}

foreach ($file in $files) {
$bicepConfiguration = Get-Content $file.FullName | ConvertFrom-Json -AsHashtable
$modified = $false

foreach ($configKey in $configuration.PsObject.Properties) {
foreach ($target in $configKey.Value.Targets) {
if ($target.Destination -eq "Parameters" -and $null -ne $bicepConfiguration.parameters[$target.Name]) {

# Find the appropriate item which will be changed in the Bicep file.
# Remove array '[' ']' characters so we can use the index value direct.
$propertyNames = $target.Name -replace "\[|\]","" -split "\."
$bicepConfigNode = $bicepConfiguration.parameters
$index = 0

# Keep navigating into properties which the configuration specifies until we reach the bottom most object,
# e.g. not a value type - but the object reference so the value is persisted.
do {
if ($bicepConfigNode -is [array]) {
# If this is an array - use the property as an array index...
if ($propertyNames[$index] -match "[0-9]+" -eq $false) {
throw "Configuration specifies an array, but the index value '${$propertyNames[$index]}' is not a number"
}

$bicepConfigNode = $bicepConfigNode[$propertyNames[$index]]

} elseif ($bicepConfigNode.ContainsKey($propertyNames[$index]) -eq $true) {
# We found the item, keep indexing into the object.
$bicepConfigNode = $bicepConfigNode[$propertyNames[$index]]
} else {
# This property doesn't exist at this level in the hierarchy,
# this isn't the property we're looking for, stop looking.
$bicepConfigNode = $null
}

++$index

} while (($null -ne $bicepConfigNode) -and ($index -lt $propertyNames.Length - 1))

# If we're here, we've got the object at the bottom of the hierarchy - and we can modify values on it.
if ($target.Destination -eq "Parameters" -and $null -ne $bicepConfigNode) {
$leafPropertyName = $propertyNames[-1]

if ($configKey.Value.Type -eq "Computed") {
$bicepConfiguration.parameters[$target.Name].value = Format-TokenizedConfigurationString $configKey.Value.Value $configuration
# If the value type is computed we replace the value with another which already exists in the configuration hierarchy.
if ($configKey.Value.Value -is [array]) {
$formattedValues = @()
foreach($formatString in $configKey.Value.Value) {
$formattedValues += Format-TokenizedConfigurationString -tokenizedString $formatString -configuration $configuration
}
$bicepConfigNode[$leafPropertyName] = $formattedValues
} else {
$bicepConfigNode[$leafPropertyName] = Format-TokenizedConfigurationString -tokenizedString $configKey.Value.Value -configuration $configuration
}
} else {
$bicepConfiguration.parameters[$target.Name].value = $configKey.Value.Value
$bicepConfigNode[$leafPropertyName] = $configKey.Value.Value
}

$modified = $true
}
}
Expand Down
1 change: 1 addition & 0 deletions src/ALZ/Private/Format-TokenizedConfigurationString.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
function Format-TokenizedConfigurationString {
param(
[AllowEmptyString()]
[Parameter(Mandatory = $true)]
[string] $tokenizedString,

Expand Down
Loading