diff --git a/src/ALZ/Private/Config-Helpers/Remove-TerraformMetaFileSet.ps1 b/src/ALZ/Private/Config-Helpers/Remove-TerraformMetaFileSet.ps1 index 1eed2be..4bf3a34 100644 --- a/src/ALZ/Private/Config-Helpers/Remove-TerraformMetaFileSet.ps1 +++ b/src/ALZ/Private/Config-Helpers/Remove-TerraformMetaFileSet.ps1 @@ -12,7 +12,9 @@ function Remove-TerraformMetaFileSet { ".terraform.lock.hcl", "examples", "yaml.tf", - ".alzlib" + ".alzlib", + "tfplan", + "tfplan.json" ), [Parameter(Mandatory = $false)] [switch]$writeVerboseLogs diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-ModuleSetup.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-ModuleSetup.ps1 index 712660c..71470d5 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/New-ModuleSetup.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/New-ModuleSetup.ps1 @@ -40,6 +40,19 @@ function New-ModuleSetup { return $versionAndPath } + if(-not [string]::IsNullOrWhiteSpace($moduleOverrideFolderPath)) { + Write-Verbose "Using module override folder path, skipping version checks." + return New-FolderStructure ` + -targetDirectory $targetDirectory ` + -url $url ` + -release $desiredRelease ` + -releaseArtifactName $releaseArtifactName ` + -targetFolder $targetFolder ` + -sourceFolder $sourceFolder ` + -overrideSourceDirectoryPath $moduleOverrideFolderPath ` + -replaceFiles:$replaceFiles.IsPresent + } + $latestReleaseTag = $null try { $latestResult = Get-GithubReleaseTag -githubRepoUrl $url -release "latest" @@ -50,7 +63,7 @@ function New-ModuleSetup { } $isAutoVersion = $release -eq "latest" - $firstRun = $null -eq $currentVersion + $firstRun = $null -eq $currentVersion -or $currentVersion -eq "" $shouldDownload = $false if($isAutoVersion -and $upgrade.IsPresent -and $null -eq $latestReleaseTag) { @@ -75,11 +88,11 @@ function New-ModuleSetup { if(!$shouldDownload -or $isFirstRun) { $newVersionAvailable = $false $currentCalculatedVersion = $currentVersion - if($isAutoVersion -and $null -ne $latestReleaseTag -and $latestReleaseTag -ne $currentVersion) { + if(!$isFirstRun -and $isAutoVersion -and $null -ne $latestReleaseTag -and $latestReleaseTag -ne $currentVersion) { $newVersionAvailable = $true } - if(!$isAutoVersion -and $null -ne $latestReleaseTag -and $latestReleaseTag -ne $currentVersion) { + if(!$isFirstRun -and !$isAutoVersion -and $null -ne $latestReleaseTag -and $latestReleaseTag -ne $currentVersion) { $newVersionAvailable = $true } diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-ALZConfigurationValue.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-ALZConfigurationValue.ps1 index 2ab28ae..1d18f27 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-ALZConfigurationValue.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-ALZConfigurationValue.ps1 @@ -11,8 +11,10 @@ function Request-ALZConfigurationValue { The Infrastructure as Code type (terraform or bicep). .PARAMETER VersionControl The version control system (github, azure-devops, or local). - .PARAMETER AzureContext - A hashtable containing Azure context information including ManagementGroups, Subscriptions, and Regions arrays. + .PARAMETER AzureContextOutputDirectory + The output directory to pass to Get-AzureContext for caching Azure context data. + .PARAMETER AzureContextClearCache + When set, clears the cached Azure context data before fetching. .PARAMETER SensitiveOnly When set, only prompts for sensitive inputs that are not already set (via environment variables or non-empty config values). .OUTPUTS @@ -30,12 +32,31 @@ function Request-ALZConfigurationValue { [string] $VersionControl, [Parameter(Mandatory = $false)] - [hashtable] $AzureContext = @{ ManagementGroups = @(); Subscriptions = @(); Regions = @() }, + [string] $AzureContextOutputDirectory = "", + + [Parameter(Mandatory = $false)] + [switch] $AzureContextClearCache, [Parameter(Mandatory = $false)] [switch] $SensitiveOnly ) + # Lazy-loaded Azure context - only fetched when first needed + $lazyAzureContext = $null + $azureContextFetched = $false + + function Get-LazyAzureContext { + if (-not $azureContextFetched) { + Set-Variable -Name azureContextFetched -Value $true -Scope 1 + if (-not [string]::IsNullOrWhiteSpace($AzureContextOutputDirectory)) { + Set-Variable -Name lazyAzureContext -Value (Get-AzureContext -OutputDirectory $AzureContextOutputDirectory -ClearCache:$AzureContextClearCache.IsPresent) -Scope 1 + } else { + Set-Variable -Name lazyAzureContext -Value (Get-AzureContext -ClearCache:$AzureContextClearCache.IsPresent) -Scope 1 + } + } + return $lazyAzureContext + } + # Helper function to get a property from schema info safely function Get-SchemaProperty { param($SchemaInfo, $PropertyName, $Default = $null) @@ -70,12 +91,14 @@ function Request-ALZConfigurationValue { $CurrentValue, $SchemaInfo, $Indent = "", - $DefaultDescription = "No description available", - $Subscriptions = @(), - $ManagementGroups = @(), - $Regions = @() + $DefaultDescription = "No description available" ) + # Initialize arrays that will be lazily populated + $Subscriptions = @() + $ManagementGroups = @() + $Regions = @() + $description = Get-SchemaProperty -SchemaInfo $SchemaInfo -PropertyName "description" -Default $DefaultDescription $helpLink = Get-SchemaProperty -SchemaInfo $SchemaInfo -PropertyName "helpLink" $isSensitive = Get-SchemaProperty -SchemaInfo $SchemaInfo -PropertyName "sensitive" -Default $false @@ -243,118 +266,145 @@ function Request-ALZConfigurationValue { # Parse comma-separated values into an array $newValue = @($inputValue -split ',' | ForEach-Object { $_.Trim() } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) } - } elseif ($source -eq "subscription" -and $Subscriptions.Count -gt 0) { - # Show subscription selection list - Write-InformationColored "${Indent} Available subscriptions:" -ForegroundColor Cyan -InformationAction Continue - for ($i = 0; $i -lt $Subscriptions.Count; $i++) { - $sub = $Subscriptions[$i] - if ($sub.id -eq $effectiveDefault) { - Write-InformationColored "${Indent} [$($i + 1)] $($sub.name) ($($sub.id)) (current)" -ForegroundColor Green -InformationAction Continue - } else { - Write-InformationColored "${Indent} [$($i + 1)] $($sub.name) ($($sub.id))" -ForegroundColor White -InformationAction Continue + } elseif ($source -eq "subscription") { + # Lazy load Azure context if we haven't loaded subscriptions yet + if ($Subscriptions.Count -eq 0) { + $ctx = Get-LazyAzureContext + if ($null -ne $ctx -and $ctx.ContainsKey('Subscriptions')) { + $Subscriptions = $ctx.Subscriptions } } - Write-InformationColored "${Indent} [0] Enter manually" -ForegroundColor Gray -InformationAction Continue + if ($Subscriptions.Count -gt 0) { + # Show subscription selection list + Write-InformationColored "${Indent} Available subscriptions:" -ForegroundColor Cyan -InformationAction Continue + for ($i = 0; $i -lt $Subscriptions.Count; $i++) { + $sub = $Subscriptions[$i] + if ($sub.id -eq $effectiveDefault) { + Write-InformationColored "${Indent} [$($i + 1)] $($sub.name) ($($sub.id)) (current)" -ForegroundColor Green -InformationAction Continue + } else { + Write-InformationColored "${Indent} [$($i + 1)] $($sub.name) ($($sub.id))" -ForegroundColor White -InformationAction Continue + } + } + Write-InformationColored "${Indent} [0] Enter manually" -ForegroundColor Gray -InformationAction Continue - $selection = Read-Host "${Indent} Select subscription (1-$($Subscriptions.Count), 0 for manual entry, or press Enter for default)" - if ([string]::IsNullOrWhiteSpace($selection)) { - $newValue = $effectiveDefault - } elseif ($selection -eq "0") { - $newValue = Get-ValidatedGuidInput -PromptText "${Indent} Enter subscription ID" -CurrentValue $effectiveDefault -Indent "${Indent} " - } else { - $selIndex = [int]$selection - 1 - if ($selIndex -ge 0 -and $selIndex -lt $Subscriptions.Count) { - $newValue = $Subscriptions[$selIndex].id - } else { - Write-InformationColored "${Indent} Invalid selection, using default" -ForegroundColor Yellow -InformationAction Continue + $selection = Read-Host "${Indent} Select subscription (1-$($Subscriptions.Count), 0 for manual entry, or press Enter for default)" + if ([string]::IsNullOrWhiteSpace($selection)) { $newValue = $effectiveDefault - } - } - # Require value if required - while ($isRequired -and [string]::IsNullOrWhiteSpace($newValue)) { - Write-InformationColored "${Indent} This field is required. Please select a subscription." -ForegroundColor Red -InformationAction Continue - $selection = Read-Host "${Indent} Select subscription (1-$($Subscriptions.Count), 0 for manual entry)" - if ($selection -eq "0") { - $newValue = Get-ValidatedGuidInput -PromptText "${Indent} Enter subscription ID" -CurrentValue "" -Indent "${Indent} " - } elseif (-not [string]::IsNullOrWhiteSpace($selection)) { + } elseif ($selection -eq "0") { + $newValue = Get-ValidatedGuidInput -PromptText "${Indent} Enter subscription ID" -CurrentValue $effectiveDefault -Indent "${Indent} " + } else { $selIndex = [int]$selection - 1 if ($selIndex -ge 0 -and $selIndex -lt $Subscriptions.Count) { $newValue = $Subscriptions[$selIndex].id + } else { + Write-InformationColored "${Indent} Invalid selection, using default" -ForegroundColor Yellow -InformationAction Continue + $newValue = $effectiveDefault + } + } + # Require value if required + while ($isRequired -and [string]::IsNullOrWhiteSpace($newValue)) { + Write-InformationColored "${Indent} This field is required. Please select a subscription." -ForegroundColor Red -InformationAction Continue + $selection = Read-Host "${Indent} Select subscription (1-$($Subscriptions.Count), 0 for manual entry)" + if ($selection -eq "0") { + $newValue = Get-ValidatedGuidInput -PromptText "${Indent} Enter subscription ID" -CurrentValue "" -Indent "${Indent} " + } elseif (-not [string]::IsNullOrWhiteSpace($selection)) { + $selIndex = [int]$selection - 1 + if ($selIndex -ge 0 -and $selIndex -lt $Subscriptions.Count) { + $newValue = $Subscriptions[$selIndex].id + } } } } - } elseif ($source -eq "managementGroup" -and $ManagementGroups.Count -gt 0) { - # Show management group selection list - Write-InformationColored "${Indent} Available management groups:" -ForegroundColor Cyan -InformationAction Continue - for ($i = 0; $i -lt $ManagementGroups.Count; $i++) { - $mg = $ManagementGroups[$i] - if ($mg.id -eq $effectiveDefault) { - Write-InformationColored "${Indent} [$($i + 1)] $($mg.displayName) ($($mg.id)) (current)" -ForegroundColor Green -InformationAction Continue - } else { - Write-InformationColored "${Indent} [$($i + 1)] $($mg.displayName) ($($mg.id))" -ForegroundColor White -InformationAction Continue + } elseif ($source -eq "managementGroup") { + # Lazy load Azure context if we haven't loaded management groups yet + if ($ManagementGroups.Count -eq 0) { + $ctx = Get-LazyAzureContext + if ($null -ne $ctx -and $ctx.ContainsKey('ManagementGroups')) { + $ManagementGroups = $ctx.ManagementGroups } } - Write-InformationColored "${Indent} [0] Enter manually" -ForegroundColor Gray -InformationAction Continue - Write-InformationColored "${Indent} Press Enter to leave empty (uses Tenant Root Group)" -ForegroundColor Gray -InformationAction Continue + if ($ManagementGroups.Count -gt 0) { + # Show management group selection list + Write-InformationColored "${Indent} Available management groups:" -ForegroundColor Cyan -InformationAction Continue + for ($i = 0; $i -lt $ManagementGroups.Count; $i++) { + $mg = $ManagementGroups[$i] + if ($mg.id -eq $effectiveDefault) { + Write-InformationColored "${Indent} [$($i + 1)] $($mg.displayName) ($($mg.id)) (current)" -ForegroundColor Green -InformationAction Continue + } else { + Write-InformationColored "${Indent} [$($i + 1)] $($mg.displayName) ($($mg.id))" -ForegroundColor White -InformationAction Continue + } + } + Write-InformationColored "${Indent} [0] Enter manually" -ForegroundColor Gray -InformationAction Continue + Write-InformationColored "${Indent} Press Enter to leave empty (uses Tenant Root Group)" -ForegroundColor Gray -InformationAction Continue - $selection = Read-Host "${Indent} Select management group (1-$($ManagementGroups.Count), 0 for manual entry, or press Enter for default)" - if ([string]::IsNullOrWhiteSpace($selection)) { - $newValue = $effectiveDefault - } elseif ($selection -eq "0") { - $newValue = Read-Host "${Indent} Enter management group ID" - if ([string]::IsNullOrWhiteSpace($newValue)) { + $selection = Read-Host "${Indent} Select management group (1-$($ManagementGroups.Count), 0 for manual entry, or press Enter for default)" + if ([string]::IsNullOrWhiteSpace($selection)) { $newValue = $effectiveDefault - } - } else { - $selIndex = [int]$selection - 1 - if ($selIndex -ge 0 -and $selIndex -lt $ManagementGroups.Count) { - $newValue = $ManagementGroups[$selIndex].id + } elseif ($selection -eq "0") { + $newValue = Read-Host "${Indent} Enter management group ID" + if ([string]::IsNullOrWhiteSpace($newValue)) { + $newValue = $effectiveDefault + } } else { - Write-InformationColored "${Indent} Invalid selection, using default" -ForegroundColor Yellow -InformationAction Continue - $newValue = $effectiveDefault + $selIndex = [int]$selection - 1 + if ($selIndex -ge 0 -and $selIndex -lt $ManagementGroups.Count) { + $newValue = $ManagementGroups[$selIndex].id + } else { + Write-InformationColored "${Indent} Invalid selection, using default" -ForegroundColor Yellow -InformationAction Continue + $newValue = $effectiveDefault + } } } - } elseif ($source -eq "azureRegion" -and $Regions.Count -gt 0) { - # Show region selection list - Write-InformationColored "${Indent} Available regions (AZ = Availability Zone support):" -ForegroundColor Cyan -InformationAction Continue - for ($i = 0; $i -lt $Regions.Count; $i++) { - $region = $Regions[$i] - $azIndicator = if ($region.hasAvailabilityZones) { " [AZ]" } else { "" } - if ($region.name -eq $effectiveDefault) { - Write-InformationColored "${Indent} [$($i + 1)] $($region.displayName) ($($region.name))$azIndicator (current)" -ForegroundColor Green -InformationAction Continue - } else { - Write-InformationColored "${Indent} [$($i + 1)] $($region.displayName) ($($region.name))$azIndicator" -ForegroundColor White -InformationAction Continue + } elseif ($source -eq "azureRegion") { + # Lazy load Azure context if we haven't loaded regions yet + if ($Regions.Count -eq 0) { + $ctx = Get-LazyAzureContext + if ($null -ne $ctx -and $ctx.ContainsKey('Regions')) { + $Regions = $ctx.Regions } } - Write-InformationColored "${Indent} [0] Enter manually" -ForegroundColor Gray -InformationAction Continue - - $selection = Read-Host "${Indent} Select region (1-$($Regions.Count), 0 for manual entry, or press Enter for default)" - if ([string]::IsNullOrWhiteSpace($selection)) { - $newValue = $effectiveDefault - } elseif ($selection -eq "0") { - $newValue = Read-Host "${Indent} Enter region name (e.g., uksouth, eastus)" - if ([string]::IsNullOrWhiteSpace($newValue)) { - $newValue = $effectiveDefault + if ($Regions.Count -gt 0) { + # Show region selection list + Write-InformationColored "${Indent} Available regions (AZ = Availability Zone support):" -ForegroundColor Cyan -InformationAction Continue + for ($i = 0; $i -lt $Regions.Count; $i++) { + $region = $Regions[$i] + $azIndicator = if ($region.hasAvailabilityZones) { " [AZ]" } else { "" } + if ($region.name -eq $effectiveDefault) { + Write-InformationColored "${Indent} [$($i + 1)] $($region.displayName) ($($region.name))$azIndicator (current)" -ForegroundColor Green -InformationAction Continue + } else { + Write-InformationColored "${Indent} [$($i + 1)] $($region.displayName) ($($region.name))$azIndicator" -ForegroundColor White -InformationAction Continue + } } - } else { - $selIndex = [int]$selection - 1 - if ($selIndex -ge 0 -and $selIndex -lt $Regions.Count) { - $newValue = $Regions[$selIndex].name - } else { - Write-InformationColored "${Indent} Invalid selection, using default" -ForegroundColor Yellow -InformationAction Continue + Write-InformationColored "${Indent} [0] Enter manually" -ForegroundColor Gray -InformationAction Continue + + $selection = Read-Host "${Indent} Select region (1-$($Regions.Count), 0 for manual entry, or press Enter for default)" + if ([string]::IsNullOrWhiteSpace($selection)) { $newValue = $effectiveDefault - } - } - # Require value if required - while ($isRequired -and [string]::IsNullOrWhiteSpace($newValue)) { - Write-InformationColored "${Indent} This field is required. Please select a region." -ForegroundColor Red -InformationAction Continue - $selection = Read-Host "${Indent} Select region (1-$($Regions.Count), 0 for manual entry)" - if ($selection -eq "0") { + } elseif ($selection -eq "0") { $newValue = Read-Host "${Indent} Enter region name (e.g., uksouth, eastus)" - } elseif (-not [string]::IsNullOrWhiteSpace($selection)) { + if ([string]::IsNullOrWhiteSpace($newValue)) { + $newValue = $effectiveDefault + } + } else { $selIndex = [int]$selection - 1 if ($selIndex -ge 0 -and $selIndex -lt $Regions.Count) { $newValue = $Regions[$selIndex].name + } else { + Write-InformationColored "${Indent} Invalid selection, using default" -ForegroundColor Yellow -InformationAction Continue + $newValue = $effectiveDefault + } + } + # Require value if required + while ($isRequired -and [string]::IsNullOrWhiteSpace($newValue)) { + Write-InformationColored "${Indent} This field is required. Please select a region." -ForegroundColor Red -InformationAction Continue + $selection = Read-Host "${Indent} Select region (1-$($Regions.Count), 0 for manual entry)" + if ($selection -eq "0") { + $newValue = Read-Host "${Indent} Enter region name (e.g., uksouth, eastus)" + } elseif (-not [string]::IsNullOrWhiteSpace($selection)) { + $selIndex = [int]$selection - 1 + if ($selIndex -ge 0 -and $selIndex -lt $Regions.Count) { + $newValue = $Regions[$selIndex].name + } } } } @@ -532,7 +582,7 @@ function Request-ALZConfigurationValue { continue } - $result = Read-InputValue -Key $subKey -CurrentValue $subCurrentValue -SchemaInfo $subSchemaInfo -Indent " " -DefaultDescription "Subscription ID for $subKey" -Subscriptions $AzureContext.Subscriptions -ManagementGroups $AzureContext.ManagementGroups -Regions $AzureContext.Regions + $result = Read-InputValue -Key $subKey -CurrentValue $subCurrentValue -SchemaInfo $subSchemaInfo -Indent " " -DefaultDescription "Subscription ID for $subKey" $subNewValue = $result.Value $subIsSensitive = $result.IsSensitive @@ -595,7 +645,7 @@ function Request-ALZConfigurationValue { } } - $result = Read-InputValue -Key $key -CurrentValue $currentValue -SchemaInfo $schemaInfo -Subscriptions $AzureContext.Subscriptions -ManagementGroups $AzureContext.ManagementGroups -Regions $AzureContext.Regions + $result = Read-InputValue -Key $key -CurrentValue $currentValue -SchemaInfo $schemaInfo $newValue = $result.Value $isSensitive = $result.IsSensitive diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-AcceleratorConfigurationInput.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-AcceleratorConfigurationInput.ps1 index 9337e36..64732b1 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-AcceleratorConfigurationInput.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-AcceleratorConfigurationInput.ps1 @@ -103,13 +103,13 @@ function Request-AcceleratorConfigurationInput { # Prompt for sensitive inputs that are not already set (e.g., PATs) Write-InformationColored "`nChecking for sensitive inputs that need to be provided..." -ForegroundColor Yellow -InformationAction Continue - $azureContext = Get-AzureContext -OutputDirectory $folderConfig.OutputFolderPath -ClearCache:$ClearCache.IsPresent Request-ALZConfigurationValue ` -ConfigFolderPath $folderConfig.ConfigFolderPath ` -IacType $folderConfig.IacType ` -VersionControl $folderConfig.VersionControl ` - -AzureContext $azureContext ` + -AzureContextOutputDirectory $folderConfig.OutputFolderPath ` + -AzureContextClearCache:$ClearCache.IsPresent ` -SensitiveOnly Write-InformationColored "`nProceeding with destroy..." -ForegroundColor Yellow -InformationAction Continue @@ -202,13 +202,22 @@ function Request-AcceleratorConfigurationInput { # Offer to configure inputs interactively (default is Yes) $configureNowResponse = Read-Host "`nWould you like to configure the input values interactively now? (Y/n)" if ($configureNowResponse -ne "n" -and $configureNowResponse -ne "N") { - $azureContext = Get-AzureContext -OutputDirectory $outputFolderPath -ClearCache:$ClearCache.IsPresent + Request-ALZConfigurationValue ` + -ConfigFolderPath $configFolderPath ` + -IacType $selectedIacType ` + -VersionControl $selectedVersionControl ` + -AzureContextOutputDirectory $outputFolderPath ` + -AzureContextClearCache:$ClearCache.IsPresent + } else { + Write-InformationColored "`nChecking for sensitive inputs that need to be provided..." -ForegroundColor Yellow -InformationAction Continue Request-ALZConfigurationValue ` -ConfigFolderPath $configFolderPath ` -IacType $selectedIacType ` -VersionControl $selectedVersionControl ` - -AzureContext $azureContext + -AzureContextOutputDirectory $outputFolderPath ` + -AzureContextClearCache:$ClearCache.IsPresent ` + -SensitiveOnly } # Check for VS Code or VS Code Insiders and offer to open the config folder diff --git a/src/ALZ/Public/Remove-PlatformLandingZone.ps1 b/src/ALZ/Public/Remove-PlatformLandingZone.ps1 index 4ecdb16..252bba4 100644 --- a/src/ALZ/Public/Remove-PlatformLandingZone.ps1 +++ b/src/ALZ/Public/Remove-PlatformLandingZone.ps1 @@ -1077,8 +1077,8 @@ function Remove-PlatformLandingZone { -IsPlan -LogFilePath $using:TempLogFileForPlan } else { $result = (az account management-group subscription add --name $subscriptionsTargetManagementGroup --subscription $subscription.name 2>&1) - if($result) { - Write-ToConsoleLog "Failed to move subscription to target management group: $($subscriptionsTargetManagementGroup), subscription: $($subscription.displayName)" -IsWarning -NoNewLine + if($result -and $result.ToLower().Contains("Error")) { + Write-ToConsoleLog "Failed to move subscription to target management group: $($subscriptionsTargetManagementGroup), subscription: $($subscription.displayName), $result" -IsWarning -NoNewLine } else { Write-ToConsoleLog "Moved subscription to target management group: $($subscriptionsTargetManagementGroup), subscription: $($subscription.displayName)" -NoNewLine } @@ -1092,8 +1092,8 @@ function Remove-PlatformLandingZone { -IsPlan -LogFilePath $using:TempLogFileForPlan } else { $result = (az account management-group subscription remove --name $_ --subscription $subscription.name 2>&1) - if($result) { - Write-ToConsoleLog "Failed to remove subscription from management group: $_, subscription: $($subscription.displayName)" -IsWarning -NoNewLine + if($result -and $result.ToLower().Contains("Error")) { + Write-ToConsoleLog "Failed to remove subscription from management group: $_, subscription: $($subscription.displayName), $result" -IsWarning -NoNewLine } else { Write-ToConsoleLog "Removed subscription from management group: $_, subscription: $($subscription.displayName)" -NoNewLine } diff --git a/src/Tests/Unit/Private/Request-AcceleratorConfigurationInput.Tests.ps1 b/src/Tests/Unit/Private/Request-AcceleratorConfigurationInput.Tests.ps1 new file mode 100644 index 0000000..5f6c853 --- /dev/null +++ b/src/Tests/Unit/Private/Request-AcceleratorConfigurationInput.Tests.ps1 @@ -0,0 +1,132 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'ALZ' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'ALZ' { + Describe 'Request-AcceleratorConfigurationInput Function Tests' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } + + Context 'When skipping interactive configuration but continuing' { + It 'invokes SensitiveOnly check for missing sensitive inputs' { + $script:answers = @( + 'C:\\temp\\acc', # target folder + 'n', # overwrite existing folder? + 'n', # configure inputs now? + 'yes' # continue? + ) + $script:idx = 0 + $prompts = [System.Collections.Generic.List[string]]::new() + Mock -CommandName Read-Host -MockWith { + param($Prompt) + $prompts.Add($Prompt) | Out-Null + if ($script:idx -lt $script:answers.Count) { + $script:answers[$script:idx++] + } else { + 'yes' + } + } + + Mock -CommandName Get-NormalizedPath -MockWith { param($Path) $Path } + Mock -CommandName Get-AcceleratorFolderConfiguration -MockWith { + [pscustomobject]@{ + FolderExists = $true + IsValid = $true + ConfigFolderPath = 'C:\\temp\\acc\\config' + InputsYamlPath = 'C:\\temp\\acc\\config\\inputs.yaml' + IacType = 'terraform' + VersionControl = 'github' + OutputFolderPath = 'C:\\temp\\acc\\output' + } + } + Mock -CommandName Resolve-Path -MockWith { param($Path) [pscustomobject]@{ Path = $Path } } + Mock -CommandName Get-Command -MockWith { $null } + Mock -CommandName Get-AzureContext -MockWith { @{ ManagementGroups = @(); Subscriptions = @(); Regions = @() } } + Mock -CommandName Request-ALZConfigurationValue -MockWith { } + Mock -CommandName Get-AcceleratorConfigPath -MockWith { + [pscustomobject]@{ + InputConfigFilePaths = @('inputs.yaml') + StarterAdditionalFiles = @() + } + } + Mock -CommandName ConvertTo-AcceleratorResult -MockWith { + param($Continue, $InputConfigFilePaths, $StarterAdditionalFiles, $OutputFolderPath) + @{ Continue = $Continue; InputConfigFilePaths = $InputConfigFilePaths; StarterAdditionalFiles = $StarterAdditionalFiles; OutputFolderPath = $OutputFolderPath } + } + + $result = Request-AcceleratorConfigurationInput + + # Debug: $prompts and $script:answers can be inspected if needed + + $result.Continue | Should -BeTrue + + Should -Invoke -CommandName Request-ALZConfigurationValue -ParameterFilter { $SensitiveOnly } -Times 1 -Scope It + # Get-AzureContext is now called lazily inside Request-ALZConfigurationValue, not by Request-AcceleratorConfigurationInput + Should -Invoke -CommandName Get-AzureContext -Times 0 -Scope It + } + } + + Context 'When configuring interactively' { + It 'does not invoke SensitiveOnly check' { + $script:answers = @( + 'C:\\temp\\acc', # target folder + 'n', # overwrite existing folder? + '', # configure inputs now? (default yes) + 'yes' # continue? + ) + $script:idx = 0 + Mock -CommandName Read-Host -MockWith { + param($Prompt) + if ($script:idx -lt $script:answers.Count) { + $script:answers[$script:idx++] + } else { + 'yes' + } + } + + Mock -CommandName Get-NormalizedPath -MockWith { param($Path) $Path } + Mock -CommandName Get-AcceleratorFolderConfiguration -MockWith { + [pscustomobject]@{ + FolderExists = $true + IsValid = $true + ConfigFolderPath = 'C:\\temp\\acc\\config' + InputsYamlPath = 'C:\\temp\\acc\\config\\inputs.yaml' + IacType = 'terraform' + VersionControl = 'github' + OutputFolderPath = 'C:\\temp\\acc\\output' + } + } + Mock -CommandName Resolve-Path -MockWith { param($Path) [pscustomobject]@{ Path = $Path } } + Mock -CommandName Get-Command -MockWith { $null } + Mock -CommandName Get-AzureContext -MockWith { @{ ManagementGroups = @(); Subscriptions = @(); Regions = @() } } + Mock -CommandName Request-ALZConfigurationValue -MockWith { } + Mock -CommandName Get-AcceleratorConfigPath -MockWith { + [pscustomobject]@{ + InputConfigFilePaths = @('inputs.yaml') + StarterAdditionalFiles = @() + } + } + Mock -CommandName ConvertTo-AcceleratorResult -MockWith { + param($Continue, $InputConfigFilePaths, $StarterAdditionalFiles, $OutputFolderPath) + @{ Continue = $Continue; InputConfigFilePaths = $InputConfigFilePaths; StarterAdditionalFiles = $StarterAdditionalFiles; OutputFolderPath = $OutputFolderPath } + } + + $result = Request-AcceleratorConfigurationInput + + $result.Continue | Should -BeTrue + + Should -Invoke -CommandName Request-ALZConfigurationValue -ParameterFilter { $SensitiveOnly } -Times 0 -Scope It + } + } + } +}