From f20459e1682ae02e8b59d9b46f60dc99fd182dde Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Sat, 6 Dec 2025 11:19:07 +0000 Subject: [PATCH 1/6] feat: improve bicep templating --- .../Convert-BicepConfigToInputConfig.ps1 | 2 ++ .../Convert-HCLVariablesToInputConfig.ps1 | 7 ++++ .../Convert-ParametersToInputConfig.ps1 | 10 +++--- .../Private/Config-Helpers/Get-ALZConfig.ps1 | 5 +-- .../Private/Config-Helpers/Write-JsonFile.ps1 | 27 ++++++++++++--- .../New-Bootstrap.ps1 | 34 +++++++++++++------ src/ALZ/Public/Deploy-Accelerator.ps1 | 25 ++++++++------ 7 files changed, 78 insertions(+), 32 deletions(-) diff --git a/src/ALZ/Private/Config-Helpers/Convert-BicepConfigToInputConfig.ps1 b/src/ALZ/Private/Config-Helpers/Convert-BicepConfigToInputConfig.ps1 index b4a8222..2d63279 100644 --- a/src/ALZ/Private/Config-Helpers/Convert-BicepConfigToInputConfig.ps1 +++ b/src/ALZ/Private/Config-Helpers/Convert-BicepConfigToInputConfig.ps1 @@ -44,6 +44,8 @@ function Convert-BicepConfigToInputConfig { $configItem | Add-Member -NotePropertyName "targets" -NotePropertyValue $variable.Value.targets } + $configItem | Add-Member -NotePropertyName "Sensitive" -NotePropertyValue $false + $configItem | Add-Member -NotePropertyName "Description" -NotePropertyValue $description $configItems | Add-Member -NotePropertyName $variable.Name -NotePropertyValue $configItem } diff --git a/src/ALZ/Private/Config-Helpers/Convert-HCLVariablesToInputConfig.ps1 b/src/ALZ/Private/Config-Helpers/Convert-HCLVariablesToInputConfig.ps1 index 87500d9..906545d 100644 --- a/src/ALZ/Private/Config-Helpers/Convert-HCLVariablesToInputConfig.ps1 +++ b/src/ALZ/Private/Config-Helpers/Convert-HCLVariablesToInputConfig.ps1 @@ -41,6 +41,13 @@ function Convert-HCLVariablesToInputConfig { $configItem | Add-Member -NotePropertyName "Description" -NotePropertyValue $description + $sensitive = $false + if ($variable.Value[0].PSObject.Properties.Name -contains "sensitive" -and $variable.Value[0].sensitive -eq $true) { + $sensitive = $true + Write-Verbose "Marking variable $($variable.Name) as sensitive..." + } + $configItem | Add-Member -NotePropertyName "Sensitive" -NotePropertyValue $sensitive + Write-Verbose "Adding variable $($variable.Name) to the configuration..." $configItems | Add-Member -NotePropertyName $variable.Name -NotePropertyValue $configItem } diff --git a/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 b/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 index 3f65b04..fec65fe 100644 --- a/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 +++ b/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 @@ -15,8 +15,9 @@ function Convert-ParametersToInputConfig { Write-Verbose "Alias $parameterAlias exists in input config, renaming..." $configItem = $inputConfig.PSObject.Properties | Where-Object { $_.Name -eq $parameterAlias } $inputConfig | Add-Member -NotePropertyName $parameterKey -NotePropertyValue @{ - Value = $configItem.Value.Value - Source = $configItem.Value.Source + Value = $configItem.Value.Value + Source = $configItem.Value.Source + Sensitive = $configItem.Value.Sensitive } $inputConfig.PSObject.Properties.Remove($configItem.Name) continue @@ -38,8 +39,9 @@ function Convert-ParametersToInputConfig { } Write-Verbose "Adding parameter $parameterKey with value $variableValue" $inputConfig | Add-Member -NotePropertyName $parameterKey -NotePropertyValue @{ - Value = $variableValue - Source = "parameter" + Value = $variableValue + Source = "parameter" + Sensitive = $false } } } diff --git a/src/ALZ/Private/Config-Helpers/Get-ALZConfig.ps1 b/src/ALZ/Private/Config-Helpers/Get-ALZConfig.ps1 index 90b1217..f585526 100644 --- a/src/ALZ/Private/Config-Helpers/Get-ALZConfig.ps1 +++ b/src/ALZ/Private/Config-Helpers/Get-ALZConfig.ps1 @@ -57,8 +57,9 @@ function Get-ALZConfig { foreach ($property in $config.PSObject.Properties) { $inputConfig | Add-Member -NotePropertyName $property.Name -NotePropertyValue @{ - Value = $property.Value - Source = $extension + Value = $property.Value + Source = $extension + Sensitive = $false } } diff --git a/src/ALZ/Private/Config-Helpers/Write-JsonFile.ps1 b/src/ALZ/Private/Config-Helpers/Write-JsonFile.ps1 index e3910b4..08ce643 100644 --- a/src/ALZ/Private/Config-Helpers/Write-JsonFile.ps1 +++ b/src/ALZ/Private/Config-Helpers/Write-JsonFile.ps1 @@ -5,7 +5,10 @@ function Write-JsonFile { [string] $jsonFilePath, [Parameter(Mandatory = $false)] - [PSObject] $configuration + [PSObject[]] $configurations, + + [Parameter(Mandatory = $false)] + [switch] $all ) if ($PSCmdlet.ShouldProcess("Download Terraform Tools", "modify")) { @@ -16,10 +19,24 @@ function Write-JsonFile { $environmentVariables = [ordered]@{} - foreach ($configKey in $configuration.PsObject.Properties | Sort-Object Name) { - foreach ($target in $configKey.Value.Targets) { - if ($target.Destination -eq "Environment") { - $environmentVariables.$($target.Name) = $configKey.Value.Value + foreach ($configuration in $configurations) { + Write-Verbose "Processing configuration for JSON output to $($jsonFilePath)" + foreach ($configKey in $configuration.PsObject.Properties | Sort-Object Name) { + Write-Verbose "Processing configuration key $($configKey.Name) for $($jsonFilePath)" + Write-Verbose "Configuration key value: $(ConvertTo-Json $configKey.Value -Depth 100)" + if($configKey.Value.Sensitive) { + Write-Verbose "Obfuscating sensitive configuration $($configKey.Name) from JSON output" + $environmentVariables.$($configKey.Name) = "" + continue + } + if($all) { + $environmentVariables.$($configKey.Name) = $configKey.Value.Value + continue + } + foreach ($target in $configKey.Value.Targets) { + if ($target.Destination -eq "Environment") { + $environmentVariables.$($target.Name) = $configKey.Value.Value + } } } } diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 index 8107aa2..a06b119 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 @@ -125,8 +125,9 @@ function New-Bootstrap { # Add the root module folder to bootstrap input config $inputConfig | Add-Member -NotePropertyName "root_module_folder_relative_path" -NotePropertyValue @{ - Value = $starterRootModuleFolder - Source = "calculated" + Value = $starterRootModuleFolder + Source = "calculated" + Sensitive = $false } # Set the starter root module folder full path @@ -146,6 +147,8 @@ function New-Bootstrap { $bootstrapParameters = Convert-HCLVariablesToInputConfig -targetVariableFile $terraformFile.FullName -hclParserToolPath $hclParserToolPath -appendToObject $bootstrapParameters } + Write-Verbose "Bootstrap Parameters before setting config: $(ConvertTo-Json $bootstrapParameters -Depth 100)" + # Getting the configuration for the starter module user input $starterParameters = [PSCustomObject]@{} @@ -165,19 +168,22 @@ function New-Bootstrap { # Set computed inputs $inputConfig | Add-Member -NotePropertyName "module_folder_path" -NotePropertyValue @{ - Value = $starterModulePath - Source = "calculated" + Value = $starterModulePath + Source = "calculated" + Sensitive = $false } $inputConfig | Add-Member -NotePropertyName "availability_zones_bootstrap" -NotePropertyValue @{ - Value = @(Get-AvailabilityZonesSupport -region $inputConfig.bootstrap_location.Value -zonesSupport $zonesSupport) - Source = "calculated" + Value = @(Get-AvailabilityZonesSupport -region $inputConfig.bootstrap_location.Value -zonesSupport $zonesSupport) + Source = "calculated" + Sensitive = $false } if ($inputConfig.PSObject.Properties.Name -contains "starter_location" -and $inputConfig.PSObject.Properties.Name -notcontains "starter_locations") { Write-Verbose "Converting starter_location $($inputConfig.starter_location.Value) to starter_locations..." $inputConfig | Add-Member -NotePropertyName "starter_locations" -NotePropertyValue @{ - Value = @($inputConfig.starter_location.Value) - Source = "calculated" + Value = @($inputConfig.starter_location.Value) + Source = "calculated" + Sensitive = $false } } @@ -187,8 +193,9 @@ function New-Bootstrap { $availabilityZonesStarter += , @(Get-AvailabilityZonesSupport -region $region -zonesSupport $zonesSupport) } $inputConfig | Add-Member -NotePropertyName "availability_zones_starter" -NotePropertyValue @{ - Value = $availabilityZonesStarter - Source = "calculated" + Value = $availabilityZonesStarter + Source = "calculated" + Sensitive = $false } } @@ -200,6 +207,8 @@ function New-Bootstrap { -configurationParameters $bootstrapParameters ` -inputConfig $inputConfig + Write-Verbose "Final Bootstrap Parameters: $(ConvertTo-Json $bootstrapConfiguration -Depth 100)" + # Getting the input for the starter module Write-Verbose "Setting the configuration for the starter module..." $starterConfiguration = Set-Config ` @@ -207,13 +216,14 @@ function New-Bootstrap { -inputConfig $inputConfig ` -copyEnvVarToConfig - Write-Verbose "Final Starter Parameters: $(ConvertTo-Json $starterParameters -Depth 100)" + Write-Verbose "Final Starter Parameters: $(ConvertTo-Json $starterConfiguration -Depth 100)" # Creating the tfvars files for the bootstrap and starter module $tfVarsFileName = "terraform.tfvars.json" $bootstrapTfvarsPath = Join-Path -Path $bootstrapModulePath -ChildPath $tfVarsFileName $starterTfvarsPath = Join-Path -Path $starterRootModuleFolderPath -ChildPath "terraform.tfvars.json" $starterBicepVarsPath = Join-Path -Path $starterModulePath -ChildPath "parameters.json" + $starterBicepAllVarsPath = Join-Path -Path $starterModulePath -ChildPath "parameters.all.json" # Write the tfvars file for the bootstrap and starter module Write-TfvarsJsonFile -tfvarsFilePath $bootstrapTfvarsPath -configuration $bootstrapConfiguration @@ -270,10 +280,12 @@ function New-Bootstrap { Set-ComputedConfiguration -configuration $starterConfiguration Edit-ALZConfigurationFilesInPlace -alzEnvironmentDestination $starterModulePath -configuration $starterConfiguration Write-JsonFile -jsonFilePath $starterBicepVarsPath -configuration $starterConfiguration + Write-JsonFile -jsonFilePath $starterBicepAllVarsPath -configuration @($inputConfig, $starterConfiguration, $bootstrapConfiguration) -all # Remove unrequired files $foldersOrFilesToRetain = $starterConfig.starter_modules.Value.$($inputConfig.starter_module_name.Value).folders_or_files_to_retain $foldersOrFilesToRetain += "parameters.json" + $foldersOrFilesToRetain += "parameters.all.json" $foldersOrFilesToRetain += "config" $foldersOrFilesToRetain += ".config" diff --git a/src/ALZ/Public/Deploy-Accelerator.ps1 b/src/ALZ/Public/Deploy-Accelerator.ps1 index da457e2..78b1c96 100644 --- a/src/ALZ/Public/Deploy-Accelerator.ps1 +++ b/src/ALZ/Public/Deploy-Accelerator.ps1 @@ -354,24 +354,29 @@ function Deploy-Accelerator { # Set computed interface inputs $inputConfig | Add-Member -MemberType NoteProperty -Name "bicep_config_file_path" -Value @{ - Value = $starterConfigFilePath - Source = "calculated" + Value = $starterConfigFilePath + Source = "calculated" + Sensitive = $false } $inputConfig | Add-Member -MemberType NoteProperty -Name "on_demand_folder_repository" -Value @{ - Value = $starterModuleUrl - Source = "calculated" + Value = $starterModuleUrl + Source = "calculated" + Sensitive = $false } $inputConfig | Add-Member -MemberType NoteProperty -Name "on_demand_folder_artifact_name" -Value @{ - Value = $starterReleaseArtifactName - Source = "calculated" + Value = $starterReleaseArtifactName + Source = "calculated" + Sensitive = $false } $inputConfig | Add-Member -MemberType NoteProperty -Name "release_version" -Value @{ - Value = ($starterReleaseTag -eq "local" ? $inputConfig.starter_module_version.Value : $starterReleaseTag) - Source = "calculated" + Value = ($starterReleaseTag -eq "local" ? $inputConfig.starter_module_version.Value : $starterReleaseTag) + Source = "calculated" + Sensitive = $false } $inputConfig | Add-Member -MemberType NoteProperty -Name "time_stamp" -Value @{ - Value = (Get-Date).ToString("yyyy-MM-dd-HH-mm-ss") - Source = "calculated" + Value = (Get-Date).ToString("yyyy-MM-dd-HH-mm-ss") + Source = "calculated" + Sensitive = $false } # Run the bootstrap From 125a64c1cd0270b965816b17eec639d659d651a2 Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Sat, 6 Dec 2025 12:45:22 +0000 Subject: [PATCH 2/6] fix file name --- .../Deploy-Accelerator-Helpers/New-Bootstrap.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 index a06b119..c376979 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 @@ -222,8 +222,10 @@ function New-Bootstrap { $tfVarsFileName = "terraform.tfvars.json" $bootstrapTfvarsPath = Join-Path -Path $bootstrapModulePath -ChildPath $tfVarsFileName $starterTfvarsPath = Join-Path -Path $starterRootModuleFolderPath -ChildPath "terraform.tfvars.json" - $starterBicepVarsPath = Join-Path -Path $starterModulePath -ChildPath "parameters.json" - $starterBicepAllVarsPath = Join-Path -Path $starterModulePath -ChildPath "parameters.all.json" + $starterBicepVarsFileName = "parameters.json" + $starterBicepAllVarsFileName = "template-parameters.json" + $starterBicepVarsPath = Join-Path -Path $starterModulePath -ChildPath $starterBicepVarsFileName + $starterBicepAllVarsPath = Join-Path -Path $starterModulePath -ChildPath $starterBicepAllVarsFileName # Write the tfvars file for the bootstrap and starter module Write-TfvarsJsonFile -tfvarsFilePath $bootstrapTfvarsPath -configuration $bootstrapConfiguration @@ -284,8 +286,8 @@ function New-Bootstrap { # Remove unrequired files $foldersOrFilesToRetain = $starterConfig.starter_modules.Value.$($inputConfig.starter_module_name.Value).folders_or_files_to_retain - $foldersOrFilesToRetain += "parameters.json" - $foldersOrFilesToRetain += "parameters.all.json" + $foldersOrFilesToRetain += $starterBicepVarsFileName + $foldersOrFilesToRetain += $starterBicepAllVarsFileName $foldersOrFilesToRetain += "config" $foldersOrFilesToRetain += ".config" From c10483a796790bd88d862f894b03a622f8e4410c Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Thu, 11 Dec 2025 16:58:30 +0000 Subject: [PATCH 3/6] various fixes and improvements --- src/ALZ/ALZ.psd1 | 4 +- .../New-Bootstrap.ps1 | 23 +-- src/ALZ/Public/Deploy-Accelerator.ps1 | 37 ++++- .../Public/New-AcceleratorFolderStructure.ps1 | 148 ++++++++++++++++++ 4 files changed, 189 insertions(+), 23 deletions(-) create mode 100644 src/ALZ/Public/New-AcceleratorFolderStructure.ps1 diff --git a/src/ALZ/ALZ.psd1 b/src/ALZ/ALZ.psd1 index 099c2d3..4f1499d 100644 --- a/src/ALZ/ALZ.psd1 +++ b/src/ALZ/ALZ.psd1 @@ -40,6 +40,7 @@ Included Cmdlets: - Deploy-Accelerator: Deploys the Azure Landing Zone accelerator to your Azure subscription. - Grant-SubscriptionCreatorRole: Grants the Subscription Creator role to a specified user or service principal. - Remove-PlatformLandingZone: Removes the deployed Azure Landing Zone from your Azure subscription +- New-AcceleratorFolderStructure: Creates a new folder structure for the Azure Landing Zone accelerator with necessary configuration files. '@ CompatiblePSEditions = 'Core' @@ -85,7 +86,8 @@ Included Cmdlets: 'Test-AcceleratorRequirement', 'Deploy-Accelerator', 'Grant-SubscriptionCreatorRole', - 'Remove-PlatformLandingZone' + 'Remove-PlatformLandingZone', + 'New-AcceleratorFolderStructure' ) # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 index c376979..c324614 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 @@ -34,9 +34,6 @@ function New-Bootstrap { [Parameter(Mandatory = $false)] [switch] $destroy, - [Parameter(Mandatory = $false)] - [PSCustomObject] $zonesSupport = $null, - [Parameter(Mandatory = $false, HelpMessage = "An extra level of logging that is turned off by default for easier debugging.")] [switch] $writeVerboseLogs, @@ -172,22 +169,14 @@ function New-Bootstrap { Source = "calculated" Sensitive = $false } - $inputConfig | Add-Member -NotePropertyName "availability_zones_bootstrap" -NotePropertyValue @{ - Value = @(Get-AvailabilityZonesSupport -region $inputConfig.bootstrap_location.Value -zonesSupport $zonesSupport) - Source = "calculated" - Sensitive = $false - } - if ($inputConfig.PSObject.Properties.Name -contains "starter_location" -and $inputConfig.PSObject.Properties.Name -notcontains "starter_locations") { - Write-Verbose "Converting starter_location $($inputConfig.starter_location.Value) to starter_locations..." - $inputConfig | Add-Member -NotePropertyName "starter_locations" -NotePropertyValue @{ - Value = @($inputConfig.starter_location.Value) - Source = "calculated" - Sensitive = $false - } - } + if ($iac -eq "bicep-classic" -and $inputConfig.PSObject.Properties.Name -contains "starter_locations") { + # Get the supported regions and availability zones + Write-Verbose "Getting Supported Regions and Availability Zones with Terraform" + $regionsAndZones = Get-AzureRegionData -toolsPath $toolsPath + Write-Verbose "Supported Regions: $($regionsAndZones.supportedRegions)" + $zonesSupport = $regionsAndZones.zonesSupport - if ($inputConfig.PSObject.Properties.Name -contains "starter_locations") { $availabilityZonesStarter = @() foreach ($region in $inputConfig.starter_locations.Value) { $availabilityZonesStarter += , @(Get-AvailabilityZonesSupport -region $region -zonesSupport $zonesSupport) diff --git a/src/ALZ/Public/Deploy-Accelerator.ps1 b/src/ALZ/Public/Deploy-Accelerator.ps1 index 78b1c96..6a05291 100644 --- a/src/ALZ/Public/Deploy-Accelerator.ps1 +++ b/src/ALZ/Public/Deploy-Accelerator.ps1 @@ -211,6 +211,12 @@ function Deploy-Accelerator { if ($PSCmdlet.ShouldProcess("Accelerator setup", "modify")) { + # Normalize output folder path + if($output_folder_path.StartsWith("~/" )) { + $output_folder_path = Join-Path $HOME $output_folder_path.Replace("~/", "") + } + $output_folder_path = (Resolve-Path -Path $output_folder_path).Path + # Check and install tools needed $toolsPath = Join-Path -Path $output_folder_path -ChildPath ".tools" if ($skipInternetChecks) { @@ -235,6 +241,11 @@ function Deploy-Accelerator { # Get the input config from yaml and json files foreach ($inputConfigFilePath in $inputConfigFilePaths) { + if($inputConfigFilePath.StartsWith("~/" )) { + $inputConfigFilePath = Join-Path $HOME $inputConfigFilePath.Replace("~/", "") + } + $inputConfigFilePath = (Resolve-Path -Path $inputConfigFilePath).Path + Write-Verbose "Loading input config from file: $inputConfigFilePath" $inputConfig = Get-ALZConfig -configFilePath $inputConfigFilePath -inputConfig $inputConfig -hclParserToolPath $hclParserToolPath } @@ -259,6 +270,8 @@ function Deploy-Accelerator { } $inputConfig = Convert-ParametersToInputConfig -inputConfig $inputConfig -parameters $parametersWithValues + Write-Verbose "Initial Input config: $(ConvertTo-Json $inputConfig -Depth 100)" + # Throw if IAC type is not specified if (!$inputConfig.iac_type.Value) { Write-InformationColored "No Infrastructure as Code type has been specified. Please supply the IAC type you wish to deploy..." -ForegroundColor Red -InformationAction Continue @@ -269,8 +282,6 @@ function Deploy-Accelerator { Write-InformationColored "Although you have selected Bicep, the Accelerator leverages the Terraform tool to bootstrap your Version Control System and Azure. This will not impact your choice of Bicep post this initial bootstrap. Please refer to our documentation for further details..." -ForegroundColor Yellow -InformationAction Continue } - Write-Verbose "Initial Input config: $(ConvertTo-Json $inputConfig -Depth 100)" - # Download the bootstrap modules $bootstrapReleaseTag = "" $bootstrapPath = "" @@ -278,6 +289,10 @@ function Deploy-Accelerator { Write-InformationColored "Checking and Downloading the bootstrap module..." -ForegroundColor Green -NewLineBefore -InformationAction Continue + if($inputConfig.bootstrap_module_override_folder_path.Value.StartsWith("~/" )) { + $inputConfig.bootstrap_module_override_folder_path.Value = Join-Path $HOME $inputConfig.bootstrap_module_override_folder_path.Value.Replace("~/", "") + } + $versionAndPath = New-ModuleSetup ` -targetDirectory $inputConfig.output_folder_path.Value ` -targetFolder $bootstrapTargetFolder ` @@ -304,7 +319,6 @@ function Deploy-Accelerator { $starterConfigFilePath = "" $bootstrapDetails = $null - $zonesSupport = $null # Request the bootstrap type if not already specified if(!$inputConfig.bootstrap_module_name.Value) { @@ -327,7 +341,6 @@ function Deploy-Accelerator { $starterModuleSourceFolder = $bootstrapAndStarterConfig.starterModuleSourceFolder $starterReleaseArtifactName = $bootstrapAndStarterConfig.starterReleaseArtifactName $starterConfigFilePath = $bootstrapAndStarterConfig.starterConfigFilePath - $zonesSupport = $bootstrapAndStarterConfig.zonesSupport # Download the starter modules $starterReleaseTag = "" @@ -336,6 +349,10 @@ function Deploy-Accelerator { if ($hasStarterModule) { Write-InformationColored "Checking and downloading the starter module..." -ForegroundColor Green -NewLineBefore -InformationAction Continue + if($inputConfig.starter_module_override_folder_path.Value.StartsWith("~/" )) { + $inputConfig.starter_module_override_folder_path.Value = Join-Path $HOME $inputConfig.starter_module_override_folder_path.Value.Replace("~/", "") + } + $versionAndPath = New-ModuleSetup ` -targetDirectory $inputConfig.output_folder_path.Value ` -targetFolder $starterModuleTargetFolder ` @@ -383,6 +400,17 @@ function Deploy-Accelerator { $bootstrapTargetPath = Join-Path $inputConfig.output_folder_path.Value $bootstrapTargetFolder $starterTargetPath = Join-Path $inputConfig.output_folder_path.Value $starterFolder + # Normalize starter additional files input + $starterAdditionalFiles = @() + foreach ($additionalFile in $inputConfig.starter_additional_files.Value) { + if($additionalFile.StartsWith("~/" )) { + $additionalFile = Join-Path $HOME $additionalFile.Replace("~/", "") + } + $additionalFile = (Resolve-Path -Path $additionalFile).Path + $starterAdditionalFiles += $additionalFile + } + $inputConfig.starter_additional_files.Value = $starterAdditionalFiles + New-Bootstrap ` -iac $inputConfig.iac_type.Value ` -bootstrapDetails $bootstrapDetails ` @@ -395,7 +423,6 @@ function Deploy-Accelerator { -starterConfig $starterConfig ` -autoApprove:$inputConfig.auto_approve.Value ` -destroy:$inputConfig.destroy.Value ` - -zonesSupport $zonesSupport ` -writeVerboseLogs:$inputConfig.write_verbose_logs.Value ` -hclParserToolPath $hclParserToolPath ` -convertTfvarsToJson:$inputConfig.convert_tfvars_to_json.Value ` diff --git a/src/ALZ/Public/New-AcceleratorFolderStructure.ps1 b/src/ALZ/Public/New-AcceleratorFolderStructure.ps1 new file mode 100644 index 0000000..695bca6 --- /dev/null +++ b/src/ALZ/Public/New-AcceleratorFolderStructure.ps1 @@ -0,0 +1,148 @@ +function New-AcceleratorFolderStructure { + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [Parameter( + Mandatory = $false, + HelpMessage = "[REQUIRED] The infrastructure as code type for the accelerator. Options are 'terraform', 'bicep' or 'bicep-classic'" + )] + [string] $iacType = "terraform", + [Parameter( + Mandatory = $false, + HelpMessage = "[REQUIRED] The version of the accelerator to use for the bootstrap and starter configuration files" + )] + [string] $versionControl = "github", + [Parameter( + Mandatory = $false, + HelpMessage = "[OPTIONAL] The scenario number to use for the starter configuration files" + )] + [int] $scenarioNumber = 1, + [Parameter( + Mandatory = $false, + HelpMessage = "[REQUIRED] The target folder to create the accelerator bootstrap and platform landing zone configuration files in" + )] + [string] $targetFolderPath = "~/accelerator", + [Parameter( + Mandatory = $false, + HelpMessage = "[OPTIONAL] Forece recreate of the target folder if it already exists" + )] + [switch] $force + ) + + if ($PSCmdlet.ShouldProcess("Accelerator folder create", "modify")) { + + $currentPath = Get-Location + + # Normalize target folder path + if($targetFolderPath.StartsWith("~/" )) { + $targetFolderPath = Join-Path $HOME $targetFolderPath.Replace("~/", "") + } + if(Test-Path -Path $targetFolderPath) { + if($force.IsPresent) { + Write-Host "Force flag is set, removing existing target folder at $targetFolderPath" + Remove-Item -Recurse -Force -Path $targetFolderPath | Write-Verbose | Out-Null + } else { + throw "Target folder $targetFolderPath already exists. Please specify a different folder path or remove the existing folder." + } + } + Write-Host "Creating target folder at $targetFolderPath" + New-Item -ItemType "directory" -Path $targetFolderPath -Force | Write-Verbose | Out-Null + $targetFolderPath = (Resolve-Path -Path $targetFolderPath).Path + + # Create target folder structure + $outputFolder = Join-Path $targetFolderPath "output" + Write-Host "Creating output folder at $outputFolder" + New-Item -ItemType "directory" $outputFolder -Force | Write-Verbose | Out-Null + + # Create temp folder + $tempFolderPath = Join-Path $targetFolderPath "temp" + Write-Host "Creating temp folder at $tempFolderPath" + New-Item -ItemType "directory" $tempFolderPath -Force | Write-Verbose | Out-Null + + # Map the repo + $repos = @{ + "terraform" = @{ + repoName = "alz-terraform-accelerator" + folderToClone = "templates/platform_landing_zone" + libraryFolderPath = "lib" + exampleFolderPath = "examples" + bootstrapExampleFolderPath = "bootstrap" + hasScenarios = $true + hasLibrary = $true + } + + "bicep" = @{ + repoName = "alz-bicep-accelerator" + folderToClone = "" + libraryFolderPath = "" + exampleFolderPath = "examples" + bootstrapExampleFolderPath = "bootstrap" + hasScenarios = $false + hasLibrary = $false + platformLandingZoneFilePath = "platform-landing-zone.yaml" + } + + "bicep-classic" = @{ + repoName = "alz-bicep" + folderToClone = "accelerator" + libraryFolderPath = "" + exampleFolderPath = "examples" + bootstrapExampleFolderPath = "bootstrap" + hasScenarios = $false + hasLibrary = $false + platformLandingZoneFilePath = "" + } + } + + # Clone the repo and copy the bootstrap and starter configuration files + $repo = $repos[$iacType] + Write-Host "Cloning repo $($repo.repoName)" + git clone -n --depth=1 --filter=tree:0 "https://github.com/Azure/$($repo.repoName)" "$tempFolderPath" | Write-Verbose | Out-Null + Set-Location $tempFolderPath + + Write-Host "Checking out folder $($repo.folderToClone)" + git sparse-checkout set --no-cone $repo.folderToClone | Write-Verbose | Out-Null + git checkout | Write-Verbose | Out-Null + + Set-Location $currentPath + $exampleFolderPath = "$($repo.folderToClone)/$($repo.exampleFolderPath)" + $bootstrapExampleFolderPath = "$exampleFolderPath/$($repo.bootstrapExampleFolderPath)" + + $configFolderPath = Join-Path $targetFolderPath "config" + Write-Host "Creating config folder at $configFolderPath" + New-Item -ItemType "directory" $configFolderPath -Force | Write-Verbose | Out-Null + + # Copy the bootstrap configuration file + Write-Host "Copying bootstrap configuration file to $($targetFolderPath)/config/inputs.yaml" + Copy-Item -Path "$tempFolderPath/$bootstrapExampleFolderPath/inputs-$versionControl.yaml" -Destination "$targetFolderPath/config/inputs.yaml" -Force | Write-Verbose | Out-Null + + if ($repo.hasLibrary) { + $libFolderPath = "$($repo.folderToClone)/$($repo.libraryFolderPath)" + Write-Host "Copying library files to $($targetFolderPath)/config" + Copy-Item -Path "$tempFolderPath/$libFolderPath" -Destination "$targetFolderPath/config" -Recurse -Force | Write-Verbose | Out-Null + } + + # Copy the platform landing zone configuration files based on scenario number or specific file path + if ($repo.hasScenarios) { + $scenarios = @{ + 1 = "full-multi-region/hub-and-spoke-vnet" + 2 = "full-multi-region/virtual-wan" + 3 = "full-multi-region-nva/hub-and-spoke-vnet" + 4 = "full-multi-region-nva/virtual-wan" + 5 = "management-only/management" + 6 = "full-single-region/hub-and-spoke-vnet" + 7 = "full-single-region/virtual-wan" + 8 = "full-single-region-nva/hub-and-spoke-vnet" + 9 = "full-single-region-nva/virtual-wan" + } + + Write-Host "Copying platform landing zone configuration file for scenario $scenarioNumber to $($targetFolderPath)/config/platform-landing-zone.tfvars" + Copy-Item -Path "$tempFolderPath/templates/platform_landing_zone/examples/$($scenarios[$scenarioNumber]).tfvars" -Destination "$targetFolderPath/config/platform-landing-zone.tfvars" -Force | Write-Verbose | Out-Null + + } elseif ($repo.platformLandingZoneFilePath -ne "") { + Write-Host "Copying platform landing zone configuration file to $($targetFolderPath)/config/platform-landing-zone.yaml" + Copy-Item -Path "$tempFolderPath/$($repo.platformLandingZoneFilePath)" -Destination "$targetFolderPath/config/platform-landing-zone.yaml" -Force | Write-Verbose | Out-Null + } + + Remove-Item -Path $tempFolderPath -Recurse -Force | Write-Verbose | Out-Null + } +} From 3f68fb9723aaf85e879de76e338b8567f9c977db Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Fri, 12 Dec 2025 11:31:50 +0000 Subject: [PATCH 4/6] Remove redundant zones code --- .../Get-BootstrapAndStarterConfig.ps1 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 index 26c8fa6..92f64d5 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 @@ -22,19 +22,12 @@ function Get-BootstrapAndStarterConfig { $starterConfigFilePath = "" $bootstrapDetails = $null - $zonesSupport = $null # Get the bootstrap configuration $bootstrapConfigFullPath = Join-Path $bootstrapPath $bootstrapConfigPath Write-Verbose "Bootstrap config path $bootstrapConfigFullPath" $bootstrapConfig = Get-ALZConfig -configFilePath $bootstrapConfigFullPath - # Get the supported regions and availability zones - Write-Verbose "Getting Supported Regions and Availability Zones with Terraform" - $regionsAndZones = Get-AzureRegionData -toolsPath $toolsPath - Write-Verbose "Supported Regions: $($regionsAndZones.supportedRegions)" - $zonesSupport = $regionsAndZones.zonesSupport - # Get the available bootstrap modules $bootstrapModules = $bootstrapConfig.bootstrap_modules.Value @@ -72,7 +65,6 @@ function Get-BootstrapAndStarterConfig { starterModuleSourceFolder = $starterModuleSourceFolder starterReleaseArtifactName = $starterReleaseArtifactName starterConfigFilePath = $starterConfigFilePath - zonesSupport = $zonesSupport } } } From 5b1e5b85eb6f5e8c01041086b087b4bf67a59fc3 Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Fri, 12 Dec 2025 14:22:55 +0000 Subject: [PATCH 5/6] add debugging info --- src/ALZ/Public/Deploy-Accelerator.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ALZ/Public/Deploy-Accelerator.ps1 b/src/ALZ/Public/Deploy-Accelerator.ps1 index 6a05291..ebb9d93 100644 --- a/src/ALZ/Public/Deploy-Accelerator.ps1 +++ b/src/ALZ/Public/Deploy-Accelerator.ps1 @@ -212,10 +212,12 @@ function Deploy-Accelerator { if ($PSCmdlet.ShouldProcess("Accelerator setup", "modify")) { # Normalize output folder path + Write-Verbose "Normalizing: $output_folder_path" if($output_folder_path.StartsWith("~/" )) { $output_folder_path = Join-Path $HOME $output_folder_path.Replace("~/", "") } $output_folder_path = (Resolve-Path -Path $output_folder_path).Path + Write-Verbose "Using output folder path: $output_folder_path" # Check and install tools needed $toolsPath = Join-Path -Path $output_folder_path -ChildPath ".tools" From 6f7978155be7369fbf90449a1e6030cf001f22ab Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Fri, 12 Dec 2025 14:27:23 +0000 Subject: [PATCH 6/6] remove resolve path --- src/ALZ/Public/Deploy-Accelerator.ps1 | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ALZ/Public/Deploy-Accelerator.ps1 b/src/ALZ/Public/Deploy-Accelerator.ps1 index ebb9d93..6cb4818 100644 --- a/src/ALZ/Public/Deploy-Accelerator.ps1 +++ b/src/ALZ/Public/Deploy-Accelerator.ps1 @@ -216,7 +216,6 @@ function Deploy-Accelerator { if($output_folder_path.StartsWith("~/" )) { $output_folder_path = Join-Path $HOME $output_folder_path.Replace("~/", "") } - $output_folder_path = (Resolve-Path -Path $output_folder_path).Path Write-Verbose "Using output folder path: $output_folder_path" # Check and install tools needed @@ -246,7 +245,6 @@ function Deploy-Accelerator { if($inputConfigFilePath.StartsWith("~/" )) { $inputConfigFilePath = Join-Path $HOME $inputConfigFilePath.Replace("~/", "") } - $inputConfigFilePath = (Resolve-Path -Path $inputConfigFilePath).Path Write-Verbose "Loading input config from file: $inputConfigFilePath" $inputConfig = Get-ALZConfig -configFilePath $inputConfigFilePath -inputConfig $inputConfig -hclParserToolPath $hclParserToolPath } @@ -408,7 +406,6 @@ function Deploy-Accelerator { if($additionalFile.StartsWith("~/" )) { $additionalFile = Join-Path $HOME $additionalFile.Replace("~/", "") } - $additionalFile = (Resolve-Path -Path $additionalFile).Path $starterAdditionalFiles += $additionalFile } $inputConfig.starter_additional_files.Value = $starterAdditionalFiles