Private/Test-AzLocalNamingConfigDefaults.ps1
|
Function Test-AzLocalNamingConfigDefaults { ######################################## <# .SYNOPSIS Validates that the naming configuration has been customised from shipped defaults. .DESCRIPTION Checks the naming configuration object for placeholder/example values that ship with the module. These defaults (contoso.com, xxxxxxxx tenant ID) will never work in a real deployment, so this function provides a clear early failure with actionable guidance. Called by public deployment functions before any ARM operations are attempted. .PARAMETER Config The naming configuration object returned by Get-AzLocalNamingConfig. .PARAMETER ConfigFilePath The file path the configuration was loaded from, for error message context. .NOTES Author: Neil Bird, MSFT Version: 1.0 Created: March 27th 2026 #> ######################################## [OutputType([void])] param( [Parameter(Mandatory = $true)] [PSCustomObject]$Config, [Parameter(Mandatory = $false)] [string]$ConfigFilePath = "" ) $configErrors = @() # Check environment section and tenant-specific values. if ($null -eq $Config.PSObject.Properties['environment'] -or $null -eq $Config.environment) { $configErrors += "environment section is missing from the configuration file." } else { if ($null -eq $Config.environment.PSObject.Properties['tenantId'] -or [string]::IsNullOrWhiteSpace([string]$Config.environment.tenantId)) { $configErrors += "environment.tenantId is missing or empty. Set it to your Entra ID tenant GUID." } elseif ($Config.environment.tenantId -eq 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx') { $configErrors += "environment.tenantId is still the placeholder value. Set it to your Entra ID tenant GUID. Find it with: (Get-AzContext).Tenant.Id" } else { [guid]$parsedTenantId = [guid]::Empty if (-not [guid]::TryParse([string]$Config.environment.tenantId, [ref]$parsedTenantId)) { $configErrors += "environment.tenantId must be a valid GUID." } } if ($Config.environment.PSObject.Properties['hciResourceProviderObjectID'] -and -not [string]::IsNullOrWhiteSpace([string]$Config.environment.hciResourceProviderObjectID)) { [guid]$parsedObjectId = [guid]::Empty if (-not [guid]::TryParse([string]$Config.environment.hciResourceProviderObjectID, [ref]$parsedObjectId)) { $configErrors += "environment.hciResourceProviderObjectID must be a valid GUID when specified." } } } # Check every default consumed by Start-AzLocalTemplateDeployment. if ($null -eq $Config.PSObject.Properties['defaults'] -or $null -eq $Config.defaults) { $configErrors += "defaults section is missing from the configuration file." } else { foreach ($propertyName in @('domainFqdn', 'namingPrefix', 'azureStackLCMAdminUsername', 'location', 'storageAccountType')) { if ($null -eq $Config.defaults.PSObject.Properties[$propertyName] -or [string]::IsNullOrWhiteSpace([string]$Config.defaults.$propertyName)) { $configErrors += "defaults.$propertyName is missing or empty." } } foreach ($propertyName in @('dnsServers', 'computeManagementAdapters', 'storageAdapters')) { if ($null -eq $Config.defaults.PSObject.Properties[$propertyName] -or @($Config.defaults.$propertyName).Count -eq 0 -or @($Config.defaults.$propertyName | Where-Object { [string]::IsNullOrWhiteSpace([string]$_) }).Count -gt 0) { $configErrors += "defaults.$propertyName must contain at least one non-empty value." } } if ($Config.defaults.PSObject.Properties['dnsServers']) { foreach ($dnsServer in @($Config.defaults.dnsServers)) { if ([string]::IsNullOrWhiteSpace([string]$dnsServer)) { continue } [System.Net.IPAddress]$parsedAddress = $null if (-not [System.Net.IPAddress]::TryParse([string]$dnsServer, [ref]$parsedAddress)) { $configErrors += "defaults.dnsServers contains invalid IP address '$dnsServer'." } } } if ($Config.defaults.PSObject.Properties['domainFqdn'] -and $Config.defaults.domainFqdn -eq 'contoso.com') { $configErrors += "defaults.domainFqdn is still the example value 'contoso.com'. Set it to your Active Directory domain FQDN." } } # Check every naming pattern consumed by deployment and monitoring functions. if ($null -eq $Config.PSObject.Properties['namingStandards'] -or $null -eq $Config.namingStandards) { $configErrors += "namingStandards section is missing from the configuration file." } else { $requiredNamingStandards = @( 'clusterName', 'resourceGroupName', 'keyVaultName', 'customLocation', 'resourceBridgeName', 'diagnosticStorageAccountName', 'clusterWitnessStorageAccountName', 'nodeNamePattern', 'adouPath', 'deploymentName' ) foreach ($propertyName in $requiredNamingStandards) { if ($null -eq $Config.namingStandards.PSObject.Properties[$propertyName] -or [string]::IsNullOrWhiteSpace([string]$Config.namingStandards.$propertyName)) { $configErrors += "namingStandards.$propertyName is missing or empty." } } if ($Config.namingStandards.PSObject.Properties['adouPath'] -and $Config.namingStandards.adouPath -match 'DC=contoso,DC=com') { $configErrors += "namingStandards.adouPath still references 'DC=contoso,DC=com'. Update the OU path to match your Active Directory structure." } } if ($configErrors.Count -gt 0) { Write-AzLocalLog "Naming configuration file has not been customised for your environment." -Level Error if (-not [string]::IsNullOrWhiteSpace($ConfigFilePath)) { Write-AzLocalLog "Config file: $ConfigFilePath" -Level Error } foreach ($err in $configErrors) { Write-AzLocalLog " - $err" -Level Error } Write-AzLocalLog "Edit the configuration file and update the values above before running a deployment." -Level Error $pathHint = if (-not [string]::IsNullOrWhiteSpace($ConfigFilePath)) { " at '$ConfigFilePath'" } else { "" } throw "Naming configuration${pathHint} is invalid: $($configErrors -join ' ')" } } |