Public/Get-emsEnvironmentFromLocalFile.ps1
|
<#PSScriptInfo
.VERSION 1.0.0 .GUID 666c04e1-2bab-4491-b18c-baa964f58bda .AUTHOR enthus Managed Services GmbH .COMPANYNAME enthus Managed Services GmbH #> #Requires -Version 5.1 <# .SYNOPSIS Loads the content of an environment file. Asks the user interactively for the desired environment. .DESCRIPTION This cmdlet loads the content of an environment file by prompting the user to select a tenant name and stage name. It searches for environment files matching the pattern '.env.{tenant name}.{stage name}.json' in the current directory and provides interactive selection for available options. The function validates file existence, provides user-friendly prompts with default values and returns the parsed JSON content. It supports the following stage name types: loc (local), stg (staging), prd (production) and tst (test). .NOTES PSVersion: 5.1.x or 7.2.x ENVIRONMENT: [ ] Azure Automation [ ] Azure Function [x] Local [ ] Nerdio [ ] PowerShell Universal [ ] Server [ ] ... REQUIRED CONTEXT: [ ] Application && Delegated [ ] Application [ ] Delegated [x] User REQUIRED PERMISSIONS: - None .PARAMETER TenantName Reference parameter that will be updated with the selected tenant name. This parameter is mandatory. The value is used as a default option if already set. .PARAMETER StageName Reference parameter that will be updated with the selected stage name. This parameter is mandatory. Supported values: loc, stg, prd, tst. The value is used as a default option if already set. .INPUTS None. This cmdlet does not accept pipeline input. .OUTPUTS System.Object. Returns the parsed JSON content of the selected environment file. .EXAMPLE $environmentTenantName = $null $environmentStageName = $null $environment = Get-emsEnvironmentFromLocalFile -TenantName ([ref]$environmentTenantName) -StageName ([ref]$environmentStageName) Prompts the user to select an environment file and returns its content while updating the tenant and stage name variables. .EXAMPLE $environmentTenantName = "contoso" $environmentStageName = "prd" $environment = Get-emsEnvironmentFromLocalFile -TenantName ([ref]$environmentTenantName) -StageName ([ref]$environmentStageName) Uses existing values as defaults and prompts for confirmation or allows changing the selection. .EXAMPLE $environmentTenantName = $null $environmentStageName = $null $environment = Get-emsEnvironmentFromLocalFile -TenantName ([ref]$environmentTenantName) -StageName ([ref]$environmentStageName) -Path "C:\Config" Searches for environment files in the specified directory instead of the current directory. #> function Get-emsEnvironmentFromLocalFile { [CmdletBinding()] [OutputType([System.Object])] param ( [Parameter(Mandatory = $true)] [ref]$TenantName, [Parameter(Mandatory = $true)] [ref]$StageName, [Parameter()] [string]$Path = "./" ) $verbosePrefix = "Get-emsEnvironmentFromLocalFile | " #region Validation if (!(Get-emsIsInteractiveHost)) { throw "This function requires an interactive PowerShell host." } #endregion Validation $validStageNames = @('loc', 'stg', 'prd', 'tst') $stageNamePattern = "($($validStageNames -join '|'))" try { #region File discovery $environmentFilesRegex = "^\.env\.(?<tenantName>[\w-]+)\.(?<stageName>$stageNamePattern)\.json$" $environmentFilesNamingExample = ".env.tenantName.stageName.json" Write-Verbose "$($verbosePrefix)Search for environment files in path '$Path' ..." if (!(Test-Path -Path $Path)) { throw [System.IO.DirectoryNotFoundException]::new("The specified path '$Path' does not exist.") } $files = Get-ChildItem -Path $Path -File -ErrorAction Stop Write-Verbose "$($verbosePrefix)Filter files by environment naming schema ('$environmentFilesRegex') ..." $environmentFiles = $files | Where-Object { $_.Name -match $environmentFilesRegex } | ForEach-Object { $match = [regex]::Match($_.Name, $environmentFilesRegex) [PSCustomObject]@{ File = $_ TenantName = $match.Groups['tenantName'].Value StageName = $match.Groups['stageName'].Value FullName = $_.FullName } } if ($environmentFiles.Count -eq 0) { throw [System.IO.FileNotFoundException]::new("No environment files found with naming schema: '$environmentFilesNamingExample'.") } Write-Verbose "$($verbosePrefix)>> $($environmentFiles.Count) environment file(s) found" #endregion File discovery #region Tenant name selection $availableTenantNames = $environmentFiles.TenantName | Sort-Object -Unique Write-Verbose "$($verbosePrefix)Available tenant names: $($availableTenantNames -join ', ')" $selectedTenantName = Read-emsPrompt -Title "Environment file selection" -Question "Please enter the tenant name you want to use:" -Options $availableTenantNames -DefaultOption $TenantName.Value # Reset stage name if tenant name has changed if ($TenantName.Value -and ($TenantName.Value -ne $selectedTenantName)) { Write-Verbose "$($verbosePrefix)Tenant name changed from '$($TenantName.Value)' to '$selectedTenantName'; reset stage name to null ..." $StageName.Value = $null } #endregion Tenant name selection #region Stage name selection $availableStageNames = $environmentFiles | Where-Object { $_.TenantName -eq $selectedTenantName } | Select-Object -ExpandProperty StageName | Sort-Object -Unique Write-Verbose "$($verbosePrefix)Available stage names for tenant name '$selectedTenantName': $($availableStageNames -join ', ')" $selectedStageName = Read-emsPrompt -Title "Environment file selection" -Question "Please enter the stage name you want to use:" -Options $availableStageNames -DefaultOption $StageName.Value #endregion Stage name selection #region File loading and validation $selectedFile = $environmentFiles | Where-Object { $_.TenantName -eq $selectedTenantName -and $_.StageName -eq $selectedStageName } | Select-Object -First 1 if (!$selectedFile) { throw [System.IO.FileNotFoundException]::new("Environment file for tenant name '$selectedTenantName' and stage name '$selectedStageName' not found.") } $environmentFilePath = $selectedFile.FullName Write-Verbose "$($verbosePrefix)Load environment file '$environmentFilePath' ..." try { $environmentFileContent = Get-Content -Path $environmentFilePath -Raw -Encoding UTF8 -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop } catch [System.ArgumentException] { throw [System.FormatException]::new("Failed to parse JSON content from environment file '$environmentFilePath'. The file contains invalid JSON: $($_.Exception.Message)") } catch { throw [System.IO.IOException]::new("Failed to read environment file '$environmentFilePath': $($_.Exception.Message)") } #endregion File loading and validation #region Create result object Write-Verbose "$($verbosePrefix)>> Environment successfully loaded: $selectedTenantName.$selectedStageName" # Store selected values in reference parameters for backward compatibility $TenantName.Value = $selectedTenantName $StageName.Value = $selectedStageName Write-Output $environmentFileContent #endregion Create result object } catch { $errorRecord = [System.Management.Automation.ErrorRecord]::new( $_.Exception, 'EnvironmentFileLoadFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $environmentFilePath ) $PSCmdlet.ThrowTerminatingError($errorRecord) } } |