diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/AcceleratorInputSchema.json b/src/ALZ/Private/Deploy-Accelerator-Helpers/AcceleratorInputSchema.json index 1e19faf..806ef6a 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/AcceleratorInputSchema.json +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/AcceleratorInputSchema.json @@ -28,6 +28,12 @@ "type": "object", "required": true, "properties": { + "management": { + "description": "The subscription ID for the Management subscription where logging, monitoring, and automation resources will be deployed", + "type": "guid", + "required": true, + "source": "subscription" + }, "connectivity": { "description": "The subscription ID for the Connectivity subscription where networking resources like hubs, firewalls, and DNS will be deployed", "type": "guid", @@ -40,12 +46,6 @@ "required": false, "source": "subscription" }, - "management": { - "description": "The subscription ID for the Management subscription where logging, monitoring, and automation resources will be deployed", - "type": "guid", - "required": true, - "source": "subscription" - }, "security": { "description": "The subscription ID for the Security subscription where security monitoring and governance resources will be deployed", "type": "guid", diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-AzureContext.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-AzureContext.ps1 index 41a208a..5b010df 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-AzureContext.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Get-AzureContext.ps1 @@ -45,6 +45,14 @@ function Get-AzureContext { if ($cacheAge.TotalHours -lt $cacheExpirationHours) { try { $cachedContext = Get-Content -Path $cacheFilePath -Raw -Force | ConvertFrom-Json -AsHashtable + $currentSubscriptionId = az account show --query "id" -o tsv 2>$null + if ($LASTEXITCODE -eq 0 -and $currentSubscriptionId) { + $cachedContext.CurrentSubscriptionId = $currentSubscriptionId.Trim() + } + $currentTenantId = az account show --query "tenantId" -o tsv 2>$null + if ($LASTEXITCODE -eq 0 -and $currentTenantId) { + $cachedContext.CurrentTenantId = $currentTenantId.Trim() + } Write-ToConsoleLog "Using cached Azure context (cached $([math]::Round($cacheAge.TotalMinutes)) minutes ago). Use -clearCache to refresh." Write-ToConsoleLog "Found $($cachedContext.ManagementGroups.Count) management groups, $($cachedContext.Subscriptions.Count) subscriptions, and $($cachedContext.Regions.Count) regions" return $cachedContext @@ -55,17 +63,22 @@ function Get-AzureContext { } $azureContext = @{ - ManagementGroups = @() - Subscriptions = @() - Regions = @() + ManagementGroups = @() + Subscriptions = @() + Regions = @() + CurrentSubscriptionId = $null + CurrentTenantId = $null } Write-ToConsoleLog "Querying Azure for management groups, subscriptions, and regions... (this can take up to 30 seconds)" try { # Get the current tenant ID - $tenantResult = az account show --query "tenantId" -o tsv 2>$null - $currentTenantId = if ($LASTEXITCODE -eq 0 -and $tenantResult) { $tenantResult.Trim() } else { $null } + $accountResult = az account show --query "{tenantId:tenantId, subscriptionId:id}" -o json 2>$null + $account = if ($LASTEXITCODE -eq 0 -and $accountResult) { $accountResult | ConvertFrom-Json } else { $null } + $currentTenantId = $account.tenantId + $azureContext.CurrentSubscriptionId = $account.subscriptionId + $azureContext.CurrentTenantId = $currentTenantId # Get management groups $mgResult = az account management-group list --query "[].{id:name, displayName:displayName}" -o json 2>$null diff --git a/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-ALZConfigurationValue.ps1 b/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-ALZConfigurationValue.ps1 index 17cb8b9..e1273a3 100644 --- a/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-ALZConfigurationValue.ps1 +++ b/src/ALZ/Private/Deploy-Accelerator-Helpers/Request-ALZConfigurationValue.ps1 @@ -37,6 +37,9 @@ function Request-ALZConfigurationValue { [Parameter(Mandatory = $false)] [switch] $AzureContextClearCache, + [Parameter(Mandatory = $false)] + [int] $ScenarioNumber = 0, + [Parameter(Mandatory = $false)] [switch] $SensitiveOnly ) @@ -69,6 +72,10 @@ function Request-ALZConfigurationValue { $isRequired = Get-SchemaProperty -SchemaInfo $SchemaInfo -PropertyName "required" -Default $false $source = Get-SchemaProperty -SchemaInfo $SchemaInfo -PropertyName "source" + if ($Key -in @("management", "connectivity", "identity", "security")) { + $description = $description -replace "\b$([regex]::Escape($Key))(?=\s+subscription\b)", "$([char]27)[33m`$&$([char]27)[0m" + } + # For sensitive inputs, check if value is set via environment variable $envVarValue = $null if ($isSensitive) { @@ -101,6 +108,7 @@ function Request-ALZConfigurationValue { # Determine effective default (don't use placeholders as defaults) $effectiveDefault = if ($isPlaceholder) { "" } elseif ($isArray -and $hasPlaceholderItems) { @() } else { $CurrentValue } + $hasEffectiveDefault = $null -ne $effectiveDefault -and -not [string]::IsNullOrWhiteSpace($effectiveDefault) # Build base parameters for Read-MenuSelection $menuParams = @{ @@ -109,7 +117,7 @@ function Request-ALZConfigurationValue { Options = @() DefaultValue = $effectiveDefault AllowManualEntry = $true - ManualEntryPrompt = "Enter value (press enter to accept default)" + ManualEntryPrompt = if ($hasEffectiveDefault) { "Enter value (press enter to accept default)" } else { "Enter value" } Type = $schemaType IsRequired = $isRequired RequiredMessage = "This field is required. Please enter a value." @@ -127,7 +135,42 @@ function Request-ALZConfigurationValue { $menuParams.ManualEntryPrompt = "Enter subscription ID" $menuParams.RequiredMessage = "This field is required. Please select a subscription." $menuParams.EmptyMessage = "No subscriptions found in Azure context." - if (-not $isRequired) { + $menuParams.DefaultOptionMarker = "" + if ($Key -eq "bootstrap_subscription_id" -and -not [string]::IsNullOrWhiteSpace($AzureContext.CurrentSubscriptionId)) { + $menuParams.DefaultValue = $AzureContext.CurrentSubscriptionId + $menuParams.DefaultOptionMarker = "current" + } elseif ($Key -in @("management", "connectivity", "identity", "security") -and [string]::IsNullOrWhiteSpace($effectiveDefault)) { + $subscriptionsWithNames = @($AzureContext.Subscriptions | ForEach-Object { + $subscriptionName = if ($_.PSObject.Properties.Name -contains "name") { + $_.name + } else { + $_.label -replace '\s+\([^)]+\)$', '' + } + [PSCustomObject]@{ + Name = $subscriptionName + Value = $_.value + } + }) + # Prefer a friendly name match for workload-style keys like "management" or + # "connectivity" so the user is not forced to choose manually when the answer is obvious. + $exactMatches = @($subscriptionsWithNames | Where-Object { $_.Name -ieq $Key }) + $wordMatchPattern = "(?