Tools/Invoke-VcfCheckLauncher.ps1
|
# Copyright (c) 2026 Broadcom. All Rights Reserved. # Broadcom Confidential. The term "Broadcom" refers to Broadcom Inc. # and/or its subsidiaries. # # ============================================================================= # # SOFTWARE LICENSE AGREEMENT # # Copyright (c) CA, Inc. All rights reserved. # # You are hereby granted a non-exclusive, worldwide, royalty-free license # under CA, Inc.'s copyrights to use, copy, modify, and distribute this # software in source code or binary form for use in connection with CA, Inc. # products. # # This copyright notice shall be included in all copies or substantial # portions of the software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # # ============================================================================= <# .SYNOPSIS Command-line entry point for executing the VcfCheck module. .DESCRIPTION Accepts execution parameters via command-line arguments and reads SDDC Manager credential secrets directly from process environment variables (`VCFCHECK_SDDC_PASSWORD` and `VCFCHECK_ROOT_PASSWORD`). Converts plaintext credentials to SecureString objects, executes prechecks via `Invoke-VcfCheck`, and securely disposes of sensitive variables in memory upon completion. Exit codes: - 0: Precheck completed with no blocking failures. - 1: Precheck completed with one or more blocking failures. - 2: Precheck execution terminated unexpectedly due to an unhandled exception. .PARAMETER SddcManagerFqdn Fully qualified domain name of the SDDC Manager appliance. Forwarded to `Invoke-VcfCheck`. .PARAMETER SddcManagerUser Username for SDDC Manager authentication. Forwarded to `Invoke-VcfCheck`. .PARAMETER CheckId Comma-separated string of check IDs to execute. Defined as a single string to ensure consistent command-line argument binding across subprocess invocations. .PARAMETER Domain Optional comma-separated string of VCF workload domain names to scope execution. .PARAMETER RunId Optional unique execution run identifier. Forwarded to `Invoke-VcfCheck`. .PARAMETER EnvironmentName Optional human-readable environment name used for report generation. .PARAMETER OutputPath Directory path where precheck report artifacts are written. Defaults to `$env:VcfCheckBaseDirectory\Findings`. .PARAMETER ConnectivityTimeoutSeconds Timeout duration in seconds for REST and network connectivity checks. Defaults to 30 seconds. .PARAMETER VcfDestinationRelease Target VCF release version, release family (e.g., '9.1.0'), or 'latest'. .PARAMETER HealthSummaryMaxPollAttempts Forwarded to Invoke-VcfCheck's own -HealthSummaryMaxPollAttempts. 0 (default) leaves the 'SDDC Manager Health Summary' check on its own built-in poll budget. .PARAMETER PreUpgradeCheckSetMaxPollAttempts Forwarded to Invoke-VcfCheck's own -PreUpgradeCheckSetMaxPollAttempts. 0 (default) leaves the 'SDDC Manager Pre-Upgrade Check-Set Assessment' check on its own built-in poll budget. .NOTES Serves as the launcher contract between external execution callers and the VcfCheck module. .EXAMPLE pwsh -NoProfile -NonInteractive -File Invoke-VcfCheckLauncher.ps1 -SddcManagerFqdn sddc.example.com -SddcManagerUser administrator@vsphere.local -CheckId "sddc_bom_check,sddc_check_failed_tasks" #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$SddcManagerFqdn, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$SddcManagerUser, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$CheckId, [Parameter(Mandatory = $false)] [AllowEmptyString()] [String]$Domain = '', [Parameter(Mandatory = $false)] [AllowEmptyString()] [String]$RunId = '', [Parameter(Mandatory = $false)] [AllowEmptyString()] [String]$EnvironmentName = '', [Parameter(Mandatory = $false)] [AllowEmptyString()] [String]$OutputPath = '', [Parameter(Mandatory = $false)] [Int]$ConnectivityTimeoutSeconds = 30, [Parameter(Mandatory = $false)] [AllowEmptyString()] [String]$VcfDestinationRelease = '', [Parameter(Mandatory = $false)] [Int]$HealthSummaryMaxPollAttempts = 0, [Parameter(Mandatory = $false)] [Int]$PreUpgradeCheckSetMaxPollAttempts = 0 ) $checkIds = @($CheckId -split ',' | Where-Object { -not [String]::IsNullOrWhiteSpace($_) } | ForEach-Object { $_.Trim() }) if ($checkIds.Count -eq 0) { Write-Host 'ERROR: -CheckId did not contain any non-empty check ids after splitting on commas.' -ForegroundColor Red exit 1 } $domains = @($Domain -split ',' | Where-Object { -not [String]::IsNullOrWhiteSpace($_) } | ForEach-Object { $_.Trim() }) # Suppress PSStyle ANSI escape codes so captured output remains plain text. if ($null -ne $PSStyle) { $PSStyle.OutputRendering = 'PlainText' } if ([String]::IsNullOrWhiteSpace($env:VcfCheckBaseDirectory) -and [String]::IsNullOrWhiteSpace($OutputPath)) { Write-Host 'ERROR: VcfCheckBaseDirectory is not set and -OutputPath was not provided. Run Initialize-VcfCheck first.' -ForegroundColor Red exit 1 } # Resolve module manifest location via environment override or relative path fallback. $envModulePsd1 = ([String]$env:VCFCHECK_MODULE_PSD1).Trim() if (-not [String]::IsNullOrWhiteSpace($envModulePsd1) -and (Test-Path -LiteralPath $envModulePsd1 -PathType Leaf)) { $modulePath = $envModulePsd1 } else { $modulePath = Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -ChildPath 'VcfCheck.psd1' } try { Import-Module -Name $modulePath -Force -ErrorAction Stop } catch { Write-Host "ERROR: Could not load the VcfCheck module from `"$modulePath`": $($_.Exception.Message)" -ForegroundColor Red exit 1 } $sddcPasswordPlainText = $env:VCFCHECK_SDDC_PASSWORD if ([String]::IsNullOrEmpty($sddcPasswordPlainText)) { Write-Host 'ERROR: VCFCHECK_SDDC_PASSWORD environment variable was not set.' -ForegroundColor Red exit 1 } $sddcPassword = $null $rootPassword = $null $ariaOpsEndpointCredentials = @() try { $sddcPassword = ConvertTo-SecureString -String $sddcPasswordPlainText -AsPlainText -Force $rootPasswordPlainText = $env:VCFCHECK_ROOT_PASSWORD if (-not [String]::IsNullOrEmpty($rootPasswordPlainText)) { $rootPassword = ConvertTo-SecureString -String $rootPasswordPlainText -AsPlainText -Force } # Standalone Aria Operations endpoint passwords (Environment.Integrations), collected # session-only by the browser - see Tools/Start-VcfCheckServer.py's _resolve_aria_ops_credentials. $ariaOpsCredentialsJson = $env:VCFCHECK_ARIAOPS_CREDENTIALS_JSON if (-not [String]::IsNullOrEmpty($ariaOpsCredentialsJson)) { try { $ariaOpsEndpointCredentials = @(ConvertFrom-Json -InputObject $ariaOpsCredentialsJson -ErrorAction Stop | ForEach-Object { [PSCustomObject]@{ Fqdn = $_.Fqdn; Password = (ConvertTo-SecureString -String $_.Password -AsPlainText -Force) } }) } catch { Write-LogMessage -Type WARNING -Message "Could not parse VCFCHECK_ARIAOPS_CREDENTIALS_JSON: $($_.Exception.Message)" $ariaOpsEndpointCredentials = @() } } $invokeParams = @{ SddcManagerFqdn = $SddcManagerFqdn SddcManagerUser = $SddcManagerUser SddcManagerPassword = $sddcPassword CheckId = $checkIds ConnectivityTimeoutSeconds = $ConnectivityTimeoutSeconds } if ($rootPassword) { $invokeParams['SddcManagerRootPassword'] = $rootPassword } if ($domains.Count -gt 0) { $invokeParams['Domain'] = $domains } if (-not [String]::IsNullOrWhiteSpace($OutputPath)) { $invokeParams['OutputPath'] = $OutputPath } if (-not [String]::IsNullOrWhiteSpace($RunId)) { $invokeParams['RunId'] = $RunId } if (-not [String]::IsNullOrWhiteSpace($EnvironmentName)) { $invokeParams['EnvironmentName'] = $EnvironmentName } if (-not [String]::IsNullOrWhiteSpace($VcfDestinationRelease)) { $invokeParams['VcfDestinationRelease'] = $VcfDestinationRelease } if ($HealthSummaryMaxPollAttempts -gt 0) { $invokeParams['HealthSummaryMaxPollAttempts'] = $HealthSummaryMaxPollAttempts } if ($PreUpgradeCheckSetMaxPollAttempts -gt 0) { $invokeParams['PreUpgradeCheckSetMaxPollAttempts'] = $PreUpgradeCheckSetMaxPollAttempts } if ($ariaOpsEndpointCredentials.Count -gt 0) { $invokeParams['AriaOpsEndpointCredentials'] = $ariaOpsEndpointCredentials } $results = Invoke-VcfCheck @invokeParams $hasBlockingFailure = @($results | Where-Object { $_.Blocking -and $_.Status -in @('Fail', 'Error') }).Count -gt 0 exit ([Int]$hasBlockingFailure) } catch { # Log terminating execution errors and exit with code 2. Write-LogMessage -Type ERROR -Message "Run terminated unexpectedly: $($_.Exception.Message)" exit 2 } finally { $sddcPasswordPlainText = $null $env:VCFCHECK_ARIAOPS_CREDENTIALS_JSON = $null Remove-Variable -Name sddcPasswordPlainText, rootPasswordPlainText, sddcPassword, rootPassword, ariaOpsCredentialsJson, ariaOpsEndpointCredentials -ErrorAction SilentlyContinue [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers() } |