Skip to content
234 changes: 133 additions & 101 deletions utilities/tools/Test-NamePrefixAvailability.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -56,123 +56,155 @@ function Test-NamePrefixAvailability {
'Microsoft.ContainerRegistry/registries'
'Microsoft.KeyVault/vaults'
)
$parameterFiles = (Get-ChildItem -Path $repoRoot -Recurse -Filter '*.json').FullName | ForEach-Object { $_.Replace('\', '/') }
$parameterFiles = $parameterFiles | Where-Object { $_ -match '(?:{0}).*parameters\.json' -f ($relevantResourceTypes -join '|' -replace '/', '\/+') }

# Replace parameter file tokens
# -----------------------------
$storageAccountNames = @()
$containerRegistryNames = @()
$keyVaultNames = @()

# Tokens in settings.yml
$GlobalVariablesObject = Get-Content -Path (Join-Path $repoRoot 'settings.yml') | ConvertFrom-Yaml -ErrorAction Stop | Select-Object -ExpandProperty variables

# Construct Token Configuration Input
$tokenConfiguration = @{
FilePathList = $parameterFiles
Tokens = @{
'namePrefix' = $namePrefix
}
TokenPrefix = $GlobalVariablesObject | Select-Object -ExpandProperty tokenPrefix
TokenSuffix = $GlobalVariablesObject | Select-Object -ExpandProperty tokenSuffix
$parameterFiles = (Get-ChildItem -Path $repoRoot -Recurse -Filter 'deploy.test.bicep').FullName | Where-Object {
Test-Path (Join-Path (Split-Path $_ -Parent) 'dependencies.bicep') # Currently we only need to consider files that have ResourceGroup resources
} | ForEach-Object {
$_.Replace('\', '/')
}

# Add additional tokens provided by the user
$tokenConfiguration.Tokens += $Tokens

# Invoke Token Replacement Functionality and Convert Tokens in Parameter Files
$null = Convert-TokensInFileList @tokenConfiguration

try {

# Extract Parameter Names
# -----------------------
$storageAccountFiles = $parameterFiles | Where-Object { $_ -match 'Microsoft.Storage/storageAccounts' }
$storageAccountNames = $storageAccountFiles | ForEach-Object { (ConvertFrom-Json (Get-Content $_ -Raw)).parameters.name.value } | Where-Object { $null -ne $_ }

$keyVaultFiles = $parameterFiles | Where-Object { $_ -match 'Microsoft.KeyVault/vaults' }
$keyVaultNames = $keyVaultFiles | ForEach-Object { (ConvertFrom-Json (Get-Content $_ -Raw)).parameters.name.value } | Where-Object { $null -ne $_ }
foreach ($parameterFile in $parameterFiles) {

$fileContent = Get-Content -Path $parameterFile

foreach ($relevantResourceType in $relevantResourceTypes) {
switch ($relevantResourceType) {
'Microsoft.Storage/storageAccounts' {
$filter = 'storageAccountName:'
}
'Microsoft.ContainerRegistry/registries' {
$filter = 'registryName:'
}
'Microsoft.KeyVault/vaults' {
$filter = 'keyVaultName:'
}
Default {
Write-Warning "The entered resource Type '$_' could not be matched."
continue
}
}

$acrFiles = $parameterFiles | Where-Object { $_ -match 'Microsoft.ContainerRegistry/registries' }
$acrNames = $acrFiles | ForEach-Object { (ConvertFrom-Json (Get-Content $_ -Raw)).parameters.name.value } | Where-Object { $null -ne $_ }
$temp = $null

$subscriptionId = (Get-AzContext).Subscription.Id
# determine if entry is of one of the resourceTypes using the filter variable
$temp = $fileContent | ForEach-Object {
if ($_ -match "$filter\s'") { $_ }
}

# Storage
Write-Host "`nCheck Storage Accounts" -ForegroundColor 'Cyan'
Write-Host '======================' -ForegroundColor 'Cyan'
foreach ($storageAccountName in $storageAccountNames) {
$path = '/subscriptions/{0}/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01' -f $subscriptionId
$requestInputObject = @{
Method = 'POST'
Path = $path
Payload = @{
name = $storageAccountName
type = 'Microsoft.Storage/storageAccounts'
} | ConvertTo-Json
# determine serviceshort default value if no parameter has been supplied
$serviceShort = $fileContent | Where-Object {
$_ -Match "^param serviceShort string = '([a-z]+)'$"
} | ForEach-Object {
$matches[1]
}
$response = ((Invoke-AzRestMethod @requestInputObject).Content | ConvertFrom-Json)
if ($response.nameAvailable) { Write-Host "=> The storage account name [$storageAccountName] is currently available" -ForegroundColor 'Green' }
else {
Write-Warning "=> Warning: The storage account name [$storageAccountName] is not available. Please try a different prefix."
$prefixAvailable = $false

if ($temp) {
$temp = $temp.Split($filter)
Comment thread
AlexanderSehr marked this conversation as resolved.
$temp = $temp | Where-Object { $_ -match '\S' } # replace empty lines in array

# trim the entry and replace placeholder values
$temp = $temp.Replace("'", '') # remove trailing quotes
$temp = $temp.Replace('<<namePrefix>>', $namePrefix)
$temp = $temp.Replace('${serviceShort}', $serviceShort)
$temp = $temp.Replace(' ', '') # remove trailing whitespaces

# drop entries which generate its name during runtime (e.g. via uniqueString function in bicep)
if ($temp -match 'uniqueString') {
continue
}

# add entry to resourcetype-specific list
switch ($filter) {
'storageAccountName:' { $storageAccountNames += $temp }
'registryName:' { $containerRegistryNames += $temp }
'keyVaultName:' { $keyVaultNames += $temp }
Default {}
}
}
}
}

# Key Vault
Write-Host "`nChecking Key Vaults" -ForegroundColor 'Cyan'
Write-Host '===================' -ForegroundColor 'Cyan'
foreach ($keyVaultName in $keyVaultNames) {
$path = '/subscriptions/{0}/providers/Microsoft.KeyVault/checkNameAvailability?api-version=2021-10-01' -f $subscriptionId
$requestInputObject = @{
Method = 'POST'
Path = $path
Payload = @{
name = $keyVaultName
type = 'Microsoft.KeyVault/vaults'
} | ConvertTo-Json
}
$response = ((Invoke-AzRestMethod @requestInputObject).Content | ConvertFrom-Json)
if ($response.nameAvailable) { Write-Host "=> The key vault name [$keyVaultName] is currently available" -ForegroundColor 'Green' }
else {
Write-Warning "=> Warning: The key vault name [$keyVaultName] is not available. Please try a different prefix."
$prefixAvailable = $false
}
$storageAccountNames = $storageAccountNames | Select-Object -Unique
$containerRegistryNames = $containerRegistryNames | Select-Object -Unique
$keyVaultNames = $keyVaultNames | Select-Object -Unique

# Extract Parameter Names
# -----------------------
$subscriptionId = (Get-AzContext).Subscription.Id

# Storage
Write-Host "`nCheck Storage Accounts" -ForegroundColor 'Cyan'
Write-Host '======================' -ForegroundColor 'Cyan'
foreach ($storageAccountName in $storageAccountNames) {
$path = '/subscriptions/{0}/providers/Microsoft.Storage/checkNameAvailability?api-version=2021-04-01' -f $subscriptionId
$requestInputObject = @{
Method = 'POST'
Path = $path
Payload = @{
name = $storageAccountName
type = 'Microsoft.Storage/storageAccounts'
} | ConvertTo-Json
}
$response = ((Invoke-AzRestMethod @requestInputObject).Content | ConvertFrom-Json)
if ($response.nameAvailable) { Write-Host "=> The storage account name [$storageAccountName] is currently available" -ForegroundColor 'Green' }
else {
Write-Warning "=> Warning: The storage account name [$storageAccountName] is not available. Please try a different prefix."
$prefixAvailable = $false
}
}

# Azure Container Registry
Write-Host "`nCheck Azure Container Registies" -ForegroundColor 'Cyan'
Write-Host '==============================' -ForegroundColor 'Cyan'
foreach ($acrName in $acrNames) {
$path = '/subscriptions/{0}/providers/Microsoft.ContainerRegistry/checkNameAvailability?api-version=2019-05-01' -f $subscriptionId
$requestInputObject = @{
Method = 'POST'
Path = $path
Payload = @{
name = $acrName
type = 'Microsoft.ContainerRegistry/registries'
} | ConvertTo-Json
}
$response = ((Invoke-AzRestMethod @requestInputObject).Content | ConvertFrom-Json)
if ($response.nameAvailable) { Write-Host "=> The Azure container registry name [$acrName] is currently available" -ForegroundColor 'Green' }
else {
Write-Warning "=> Warning: The Azure container registry name [$acrName] is not available. Please try a different prefix."
$prefixAvailable = $false
}
# Key Vault
Write-Host "`nChecking Key Vaults" -ForegroundColor 'Cyan'
Write-Host '===================' -ForegroundColor 'Cyan'
foreach ($keyVaultName in $keyVaultNames) {
$path = '/subscriptions/{0}/providers/Microsoft.KeyVault/checkNameAvailability?api-version=2021-10-01' -f $subscriptionId
$requestInputObject = @{
Method = 'POST'
Path = $path
Payload = @{
name = $keyVaultName
type = 'Microsoft.KeyVault/vaults'
} | ConvertTo-Json
}
$response = ((Invoke-AzRestMethod @requestInputObject).Content | ConvertFrom-Json)
if ($response.nameAvailable) { Write-Host "=> The key vault name [$keyVaultName] is currently available" -ForegroundColor 'Green' }
else {
Write-Warning "=> Warning: The key vault name [$keyVaultName] is not available. Please try a different prefix."
$prefixAvailable = $false
}
}

Write-Host "`nRESULT" -ForegroundColor 'Cyan'
Write-Host '======' -ForegroundColor 'Cyan'
if (-not $prefixAvailable) {
Write-Error "=> Prefix [$namePrefix] is not available for all resources. Please try a different one."
} else {
Write-Host "=> Prefix [$namePrefix] is available for all resources." -ForegroundColor 'Green'
# Azure Container Registry
Write-Host "`nCheck Azure Container Registries" -ForegroundColor 'Cyan'
Write-Host '==============================' -ForegroundColor 'Cyan'
foreach ($acrName in $acrNames) {
$path = '/subscriptions/{0}/providers/Microsoft.ContainerRegistry/checkNameAvailability?api-version=2019-05-01' -f $subscriptionId
$requestInputObject = @{
Method = 'POST'
Path = $path
Payload = @{
name = $acrName
type = 'Microsoft.ContainerRegistry/registries'
} | ConvertTo-Json
}
$response = ((Invoke-AzRestMethod @requestInputObject).Content | ConvertFrom-Json)
if ($response.nameAvailable) { Write-Host "=> The Azure container registry name [$acrName] is currently available" -ForegroundColor 'Green' }
else {
Write-Warning "=> Warning: The Azure container registry name [$acrName] is not available. Please try a different prefix."
$prefixAvailable = $false
}
} catch {
Write-Error $_
} finally {
# Restore parameter files
# -----------------------
Write-Verbose 'Restoring Tokens'
$null = Convert-TokensInFileList @tokenConfiguration -SwapValueWithName $true
}

Write-Host "`nRESULT" -ForegroundColor 'Cyan'
Write-Host '======' -ForegroundColor 'Cyan'
if (-not $prefixAvailable) {
Write-Error "=> Prefix [$namePrefix] is not available for all resources. Please try a different one."
} else {
Write-Host "=> Prefix [$namePrefix] is available for all resources." -ForegroundColor 'Green'
}
}

Expand Down