Files
NODEDC_MISSION_CORE/deploy/telemetry-plane/telegraf/Install-NdcMissionCoreTelegraf.ps1
T

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
}