From 739bcfd4824e8f6c2ae6ea1bcd059ced057d435e Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Mon, 18 Nov 2024 20:58:55 +0000 Subject: [PATCH 1/6] Save changes --- .../Convert-ParametersToInputConfig.ps1 | 10 +- .../Private/Config-Helpers/Get-ALZConfig.ps1 | 19 ++- src/ALZ/Private/Config-Helpers/Set-Config.ps1 | 2 +- .../Config-Helpers/Write-TfvarsJsonFile.ps1 | 10 +- .../Get-BootstrapAndStarterConfig.ps1 | 2 - .../New-Bootstrap.ps1 | 71 +++++++--- src/ALZ/Public/New-ALZEnvironment.ps1 | 124 +++++++++++------- 7 files changed, 164 insertions(+), 74 deletions(-) diff --git a/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 b/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 index 2edc45f5..340c7dd8 100644 --- a/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 +++ b/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 @@ -14,7 +14,10 @@ function Convert-ParametersToInputConfig { if($inputConfig.PsObject.Properties.Name -contains $parameterAlias) { Write-Verbose "Alias $parameterAlias exists in input config, renaming..." $configItem = $inputConfig.PSObject.Properties | Where-Object { $_.Name -eq $parameterAlias } - $inputConfig | Add-Member -NotePropertyName $parameterKey -NotePropertyValue $configItem.Value + $inputConfig | Add-Member -NotePropertyName $parameterKey -NotePropertyValue @{ + Value = $configItem.Value + Source = "parameter" + } $inputConfig.PSObject.Properties.Remove($configItem.Name) continue } @@ -34,7 +37,10 @@ function Convert-ParametersToInputConfig { $variableValue = [bool]::Parse($variableValue) } Write-Verbose "Adding parameter $parameterKey with value $variableValue" - $inputConfig | Add-Member -NotePropertyName $parameterKey -NotePropertyValue $variableValue + $inputConfig | Add-Member -NotePropertyName $parameterKey -NotePropertyValue @{ + Value = $variableValue + Source = "parameter" + } } } diff --git a/src/ALZ/Private/Config-Helpers/Get-ALZConfig.ps1 b/src/ALZ/Private/Config-Helpers/Get-ALZConfig.ps1 index a3c5e41a..67ed1c56 100644 --- a/src/ALZ/Private/Config-Helpers/Get-ALZConfig.ps1 +++ b/src/ALZ/Private/Config-Helpers/Get-ALZConfig.ps1 @@ -3,7 +3,9 @@ function Get-ALZConfig { [Parameter(Mandatory = $false)] [string] $configFilePath = "", [Parameter(Mandatory = $false)] - [PSCustomObject] $inputConfig = $null + [PSCustomObject] $inputConfig = $null, + [Parameter(Mandatory = $false)] + [string] $hclParserToolPath = "" ) if(!(Test-Path $configFilePath)) { @@ -39,14 +41,25 @@ function Get-ALZConfig { Write-Error $errorMessage throw $errorMessage } + } elseif($extension -eq ".tfvars") { + try { + $config = [PSCustomObject](& $hclParserToolPath $configFilePath | ConvertFrom-Json) + } catch { + $errorMessage = "Failed to parse HCL inputs. Please check the HCL file for errors and try again. $_" + Write-Error $errorMessage + throw $errorMessage + } } else { - throw "The config file must be a json or yaml/yml file" + throw "The config file must be a json, yaml/yml or tfvars file" } Write-Verbose "Config file loaded from $configFilePath with $($config.PSObject.Properties.Name.Count) properties." foreach($property in $config.PSObject.Properties) { - $inputConfig | Add-Member -NotePropertyName $property.Name -NotePropertyValue $property.Value + $inputConfig | Add-Member -NotePropertyName $property.Name -NotePropertyValue @{ + Value = $property.Value + Source = $extension + } } return $inputConfig diff --git a/src/ALZ/Private/Config-Helpers/Set-Config.ps1 b/src/ALZ/Private/Config-Helpers/Set-Config.ps1 index a7f95225..365c3ba9 100644 --- a/src/ALZ/Private/Config-Helpers/Set-Config.ps1 +++ b/src/ALZ/Private/Config-Helpers/Set-Config.ps1 @@ -72,7 +72,7 @@ function Set-Config { # Look for input config match $inputConfigItem = $inputConfig.PsObject.Properties | Where-Object { $_.Name -eq $inputConfigName } if($null -ne $inputConfigItem) { - $configurationValue.Value.Value = $inputConfigItem.Value + $configurationValue.Value.Value = $inputConfigItem.Value.Value continue } diff --git a/src/ALZ/Private/Config-Helpers/Write-TfvarsJsonFile.ps1 b/src/ALZ/Private/Config-Helpers/Write-TfvarsJsonFile.ps1 index 8596862c..65ca0b53 100644 --- a/src/ALZ/Private/Config-Helpers/Write-TfvarsJsonFile.ps1 +++ b/src/ALZ/Private/Config-Helpers/Write-TfvarsJsonFile.ps1 @@ -5,7 +5,10 @@ function Write-TfvarsJsonFile { [string] $tfvarsFilePath, [Parameter(Mandatory = $false)] - [PSObject] $configuration + [PSObject] $configuration, + + [Parameter(Mandatory = $false)] + [string[]] $skipItems = @() ) if ($PSCmdlet.ShouldProcess("Download Terraform Tools", "modify")) { @@ -17,6 +20,11 @@ function Write-TfvarsJsonFile { $jsonObject = [ordered]@{} foreach($configurationProperty in $configuration.PSObject.Properties | Sort-Object Name) { + if($skipItems -contains $configurationProperty.Name) { + Write-Verbose "Skipping configuration property: $($configurationProperty.Name)" + continue + } + $configurationValue = $configurationProperty.Value.Value if($null -ne $configurationValue -and $configurationValue.ToString() -eq "sourced-from-env") { diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 index 449a46d4..7011e584 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 @@ -11,8 +11,6 @@ function Get-BootstrapAndStarterConfig { [Parameter(Mandatory = $false)] [string]$bootstrapConfigPath, [Parameter(Mandatory = $false)] - [PSCustomObject]$inputConfig, - [Parameter(Mandatory = $false)] [string]$toolsPath ) diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 index 157cee4f..aef7fa96 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 @@ -46,7 +46,15 @@ function New-Bootstrap { [Parameter(Mandatory = $false)] [string] - $hclParserToolPath + $hclParserToolPath, + + [Parameter(Mandatory = $false)] + [switch] + $convertTfvarsToJson, + + [Parameter(Mandatory = $false)] + [string[]] + $inputConfigFilePaths = @() ) if ($PSCmdlet.ShouldProcess("ALZ-Terraform module configuration", "modify")) { @@ -71,13 +79,16 @@ function New-Bootstrap { $starterFoldersToRetain = @() if($hasStarter) { - if($inputConfig.starter_module_name -eq "") { - $inputConfig.starter_module_name = Request-SpecialInput -type "starter" -starterConfig $starterConfig + if($inputConfig.starter_module_name.Value -eq "") { + $inputConfig.starter_module_name = @{ + Value = Request-SpecialInput -type "starter" -starterConfig $starterConfig + Source = "user" + } } - $chosenStarterConfig = $starterConfig.starter_modules.$($inputConfig.starter_module_name) + $chosenStarterConfig = $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value) - Write-Verbose "Selected Starter: $($inputConfig.starter_module_name))" + Write-Verbose "Selected Starter: $($inputConfig.starter_module_name.Value))" $starterModulePath = (Resolve-Path (Join-Path -Path $starterPath -ChildPath $chosenStarterConfig.location)).Path $starterRootModuleFolderPath = $starterModulePath Write-Verbose "Starter Module Path: $starterModulePath" @@ -94,7 +105,10 @@ function New-Bootstrap { $starterFoldersToRetain += $starterRootModuleFolder # Add the root module folder to bootstrap input config - $inputConfig | Add-Member -NotePropertyName "root_module_folder_relative_path" -NotePropertyValue $starterRootModuleFolder + $inputConfig | Add-Member -NotePropertyName "root_module_folder_relative_path" -NotePropertyValue @{ + Value = $starterRootModuleFolder + Source = "caluated" + } # Set the starter root module folder full path $starterRootModuleFolderPath = Join-Path -Path $starterModulePath -ChildPath $starterRootModuleFolder @@ -126,25 +140,37 @@ function New-Bootstrap { } if($iac -eq "bicep") { - $starterParameters = Convert-BicepConfigToInputConfig -bicepConfig $starterConfig.starter_modules.$($inputConfig.starter_module_name) -validators $validationConfig + $starterParameters = Convert-BicepConfigToInputConfig -bicepConfig $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value) -validators $validationConfig } } # Set computed inputs - $inputConfig | Add-Member -NotePropertyName "module_folder_path" -NotePropertyValue $starterModulePath - $inputConfig | Add-Member -NotePropertyName "availability_zones_bootstrap" -NotePropertyValue @(Get-AvailabilityZonesSupport -region $inputConfig.bootstrap_location -zonesSupport $zonesSupport) + $inputConfig | Add-Member -NotePropertyName "module_folder_path" -NotePropertyValue @{ + Value = $starterModulePath + Source = "calculated" + } + $inputConfig | Add-Member -NotePropertyName "availability_zones_bootstrap" -NotePropertyValue @{ + Value = @(Get-AvailabilityZonesSupport -region $inputConfig.bootstrap_location.Value -zonesSupport $zonesSupport) + Source = "calculated" + } if($inputConfig.PSObject.Properties.Name -contains "starter_location" -and $inputConfig.PSObject.Properties.Name -notcontains "starter_locations") { - Write-Verbose "Converting starter_location $($inputConfig.starter_location) to starter_locations..." - $inputConfig | Add-Member -NotePropertyName "starter_locations" -NotePropertyValue @($inputConfig.starter_location) + 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" + } } if($inputConfig.PSObject.Properties.Name -contains "starter_locations") { $availabilityZonesStarter = @() - foreach($region in $inputConfig.starter_locations) { + foreach($region in $inputConfig.starter_locations.Value) { $availabilityZonesStarter += , @(Get-AvailabilityZonesSupport -region $region -zonesSupport $zonesSupport) } - $inputConfig | Add-Member -NotePropertyName "availability_zones_starter" -NotePropertyValue $availabilityZonesStarter + $inputConfig | Add-Member -NotePropertyName "availability_zones_starter" -NotePropertyValue @{ + Value = $availabilityZonesStarter + Source = "calculated" + } } Write-Verbose "Final Input config: $(ConvertTo-Json $inputConfig -Depth 100)" @@ -188,7 +214,18 @@ function New-Bootstrap { } } Remove-TerraformMetaFileSet -path $starterModulePath -writeVerboseLogs:$writeVerboseLogs.IsPresent - Write-TfvarsJsonFile -tfvarsFilePath $starterTfvarsPath -configuration $starterConfiguration + if($convertTfvarsToJson) { + Write-TfvarsJsonFile -tfvarsFilePath $starterTfvarsPath -configuration $starterConfiguration + } else { + $inputsFromTfvars = $inputConfig.PSObject.Properties | Where-Object { $_.Value.Source -eq ".tfvars" } | Select-Object -ExpandProperty Name + Write-TfvarsJsonFile -tfvarsFilePath $starterTfvarsPath -configuration $starterConfiguration -skipItems $inputsFromTfvars + foreach($inputConfigFilePath in $inputConfigFilePaths | Where-Object { $_ -like "*.tfvars" }) { + $fileName = [System.IO.Path]::GetFileName($inputConfigFilePath) + $fileName = $fileName.Replace(".tfvars", ".auto.tfvars") + $destination = Join-Path -Path $starterModulePath -ChildPath $fileName + Copy-Item -Path $inputConfigFilePath -Destination $destination + } + } } if($iac -eq "bicep") { @@ -198,16 +235,16 @@ function New-Bootstrap { Write-JsonFile -jsonFilePath $starterBicepVarsPath -configuration $starterConfiguration # Remove unrequired files - $foldersOrFilesToRetain = $starterConfig.starter_modules.$($inputConfig.starter_module_name).folders_or_files_to_retain + $foldersOrFilesToRetain = $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value).folders_or_files_to_retain $foldersOrFilesToRetain += "parameters.json" $foldersOrFilesToRetain += "config" $foldersOrFilesToRetain += "starter-cache.json" - foreach($deployment_file in $starterConfig.starter_modules.$($inputConfig.starter_module_name).deployment_files) { + foreach($deployment_file in $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value).deployment_files) { $foldersOrFilesToRetain += $deployment_file.templateParametersSourceFilePath } - $subFoldersOrFilesToRemove = $starterConfig.starter_modules.$($inputConfig.starter_module_name).subfolders_or_files_to_remove + $subFoldersOrFilesToRemove = $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value).subfolders_or_files_to_remove Remove-UnrequiredFileSet -path $starterModulePath -foldersOrFilesToRetain $foldersOrFilesToRetain -subFoldersOrFilesToRemove $subFoldersOrFilesToRemove -writeVerboseLogs:$writeVerboseLogs.IsPresent } diff --git a/src/ALZ/Public/New-ALZEnvironment.ps1 b/src/ALZ/Public/New-ALZEnvironment.ps1 index deb7ff1f..91fcbb17 100644 --- a/src/ALZ/Public/New-ALZEnvironment.ps1 +++ b/src/ALZ/Public/New-ALZEnvironment.ps1 @@ -117,7 +117,7 @@ function New-ALZEnvironment { [Parameter( Mandatory = $false, - HelpMessage = "[OPTIONAL] Used to override the bootstrap folder source. This can be used to provide a folder locally in restricted environments or dev. Environment variable: ALZ_bootstrapModuleOverrideFolderPath. Config file input: bootstrapModuleOverrideFolderPath." + HelpMessage = "[OPTIONAL] Used to override the bootstrap folder source. This can be used to provide a folder locally in restricted environments or dev. Environment variable: ALZ_bootstrapModuleOverrideFolderPath. Config file input: bootstrap_module_override_folder_path." )] [Alias("bo")] [Alias("bootstrapModuleOverrideFolderPath")] @@ -125,7 +125,7 @@ function New-ALZEnvironment { [Parameter( Mandatory = $false, - HelpMessage = "[OPTIONAL] Used to override the starter folder source. This can be used to provide a folder locally in restricted environments. Environment variable: ALZ_starterModuleOverrideFolderPath. Config file input: starterModuleOverrideFolderPath." + HelpMessage = "[OPTIONAL] Used to override the starter folder source. This can be used to provide a folder locally in restricted environments. Environment variable: ALZ_starterModuleOverrideFolderPath. Config file input: starter_module_override_folder_path." )] [Alias("so")] [Alias("starterModuleOverrideFolderPath")] @@ -149,11 +149,19 @@ function New-ALZEnvironment { [Parameter( Mandatory = $false, - HelpMessage = "[OPTIONAL] An extra level of logging that is turned off by default for easier debugging. Environment variable: ALZ_write_verbose_logs. Config file input: writeVerboseLogs." + HelpMessage = "[OPTIONAL] An extra level of logging that is turned off by default for easier debugging. Environment variable: ALZ_write_verbose_logs. Config file input: write_verbose_logs." )] [Alias("v")] [Alias("writeVerboseLogs")] - [switch] $write_verbose_logs + [switch] $write_verbose_logs, + + [Parameter( + Mandatory = $false, + HelpMessage = "[OPTIONAL] Determines whether to convert tfvars input files to tfvars.json files. Environment variable: ALZ_convert_tfvars_to_json. Config file input: convert_tfvars_to_json." + )] + [Alias("tj")] + [Alias("convertTfvarsToJson")] + [switch] $convert_tfvars_to_json ) $ProgressPreference = "SilentlyContinue" @@ -162,6 +170,16 @@ function New-ALZEnvironment { if ($PSCmdlet.ShouldProcess("Accelerator setup", "modify")) { + # Check and install tools needed + $toolsPath = Join-Path -Path $output_folder_path -ChildPath ".tools" + if($skipInternetChecks) { + Write-InformationColored "Skipping Terraform tool check as you used the skipInternetCheck parameter. Please ensure you have the most recent version of Terraform installed" -ForegroundColor Yellow -InformationAction Continue + } else { + Write-InformationColored "Checking you have the latest version of Terraform installed..." -ForegroundColor Green -NewLineBefore -InformationAction Continue + Get-TerraformTool -version "latest" -toolsPath $toolsPath + $hclParserToolPath = Get-HCLParserTool -toolVersion "v0.6.0" -toolsPath $toolsPath + } + # Get User Inputs from the input config file $inputConfig = $null if ($inputConfigFilePaths.Length -eq 0) { @@ -173,10 +191,11 @@ function New-ALZEnvironment { $inputConfigFilePaths = @(Request-SpecialInput -type "inputConfigFilePath") } } + + # Get the input config from yaml and json files foreach($inputConfigFilePath in $inputConfigFilePaths) { - $inputConfig = Get-ALZConfig -configFilePath $inputConfigFilePath -inputConfig $inputConfig + $inputConfig = Get-ALZConfig -configFilePath $inputConfigFilePath -inputConfig $inputConfig -hclParserToolPath $hclParserToolPath } - Write-Verbose "Initial Input config: $(ConvertTo-Json $inputConfig -Depth 100)" # Set accelerator input config from input file, environment variables or parameters $parameters = (Get-Command -Name $MyInvocation.InvocationName).Parameters @@ -200,23 +219,19 @@ function New-ALZEnvironment { $inputConfig = Convert-ParametersToInputConfig -inputConfig $inputConfig -parameters $parametersWithValues # Get the IAC type if not specified - if ($inputConfig.iac_type -eq "") { - $inputConfig.iac_type = Request-SpecialInput -type "iac" + if ($inputConfig.iac_type.Value -eq "") { + $inputConfig.iac_type = @{ + Value = Request-SpecialInput -type "iac" + Source = "user" + } } - # Check and install Terraform CLI if needed - $toolsPath = Join-Path -Path $inputConfig.output_folder_path -ChildPath ".tools" - if($skipInternetChecks) { - Write-InformationColored "Skipping Terraform tool check as you used the skipInternetCheck parameter. Please ensure you have the most recent version of Terraform installed" -ForegroundColor Yellow -InformationAction Continue - } else { - Write-InformationColored "Checking you have the latest version of Terraform installed..." -ForegroundColor Green -NewLineBefore -InformationAction Continue - if ($inputConfig.iac_type -eq "bicep") { - Write-InformationColored "Although you have selected Bicep, the Accelerator leverages the Terraform tool to bootstrap your Version Control System and Azure. This is will not impact your choice of Bicep post this initial bootstrap. Please refer to our documentation for further details..." -ForegroundColor Yellow -InformationAction Continue - } - Get-TerraformTool -version "latest" -toolsPath $toolsPath - $hclParserToolPath = Get-HCLParserTool -toolVersion "v0.6.0" -toolsPath $toolsPath + if ($inputConfig.iac_type.Value -eq "bicep") { + Write-InformationColored "Although you have selected Bicep, the Accelerator leverages the Terraform tool to bootstrap your Version Control System and Azure. This is 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 = "" @@ -225,15 +240,15 @@ function New-ALZEnvironment { Write-InformationColored "Checking and Downloading the bootstrap module..." -ForegroundColor Green -NewLineBefore -InformationAction Continue $versionAndPath = New-ModuleSetup ` - -targetDirectory $inputConfig.output_folder_path ` + -targetDirectory $inputConfig.output_folder_path.Value ` -targetFolder $bootstrapTargetFolder ` - -sourceFolder $inputConfig.bootstrap_source_folder ` - -url $inputConfig.bootstrap_module_url ` - -release $inputConfig.bootstrap_module_version ` - -releaseArtifactName $inputConfig.bootstrap_module_release_artifact_name ` - -moduleOverrideFolderPath $inputConfig.bootstrap_module_override_folder_path ` - -skipInternetChecks $inputConfig.skip_internet_checks ` - -replaceFile:$inputConfig.replace_files + -sourceFolder $inputConfig.bootstrap_source_folder.Value ` + -url $inputConfig.bootstrap_module_url.Value ` + -release $inputConfig.bootstrap_module_version.Value ` + -releaseArtifactName $inputConfig.bootstrap_module_release_artifact_name.Value ` + -moduleOverrideFolderPath $inputConfig.bootstrap_module_override_folder_path.Value ` + -skipInternetChecks $inputConfig.skip_internet_checks.Value ` + -replaceFile:$inputConfig.replace_files.Value $bootstrapReleaseTag = $versionAndPath.releaseTag $bootstrapPath = $versionAndPath.path @@ -254,16 +269,18 @@ function New-ALZEnvironment { $zonesSupport = $null # Request the bootstrap type if not already specified - if($inputConfig.bootstrap_module_name -eq "") { - $inputConfig.bootstrap_module_name = Request-SpecialInput -type "bootstrap" -bootstrapModules $bootstrapModules + if($inputConfig.bootstrap_module_name.Value -eq "") { + $inputConfig.bootstrap_module_name = @{ + Value = Request-SpecialInput -type "bootstrap" -bootstrapModules $bootstrapModules + Source = "user" + } } $bootstrapAndStarterConfig = Get-BootstrapAndStarterConfig ` - -iac $inputConfig.iac_type ` - -bootstrap $inputConfig.bootstrap_module_name ` + -iac $inputConfig.iac_type.Value ` + -bootstrap $inputConfig.bootstrap_module_name.Value ` -bootstrapPath $bootstrapPath ` - -bootstrapConfigPath $inputConfig.bootstrap_config_path ` - -inputConfig $inputConfig ` + -bootstrapConfigPath $inputConfig.bootstrap_config_path.Value ` -toolsPath $toolsPath $bootstrapDetails = $bootstrapAndStarterConfig.bootstrapDetails @@ -283,15 +300,15 @@ function New-ALZEnvironment { Write-InformationColored "Checking and downloading the starter module..." -ForegroundColor Green -NewLineBefore -InformationAction Continue $versionAndPath = New-ModuleSetup ` - -targetDirectory $inputConfig.output_folder_path ` + -targetDirectory $inputConfig.output_folder_path.Value ` -targetFolder $starterModuleTargetFolder ` -sourceFolder $starterModuleSourceFolder ` -url $starterModuleUrl ` - -release $inputConfig.starter_module_version ` + -release $inputConfig.starter_module_version.Value ` -releaseArtifactName $starterReleaseArtifactName ` - -moduleOverrideFolderPath $inputConfig.starter_module_override_folder_path ` - -skipInternetChecks $inputConfig.skip_internet_checks ` - -replaceFile:$inputConfig.replace_files + -moduleOverrideFolderPath $inputConfig.starter_module_override_folder_path.Value ` + -skipInternetChecks $inputConfig.skip_internet_checks.Value ` + -replaceFile:$inputConfig.replace_files.Value $starterReleaseTag = $versionAndPath.releaseTag $starterPath = $versionAndPath.path @@ -299,16 +316,25 @@ function New-ALZEnvironment { } # Set computed interface inputs - $inputConfig | Add-Member -MemberType NoteProperty -Name "on_demand_folder_repository" -Value $starterModuleUrl - $inputConfig | Add-Member -MemberType NoteProperty -Name "on_demand_folder_artifact_name" -Value $starterReleaseArtifactName - $inputConfig | Add-Member -MemberType NoteProperty -Name "release_version" -Value ($starterReleaseTag -eq "local" ? $inputConfig.starter_module_version : $starterReleaseTag) + $inputConfig | Add-Member -MemberType NoteProperty -Name "on_demand_folder_repository" -Value @{ + Value = $starterModuleUrl + Source = "calaculated" + } + $inputConfig | Add-Member -MemberType NoteProperty -Name "on_demand_folder_artifact_name" -Value @{ + Value = $starterReleaseArtifactName + Source = "calaculated" + } + $inputConfig | Add-Member -MemberType NoteProperty -Name "release_version" -Value @{ + Value = ($starterReleaseTag -eq "local" ? $inputConfig.starter_module_version.Value : $starterReleaseTag) + Source = "calaculated" + } # Run the bootstrap - $bootstrapTargetPath = Join-Path $inputConfig.output_folder_path $bootstrapTargetFolder - $starterTargetPath = Join-Path $inputConfig.output_folder_path $starterFolder + $bootstrapTargetPath = Join-Path $inputConfig.output_folder_path.Value $bootstrapTargetFolder + $starterTargetPath = Join-Path $inputConfig.output_folder_path.Value $starterFolder New-Bootstrap ` - -iac $inputConfig.iac_type ` + -iac $inputConfig.iac_type.Value ` -bootstrapDetails $bootstrapDetails ` -validationConfig $validationConfig ` -inputConfig $inputConfig ` @@ -318,11 +344,13 @@ function New-ALZEnvironment { -starterTargetPath $starterTargetPath ` -starterRelease $starterReleaseTag ` -starterConfig $starterConfig ` - -autoApprove:$inputConfig.auto_approve ` - -destroy:$inputConfig.destroy ` + -autoApprove:$inputConfig.auto_approve.Value ` + -destroy:$inputConfig.destroy.Value ` -zonesSupport $zonesSupport ` - -writeVerboseLogs:$inputConfig.write_verbose_logs ` - -hclParserToolPath $hclParserToolPath + -writeVerboseLogs:$inputConfig.write_verbose_logs.Value ` + -hclParserToolPath $hclParserToolPath ` + -convertTfvarsToJson:$inputConfig.convert_tfvars_to_json.Value ` + -inputConfigFilePaths $inputConfigFilePaths } $ProgressPreference = "Continue" From 51893d25555358bdd24b7f3dd6346b60f1839b4b Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Mon, 18 Nov 2024 21:01:41 +0000 Subject: [PATCH 2/6] Fix path --- src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 index aef7fa96..c180f688 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 @@ -222,7 +222,7 @@ function New-Bootstrap { foreach($inputConfigFilePath in $inputConfigFilePaths | Where-Object { $_ -like "*.tfvars" }) { $fileName = [System.IO.Path]::GetFileName($inputConfigFilePath) $fileName = $fileName.Replace(".tfvars", ".auto.tfvars") - $destination = Join-Path -Path $starterModulePath -ChildPath $fileName + $destination = Join-Path -Path $starterRootModuleFolderPath -ChildPath $fileName Copy-Item -Path $inputConfigFilePath -Destination $destination } } From f97cee14802de0558c8c9a05bb53aaec86bb287e Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Mon, 18 Nov 2024 21:05:36 +0000 Subject: [PATCH 3/6] Missed var --- src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 index c180f688..57c4efcb 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 @@ -229,7 +229,7 @@ function New-Bootstrap { } if($iac -eq "bicep") { - Copy-ParametersFileCollection -starterPath $starterModulePath -configFiles $starterConfig.starter_modules.$($inputConfig.starter_module_name).deployment_files + Copy-ParametersFileCollection -starterPath $starterModulePath -configFiles $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value).deployment_files Set-ComputedConfiguration -configuration $starterConfiguration Edit-ALZConfigurationFilesInPlace -alzEnvironmentDestination $starterModulePath -configuration $starterConfiguration Write-JsonFile -jsonFilePath $starterBicepVarsPath -configuration $starterConfiguration From b9ee27a5631e467412002f323c574d6f8c99e37f Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Mon, 18 Nov 2024 22:14:38 +0000 Subject: [PATCH 4/6] Save changes --- .../Convert-ParametersToInputConfig.ps1 | 4 ++-- .../Config-Helpers/Remove-TerraformMetaFileSet.ps1 | 3 ++- .../Private/Config-Helpers/Request-SpecialInput.ps1 | 2 +- .../Get-BootstrapAndStarterConfig.ps1 | 8 ++++---- .../Deploy-Accelerator-Helpers/New-Bootstrap.ps1 | 12 ++++++------ 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 b/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 index 340c7dd8..4ba8458f 100644 --- a/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 +++ b/src/ALZ/Private/Config-Helpers/Convert-ParametersToInputConfig.ps1 @@ -15,8 +15,8 @@ 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 - Source = "parameter" + Value = $configItem.Value.Value + Source = $configItem.Value.Source } $inputConfig.PSObject.Properties.Remove($configItem.Name) continue diff --git a/src/ALZ/Private/Config-Helpers/Remove-TerraformMetaFileSet.ps1 b/src/ALZ/Private/Config-Helpers/Remove-TerraformMetaFileSet.ps1 index 0bc14988..d2f0d035 100644 --- a/src/ALZ/Private/Config-Helpers/Remove-TerraformMetaFileSet.ps1 +++ b/src/ALZ/Private/Config-Helpers/Remove-TerraformMetaFileSet.ps1 @@ -11,7 +11,8 @@ function Remove-TerraformMetaFileSet { "terraform.tfvars", ".terraform.lock.hcl", "examples", - "yaml.tf" + "yaml.tf", + ".alzlib" ), [Parameter(Mandatory = $false)] [switch]$writeVerboseLogs diff --git a/src/ALZ/Private/Config-Helpers/Request-SpecialInput.ps1 b/src/ALZ/Private/Config-Helpers/Request-SpecialInput.ps1 index 13957b94..b6009b41 100644 --- a/src/ALZ/Private/Config-Helpers/Request-SpecialInput.ps1 +++ b/src/ALZ/Private/Config-Helpers/Request-SpecialInput.ps1 @@ -42,7 +42,7 @@ function Request-SpecialInput { } if($type -eq "starter") { - foreach($starter in $starterConfig.starter_modules.PsObject.Properties) { + foreach($starter in $starterConfig.starter_modules.Value.PsObject.Properties) { if($starter.Name -eq $starterPipelineFolder) { continue } diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 index 7011e584..041a9856 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-BootstrapAndStarterConfig.ps1 @@ -29,7 +29,7 @@ function Get-BootstrapAndStarterConfig { $bootstrapConfigFullPath = Join-Path $bootstrapPath $bootstrapConfigPath Write-Verbose "Bootstrap config path $bootstrapConfigFullPath" $bootstrapConfig = Get-ALZConfig -configFilePath $bootstrapConfigFullPath - $validationConfig = $bootstrapConfig.validators + $validationConfig = $bootstrapConfig.validators.Value # Get the supported regions and availability zones Write-Verbose "Getting Supported Regions and Availability Zones with Terraform" @@ -40,7 +40,7 @@ function Get-BootstrapAndStarterConfig { $azureLocationValidator.AllowedValues.Values = $regionsAndZones.supportedRegions # Get the available bootstrap modules - $bootstrapModules = $bootstrapConfig.bootstrap_modules + $bootstrapModules = $bootstrapConfig.bootstrap_modules.Value # Get the bootstrap details and validate it exists (use alias for legacy values) $bootstrapDetails = $bootstrapModules.PsObject.Properties | Where-Object { $_.Name -eq $bootstrap -or $bootstrap -in $_.Value.aliases } @@ -55,9 +55,9 @@ function Get-BootstrapAndStarterConfig { if($null -ne $bootstrapStarterModule) { # If the bootstrap has starter modules, get the details and url $hasStarterModule = $true - $starterModules = $bootstrapConfig.PSObject.Properties | Where-Object { $_.Name -eq "starter_modules" } + $starterModules = $bootstrapConfig.starter_modules.Value $starterModuleType = $bootstrapStarterModule.Value - $starterModuleDetails = $starterModules.Value.PSObject.Properties | Where-Object { $_.Name -eq $starterModuleType } + $starterModuleDetails = $starterModules.PSObject.Properties | Where-Object { $_.Name -eq $starterModuleType } if($null -eq $starterModuleDetails) { Write-InformationColored "The starter modules '$($starterModuleType)' for the bootstrap type '$bootstrap' that you have selected does not exist. This could be an issue with your custom configuration, please check and try again..." -ForegroundColor Red -InformationAction Continue throw diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 index 57c4efcb..fd5324f6 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 @@ -86,7 +86,7 @@ function New-Bootstrap { } } - $chosenStarterConfig = $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value) + $chosenStarterConfig = $starterConfig.starter_modules.Value.$($inputConfig.starter_module_name.Value) Write-Verbose "Selected Starter: $($inputConfig.starter_module_name.Value))" $starterModulePath = (Resolve-Path (Join-Path -Path $starterPath -ChildPath $chosenStarterConfig.location)).Path @@ -140,7 +140,7 @@ function New-Bootstrap { } if($iac -eq "bicep") { - $starterParameters = Convert-BicepConfigToInputConfig -bicepConfig $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value) -validators $validationConfig + $starterParameters = Convert-BicepConfigToInputConfig -bicepConfig $starterConfig.starter_modules.Value.$($inputConfig.starter_module_name.Value) -validators $validationConfig } } @@ -229,22 +229,22 @@ function New-Bootstrap { } if($iac -eq "bicep") { - Copy-ParametersFileCollection -starterPath $starterModulePath -configFiles $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value).deployment_files + Copy-ParametersFileCollection -starterPath $starterModulePath -configFiles $starterConfig.starter_modules.Value.$($inputConfig.starter_module_name.Value).deployment_files Set-ComputedConfiguration -configuration $starterConfiguration Edit-ALZConfigurationFilesInPlace -alzEnvironmentDestination $starterModulePath -configuration $starterConfiguration Write-JsonFile -jsonFilePath $starterBicepVarsPath -configuration $starterConfiguration # Remove unrequired files - $foldersOrFilesToRetain = $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value).folders_or_files_to_retain + $foldersOrFilesToRetain = $starterConfig.starter_modules.Value.$($inputConfig.starter_module_name.Value).folders_or_files_to_retain $foldersOrFilesToRetain += "parameters.json" $foldersOrFilesToRetain += "config" $foldersOrFilesToRetain += "starter-cache.json" - foreach($deployment_file in $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value).deployment_files) { + foreach($deployment_file in $starterConfig.starter_modules.Value.$($inputConfig.starter_module_name.Value).deployment_files) { $foldersOrFilesToRetain += $deployment_file.templateParametersSourceFilePath } - $subFoldersOrFilesToRemove = $starterConfig.starter_modules.$($inputConfig.starter_module_name.Value).subfolders_or_files_to_remove + $subFoldersOrFilesToRemove = $starterConfig.starter_modules.Value.$($inputConfig.starter_module_name.Value).subfolders_or_files_to_remove Remove-UnrequiredFileSet -path $starterModulePath -foldersOrFilesToRetain $foldersOrFilesToRetain -subFoldersOrFilesToRemove $subFoldersOrFilesToRemove -writeVerboseLogs:$writeVerboseLogs.IsPresent } From c44e9e9a7208d9558708bca60a243507562d0c75 Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Tue, 19 Nov 2024 10:25:26 +0000 Subject: [PATCH 5/6] Add ability to supply additional files and folders to the starter --- .../New-Bootstrap.ps1 | 24 +++++++++++++++++-- src/ALZ/Public/New-ALZEnvironment.ps1 | 13 ++++++++-- 2 files changed, 33 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 fd5324f6..7b70bd9b 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-Bootstrap.ps1 @@ -54,7 +54,11 @@ function New-Bootstrap { [Parameter(Mandatory = $false)] [string[]] - $inputConfigFilePaths = @() + $inputConfigFilePaths = @(), + + [Parameter(Mandatory = $false)] + [string[]] + $starterAdditionalFiles = @() ) if ($PSCmdlet.ShouldProcess("ALZ-Terraform module configuration", "modify")) { @@ -223,7 +227,23 @@ function New-Bootstrap { $fileName = [System.IO.Path]::GetFileName($inputConfigFilePath) $fileName = $fileName.Replace(".tfvars", ".auto.tfvars") $destination = Join-Path -Path $starterRootModuleFolderPath -ChildPath $fileName - Copy-Item -Path $inputConfigFilePath -Destination $destination + Write-Verbose "Copying tfvars file $inputConfigFilePath to $destination" + Copy-Item -Path $inputConfigFilePath -Destination $destination -Force + } + } + + # Copy additional files + foreach($additionalFile in $starterAdditionalFiles) { + if(Test-Path $additionalFile -PathType Container) { + $folderName = ([System.IO.DirectoryInfo]::new($additionalFile)).Name + $destination = Join-Path -Path $starterRootModuleFolderPath -ChildPath $folderName + Write-Verbose "Copying folder $additionalFile to $destination" + Copy-Item -Path "$additionalFile/*" -Destination $destination -Recurse -Force + } else { + $fileName = [System.IO.Path]::GetFileName($inputConfigFilePath) + $destination = Join-Path -Path $starterRootModuleFolderPath -ChildPath $fileName + Write-Verbose "Copying file $additionalFile to $destination" + Copy-Item -Path $additionalFile -Destination $destination -Force } } } diff --git a/src/ALZ/Public/New-ALZEnvironment.ps1 b/src/ALZ/Public/New-ALZEnvironment.ps1 index 91fcbb17..f5269014 100644 --- a/src/ALZ/Public/New-ALZEnvironment.ps1 +++ b/src/ALZ/Public/New-ALZEnvironment.ps1 @@ -13,7 +13,7 @@ function New-ALZEnvironment { param ( [Parameter( Mandatory = $false, - HelpMessage = "[REQUIRED] The configuration inputs in json or yaml format. Environment variable: ALZ_input_config_path" + HelpMessage = "[REQUIRED] The configuration inputs in json, yaml or tfvars format. Environment variable: ALZ_input_config_path" )] [Alias("inputs")] [Alias("c")] @@ -43,6 +43,14 @@ function New-ALZEnvironment { [Alias("starter")] [string] $starter_module_name = "", + [Parameter( + Mandatory = $false, + HelpMessage = "[OPTIONAL] The additional files or folders to be copied directly to the starter module root folder. Environment variable: ALZ_starter_additional_files. Config file input: starter_additional_files." + )] + [Alias("saf")] + [Alias("starterAdditionalFiles")] + [string[]] $starter_additional_files = @(), + [Parameter( Mandatory = $false, HelpMessage = "[OPTIONAL] The target directory for the accelerator working set of files. Defaults to current working folder. Environment variable: ALZ_output_folder_path. Config file input: output_folder_path." @@ -350,7 +358,8 @@ function New-ALZEnvironment { -writeVerboseLogs:$inputConfig.write_verbose_logs.Value ` -hclParserToolPath $hclParserToolPath ` -convertTfvarsToJson:$inputConfig.convert_tfvars_to_json.Value ` - -inputConfigFilePaths $inputConfigFilePaths + -inputConfigFilePaths $inputConfigFilePaths ` + -starterAdditionalFiles $inputConfig.starter_additional_files.Value } $ProgressPreference = "Continue" From 030cb128c3c36d07fe6ec72246e5830260f4711d Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Thu, 21 Nov 2024 15:17:51 +0000 Subject: [PATCH 6/6] Fix indexed input bug --- src/ALZ/Private/Config-Helpers/Set-Config.ps1 | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/ALZ/Private/Config-Helpers/Set-Config.ps1 b/src/ALZ/Private/Config-Helpers/Set-Config.ps1 index 365c3ba9..4494010c 100644 --- a/src/ALZ/Private/Config-Helpers/Set-Config.ps1 +++ b/src/ALZ/Private/Config-Helpers/Set-Config.ps1 @@ -47,20 +47,29 @@ function Set-Config { $indexSplit = $inputConfigName.Split([char[]]@('[', ']'), [System.StringSplitOptions]::RemoveEmptyEntries) $inputConfigItem = $inputConfig.PsObject.Properties | Where-Object { $_.Name -eq $indexSplit[0] } if($null -ne $inputConfigItem) { - if(!$inputConfigItem.Value.GetType().ImplementedInterfaces.Contains([System.Collections.ICollection])) { + $inputConfigItemValue = $inputConfigItem.Value.Value + if(!$inputConfigItemValue.GetType().ImplementedInterfaces.Contains([System.Collections.ICollection])) { Write-Error "Input config item $($inputConfigName) is not an array, but an index was specified." throw "Input config item $($inputConfigName) is not an array, but an index was specified." } $index = [int]$indexSplit[1] - if($inputConfigItem.Value.Length -le $index) { + if($inputConfigItemValue.Length -le $index) { Write-Verbose "Input config item $($inputConfigName) does not have an index of $index." + if($index -eq 0) { + Write-Error "At least one value is required for input config item $($inputConfigName)." + throw "At least one value is required for input config item $($inputConfigName)." + } } else { - $inputConfigItemValue = $inputConfigItem.Value[$index] - if($null -ne $inputConfigItemValue) { - $configurationValue.Value.Value = $inputConfigItemValue + $inputConfigItemIndexValue = $inputConfigItemValue[$index] + if($null -ne $inputConfigItemIndexValue) { + $configurationValue.Value.Value = $inputConfigItemIndexValue continue } else { Write-Verbose "Input config item $($inputConfigName) with index $index is null." + if($index -eq 0) { + Write-Error "At least one value is required for input config item $($inputConfigName)." + throw "At least one value is required for input config item $($inputConfigName)." + } } } } else {