162 lines
7.1 KiB
PowerShell
162 lines
7.1 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[string]$Version = "1.38.4",
|
|
[string]$ExpectedSha256 = "6c7878ec319471ac85b82443baec2f3fa5dbcf1b6e2da5d5cd2cbb60fff2bb45",
|
|
[string]$ConfigurationTemplate = "$PSScriptRoot\mission-core-windows.conf.tmpl",
|
|
[string]$PipelineCollector = "$PSScriptRoot\Get-NdcMissionCorePipelineTelemetry.ps1",
|
|
[string]$PipelineJournal = "D:\NDC_MISSIONCORE\runtime\derived\.perception-persistent-publish\pipeline-telemetry.jsonl"
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$serviceName = "telegraf"
|
|
$installRoot = "C:\Program Files\NDC\Mission Core\Telegraf"
|
|
$configurationRoot = "C:\ProgramData\NDC\MissionCore\telemetry-agent"
|
|
$configurationPath = Join-Path $configurationRoot "telegraf.conf"
|
|
$collectorPath = Join-Path $configurationRoot "Get-NdcMissionCorePipelineTelemetry.ps1"
|
|
$archiveUrl = "https://dl.influxdata.com/telegraf/releases/telegraf-$($Version)_windows_amd64.zip"
|
|
$payload = [Console]::In.ReadToEnd() | ConvertFrom-Json
|
|
|
|
foreach ($name in @(
|
|
"MISSIONCORE_CONTOUR_ID",
|
|
"MISSIONCORE_AGENT_ID",
|
|
"MISSIONCORE_NODE_ID",
|
|
"MISSIONCORE_MQTT_HOST",
|
|
"MISSIONCORE_MQTT_PORT",
|
|
"MISSIONCORE_MQTT_USERNAME",
|
|
"MISSIONCORE_MQTT_PASSWORD",
|
|
"MISSIONCORE_TELEMETRY_INTERVAL"
|
|
)) {
|
|
$value = $payload.$name
|
|
if (-not $value) {
|
|
throw "Provisioning payload is missing $name"
|
|
}
|
|
Set-Item -Path "Env:$name" -Value ([string]$value)
|
|
}
|
|
|
|
if (Get-Service -Name $serviceName -ErrorAction SilentlyContinue) {
|
|
throw "Service '$serviceName' already exists; refusing an implicit replacement"
|
|
}
|
|
if (-not (Test-Path -LiteralPath $ConfigurationTemplate -PathType Leaf)) {
|
|
throw "Configuration template not found: $ConfigurationTemplate"
|
|
}
|
|
if (-not (Test-Path -LiteralPath $PipelineCollector -PathType Leaf)) {
|
|
throw "Pipeline collector not found: $PipelineCollector"
|
|
}
|
|
$journalParent = Get-Item -LiteralPath (
|
|
Resolve-Path -LiteralPath (Split-Path $PipelineJournal -Parent)
|
|
).Path -Force
|
|
if (
|
|
-not $journalParent.PSIsContainer -or
|
|
($journalParent.Attributes -band [IO.FileAttributes]::ReparsePoint) -or
|
|
[IO.Path]::GetPathRoot($journalParent.FullName).TrimEnd("\") -ine "D:"
|
|
) {
|
|
throw "Pipeline journal parent must be a real D: directory"
|
|
}
|
|
if (-not (Test-Path -LiteralPath $PipelineJournal)) {
|
|
New-Item -ItemType File -Path $PipelineJournal | Out-Null
|
|
}
|
|
$journal = Get-Item -LiteralPath $PipelineJournal -Force
|
|
if (
|
|
$journal.PSIsContainer -or
|
|
($journal.Attributes -band [IO.FileAttributes]::ReparsePoint)
|
|
) {
|
|
throw "Pipeline journal must be a regular file"
|
|
}
|
|
|
|
$temporaryRoot = Join-Path $env:TEMP "ndc-mission-core-telegraf-$([Guid]::NewGuid().ToString('N'))"
|
|
$archivePath = Join-Path $temporaryRoot "telegraf.zip"
|
|
$expandedRoot = Join-Path $temporaryRoot "expanded"
|
|
try {
|
|
New-Item -ItemType Directory -Path $temporaryRoot, $expandedRoot -Force | Out-Null
|
|
Invoke-WebRequest -UseBasicParsing -Uri $archiveUrl -OutFile $archivePath
|
|
$actualSha256 = (Get-FileHash -LiteralPath $archivePath -Algorithm SHA256).Hash.ToLowerInvariant()
|
|
if ($actualSha256 -ne $ExpectedSha256.ToLowerInvariant()) {
|
|
throw "Telegraf archive SHA256 mismatch"
|
|
}
|
|
Expand-Archive -LiteralPath $archivePath -DestinationPath $expandedRoot
|
|
$sourceExecutable = Get-ChildItem -Path $expandedRoot -Filter "telegraf.exe" -Recurse |
|
|
Select-Object -First 1
|
|
if (-not $sourceExecutable) {
|
|
throw "telegraf.exe is missing from the verified archive"
|
|
}
|
|
|
|
New-Item -ItemType Directory -Path $installRoot, $configurationRoot -Force | Out-Null
|
|
Copy-Item -LiteralPath $sourceExecutable.FullName -Destination (Join-Path $installRoot "telegraf.exe")
|
|
Copy-Item -LiteralPath $ConfigurationTemplate -Destination $configurationPath
|
|
Copy-Item -LiteralPath $PipelineCollector -Destination $collectorPath
|
|
& icacls.exe $configurationRoot /inheritance:r /grant:r `
|
|
"*S-1-5-18:(OI)(CI)F" "*S-1-5-32-544:(OI)(CI)F" | Out-Null
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Failed to restrict the telemetry agent configuration directory"
|
|
}
|
|
|
|
$executable = Join-Path $installRoot "telegraf.exe"
|
|
$validationOutput = Join-Path $temporaryRoot "validation.out.log"
|
|
$validationError = Join-Path $temporaryRoot "validation.error.log"
|
|
$validation = Start-Process -FilePath $executable `
|
|
-ArgumentList @("--config", $configurationPath, "--test") `
|
|
-NoNewWindow -Wait -PassThru `
|
|
-RedirectStandardOutput $validationOutput `
|
|
-RedirectStandardError $validationError
|
|
if ($validation.ExitCode -ne 0) {
|
|
$validationDetail = Get-Content -LiteralPath $validationError -Tail 8 |
|
|
Out-String
|
|
throw "Telegraf configuration validation failed: $validationDetail"
|
|
}
|
|
|
|
& $executable --service install --config $configurationPath
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Telegraf service installation failed"
|
|
}
|
|
$serviceEnvironment = @(
|
|
"MISSIONCORE_CONTOUR_ID=$($payload.MISSIONCORE_CONTOUR_ID)",
|
|
"MISSIONCORE_AGENT_ID=$($payload.MISSIONCORE_AGENT_ID)",
|
|
"MISSIONCORE_NODE_ID=$($payload.MISSIONCORE_NODE_ID)",
|
|
"MISSIONCORE_MQTT_HOST=$($payload.MISSIONCORE_MQTT_HOST)",
|
|
"MISSIONCORE_MQTT_PORT=$($payload.MISSIONCORE_MQTT_PORT)",
|
|
"MISSIONCORE_MQTT_USERNAME=$($payload.MISSIONCORE_MQTT_USERNAME)",
|
|
"MISSIONCORE_MQTT_PASSWORD=$($payload.MISSIONCORE_MQTT_PASSWORD)",
|
|
"MISSIONCORE_TELEMETRY_INTERVAL=$($payload.MISSIONCORE_TELEMETRY_INTERVAL)"
|
|
)
|
|
$serviceRegistryPath = "HKLM:\SYSTEM\CurrentControlSet\Services\$serviceName"
|
|
Set-ItemProperty -Path $serviceRegistryPath -Name Environment `
|
|
-Type MultiString -Value $serviceEnvironment
|
|
Set-ItemProperty -Path $serviceRegistryPath -Name DisplayName `
|
|
-Value "NDC Mission Core Telemetry Agent"
|
|
& sc.exe config $serviceName DisplayName= "NDC Mission Core Telemetry Agent" | Out-Null
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Failed to apply the NDC service display name"
|
|
}
|
|
Set-Service -Name $serviceName -StartupType Automatic
|
|
& sc.exe failure $serviceName reset= 86400 `
|
|
actions= restart/5000/restart/30000/restart/60000 | Out-Null
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Failed to configure Telegraf service recovery actions"
|
|
}
|
|
& sc.exe failureflag $serviceName 1 | Out-Null
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Failed to enable Telegraf recovery for non-crash failures"
|
|
}
|
|
Start-Service -Name $serviceName
|
|
$service = Get-Service -Name $serviceName
|
|
$service.WaitForStatus([ServiceProcess.ServiceControllerStatus]::Running, [TimeSpan]::FromSeconds(20))
|
|
|
|
[ordered]@{
|
|
SchemaVersion = "missioncore.telemetry-agent-install-result/v1"
|
|
Agent = "Telegraf"
|
|
Version = $Version
|
|
ServiceName = $service.Name
|
|
DisplayName = $service.DisplayName
|
|
Status = $service.Status.ToString()
|
|
StartType = $service.StartType.ToString()
|
|
RecoveryConfigured = $true
|
|
Configuration = $configurationPath
|
|
PipelineCollector = $collectorPath
|
|
PipelineJournal = $PipelineJournal
|
|
Sha256 = $actualSha256
|
|
} | ConvertTo-Json -Compress
|
|
}
|
|
finally {
|
|
Remove-Item -LiteralPath $temporaryRoot -Recurse -Force -ErrorAction SilentlyContinue
|
|
}
|