Files
FT546-WCS/tools/shadow/Start-Ft546Shadow.ps1

113 lines
4.4 KiB
PowerShell

[CmdletBinding()]
param(
[switch]$ConfirmReadOnlyShadow,
[Parameter(Mandatory = $true)][string]$PreflightJson,
[string]$JavaExecutable = 'java',
[int]$MaximumPreflightAgeMinutes = 30
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
. (Join-Path $PSScriptRoot 'ShadowScriptCommon.ps1')
if (-not $ConfirmReadOnlyShadow.IsPresent) {
throw 'CONFIRM_READ_ONLY_SHADOW_REQUIRED'
}
$preflightPath = Resolve-ShadowFile $PreflightJson
$preflight = Read-ShadowJson $preflightPath
if (-not [bool]$preflight.success) { throw 'SUCCESSFUL_PREFLIGHT_REQUIRED' }
$generatedAt = [DateTime]::Parse($preflight.generatedAtUtc).ToUniversalTime()
if (([DateTime]::UtcNow - $generatedAt).TotalMinutes -gt `
$MaximumPreflightAgeMinutes) {
throw 'PREFLIGHT_EXPIRED'
}
if ($null -eq (Get-Process -Id ([int]$preflight.stable.pid) `
-ErrorAction SilentlyContinue)) {
throw 'STABLE_PROCESS_NOT_HEALTHY'
}
$artifact = Resolve-ShadowFile $preflight.shadowArtifact.path
$config = Resolve-ShadowFile $preflight.config.path
$deployment = Resolve-ShadowDirectory $preflight.deploymentDirectory
if (-not (Test-ShadowPathWithin $artifact $deployment) -or `
-not (Test-ShadowPathWithin $config $deployment)) {
throw 'SHADOW_FILES_MUST_BE_INSIDE_DEPLOYMENT_DIRECTORY'
}
if ((Get-ShadowSha256 $artifact) -ne $preflight.shadowArtifact.sha256) {
throw 'SHADOW_ARTIFACT_CHANGED_AFTER_PREFLIGHT'
}
if ((Get-ShadowSha256 $config) -ne $preflight.config.sha256) {
throw 'SHADOW_CONFIG_CHANGED_AFTER_PREFLIGHT'
}
if ((Get-ShadowSha256 $preflight.permissionReport.path) -ne `
$preflight.permissionReport.sha256) {
throw 'PERMISSION_REPORT_CHANGED_AFTER_PREFLIGHT'
}
if ((Get-ShadowSha256 $preflight.networkDenyReport.path) -ne `
$preflight.networkDenyReport.sha256) {
throw 'NETWORK_DENY_REPORT_CHANGED_AFTER_PREFLIGHT'
}
$pidFile = [IO.Path]::GetFullPath($preflight.pidFile)
if (-not (Test-ShadowPathWithin $pidFile $deployment)) {
throw 'PID_FILE_MUST_BE_INSIDE_DEPLOYMENT_DIRECTORY'
}
if (Test-Path -LiteralPath $pidFile) { throw 'SHADOW_PID_FILE_ALREADY_EXISTS' }
$java = (Get-Command $JavaExecutable -ErrorAction Stop).Source
$logs = Join-Path $deployment 'logs'
New-Item -ItemType Directory -Path $logs -Force | Out-Null
$stdout = Join-Path $logs 'shadow-stdout.log'
$stderr = Join-Path $logs 'shadow-stderr.log'
$configUri = ([uri]$config).AbsoluteUri
$statusUri = [uri]$preflight.statusUri
$runtimeProperties = @(
'--spring.profiles.active=shadow',
'--shadow.enabled=true',
"--spring.config.additional-location=$configUri",
"--server.address=$($statusUri.Host)",
"--server.port=$($statusUri.Port)",
"--shadow.evidence.run.artifact-sha256=$($preflight.shadowArtifact.sha256)",
"--shadow.evidence.run.configuration-sha256=$($preflight.config.sha256)",
"--shadow.evidence.run.source-server=$($preflight.sourceIdentity.server)",
"--shadow.evidence.run.source-database=$($preflight.sourceIdentity.database)",
"--shadow.evidence.minimum-free-bytes=$($preflight.minimumFreeBytes)"
)
$quotedProperties = @($runtimeProperties | ForEach-Object {
'"{0}"' -f $_.Replace('"', '\"')
}) -join ' '
$arguments = '-jar "{0}" {1}' -f $artifact.Replace('"', '\"'), `
$quotedProperties
$process = $null
try {
$process = Start-Process -FilePath $java -ArgumentList $arguments `
-WorkingDirectory $deployment -WindowStyle Hidden -PassThru `
-RedirectStandardOutput $stdout -RedirectStandardError $stderr
Start-Sleep -Milliseconds 300
if ($process.HasExited) {
throw "SHADOW_PROCESS_EXITED_EARLY:$($process.ExitCode)"
}
$record = [pscustomobject]@{
schemaVersion = 1
pid = [int]$process.Id
processStartTimeUtc = $process.StartTime.ToUniversalTime().ToString('o')
javaExecutable = [IO.Path]::GetFullPath($java)
shadowArtifact = $artifact
shadowArtifactSha256 = Get-ShadowSha256 $artifact
config = $config
configSha256 = Get-ShadowSha256 $config
deploymentDirectory = $deployment
preflightJson = $preflightPath
preflightSha256 = Get-ShadowSha256 $preflightPath
startedAtUtc = [DateTime]::UtcNow.ToString('o')
}
Write-ShadowJson -Value $record -Path $pidFile
return $record
}
catch {
if ($null -ne $process -and -not $process.HasExited) {
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
}
throw
}