Private/Configuration.ps1
|
<# This is the first function called in the connector workflow. At this stage, the logger is not initialized yet, so this function must not rely on `Write-CustomLog` (or any logging target setup). It should fail fast with clear exceptions when configuration is missing or invalid. #> function Get-Configuration { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$ScriptRootPath, [Parameter(Mandatory = $true)] [string]$vSphereEnvironment ) $configPath = Join-Path -Path $ScriptRootPath -ChildPath (Join-Path -Path "Config" -ChildPath "config.json") if (-not (Test-Path -Path $configPath)) { throw "Configuration file not found at: $configPath" } $raw = Get-Content -Path $configPath -Raw -ErrorAction Stop if ([string]::IsNullOrWhiteSpace($raw)) { throw "Invalid configuration: configuration file is empty. Path: $configPath" } try { $config = $raw | ConvertFrom-Json -ErrorAction Stop } catch { throw "Invalid configuration: configuration file is not valid JSON. Path: $configPath. Error: $($_.Exception.Message)" } if ($null -eq $config) { throw "Invalid configuration: config object is null. Path: $configPath" } # Fail fast on required high-level structure so later environment selection doesn't produce misleading errors. if ($null -eq $config.vSphereEnvironments -or -not ($config.vSphereEnvironments -is [System.Array])) { throw "Invalid configuration: 'vSphereEnvironments' is required and must be an array." } if ($config.vSphereEnvironments.Count -eq 0) { throw "Invalid configuration: 'vSphereEnvironments' must not be empty." } $envConfig = $config.vSphereEnvironments | Where-Object { $_.Name -eq $vSphereEnvironment } if ($null -eq $envConfig) { throw "Environment '$vSphereEnvironment' not found in configuration" } Validate-Configuration -Config $config -EnvironmentConfig $envConfig $typedEnvConfig = [VSphereEnvironmentConfiguration]::new() $typedEnvConfig.Name = $envConfig.Name $typedEnvConfig.vCenterFQDN = $envConfig.vCenterFQDN $typedEnvConfig.WindowsCredentialEntry = $envConfig.WindowsCredentialEntry $typedNexthinkApi = [VSphereNexthinkApiConfiguration]::new() $typedNexthinkApi.HostFQDN = $config.NexthinkAPI.HostFQDN $typedNexthinkApi.LoginFQDN = $config.NexthinkAPI.LoginFQDN $typedNexthinkApi.WindowsCredentialEntry = $config.NexthinkAPI.WindowsCredentialEntry $typedNexthinkApi.RequestBatchSize = $config.NexthinkAPI.RequestBatchSize $typedLogging = $null if ($null -ne $config.Logging) { $typedLogging = [VSphereLoggingConfiguration]::new() $typedLogging.LogLevel = $config.Logging.LogLevel $typedLogging.LogRetentionDays = $config.Logging.LogRetentionDays } $cfg = [VSphereConnectorConfiguration]::new() $cfg.ScriptRootPath = $ScriptRootPath $cfg.EnvironmentConfig = $typedEnvConfig $cfg.NexthinkAPI = $typedNexthinkApi $cfg.Logging = $typedLogging return $cfg } function Validate-Configuration { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [AllowNull()] [object]$Config, [Parameter(Mandatory = $true)] [object]$EnvironmentConfig ) function Throw-ConfigError { param([string]$Message) Write-Error -Message $Message throw $Message } function Assert-NonEmptyString { param( [string]$Value, [string]$FieldName ) if ([string]::IsNullOrWhiteSpace($Value)) { Throw-ConfigError "Invalid configuration: '$FieldName' is required and must be a non-empty string." } } Write-CustomLog -Message "Validating configuration..." -Severity 'DEBUG' if ($null -eq $Config) { Throw-ConfigError "Invalid configuration: config object is null." } if ($null -eq $Config.vSphereEnvironments -or -not ($Config.vSphereEnvironments -is [System.Array])) { Throw-ConfigError "Invalid configuration: 'vSphereEnvironments' is required and must be an array." } if ($Config.vSphereEnvironments.Count -eq 0) { Throw-ConfigError "Invalid configuration: 'vSphereEnvironments' must not be empty." } if ($null -eq $Config.NexthinkAPI) { Throw-ConfigError "Invalid configuration: 'NexthinkAPI' section is required." } # Validate selected environment config Assert-NonEmptyString -Value $EnvironmentConfig.Name -FieldName 'vSphereEnvironments[].Name' Assert-NonEmptyString -Value $EnvironmentConfig.vCenterFQDN -FieldName 'vSphereEnvironments[].vCenterFQDN' Assert-NonEmptyString -Value $EnvironmentConfig.WindowsCredentialEntry -FieldName 'vSphereEnvironments[].WindowsCredentialEntry' # Validate Nexthink API settings (fail fast, even if not used yet by metrics) Assert-NonEmptyString -Value $Config.NexthinkAPI.HostFQDN -FieldName 'NexthinkAPI.HostFQDN' Assert-NonEmptyString -Value $Config.NexthinkAPI.LoginFQDN -FieldName 'NexthinkAPI.LoginFQDN' Assert-NonEmptyString -Value $Config.NexthinkAPI.WindowsCredentialEntry -FieldName 'NexthinkAPI.WindowsCredentialEntry' $batchSizeRaw = $Config.NexthinkAPI.RequestBatchSize if ($null -eq $batchSizeRaw -or [string]::IsNullOrWhiteSpace([string]$batchSizeRaw)) { Throw-ConfigError "Invalid configuration: 'NexthinkAPI.RequestBatchSize' is required and must be a positive integer." } $batchSize = 0 if (-not [int]::TryParse([string]$batchSizeRaw, [ref]$batchSize) -or $batchSize -le 0) { Throw-ConfigError "Invalid configuration: 'NexthinkAPI.RequestBatchSize' must be a positive integer. Value: '$batchSizeRaw'" } # Normalize type (config.json currently stores it as a string) $Config.NexthinkAPI.RequestBatchSize = $batchSize # Optional logging settings validation if ($null -ne $Config.Logging) { if ($null -ne $Config.Logging.LogLevel -and -not [string]::IsNullOrWhiteSpace([string]$Config.Logging.LogLevel)) { $allowed = @('DEBUG', 'INFO', 'WARNING', 'ERROR') if ($allowed -notcontains ([string]$Config.Logging.LogLevel).ToUpperInvariant()) { Throw-ConfigError "Invalid configuration: 'Logging.LogLevel' must be one of: $($allowed -join ', '). Value: '$($Config.Logging.LogLevel)'" } } if ($null -ne $Config.Logging.LogRetentionDays -and -not [string]::IsNullOrWhiteSpace([string]$Config.Logging.LogRetentionDays)) { $retention = 0 if (-not [int]::TryParse([string]$Config.Logging.LogRetentionDays, [ref]$retention) -or $retention -le 0) { Throw-ConfigError "Invalid configuration: 'Logging.LogRetentionDays' must be a positive integer. Value: '$($Config.Logging.LogRetentionDays)'" } $Config.Logging.LogRetentionDays = $retention } } Write-CustomLog -Message "Configuration validated successfully." -Severity 'DEBUG' } |