Skip to content

Commit 8b7bedf

Browse files
authored
Added Promtail to Alloy migration scripts (#20)
1 parent 2eadaa1 commit 8b7bedf

2 files changed

Lines changed: 213 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<#
2+
.DESCRIPTION
3+
Migrates Promtail to Grafana Alloy.
4+
5+
.EXAMPLE
6+
.\Migrate-Promtail-To-Alloy.ps1 -PromtailConfig "C:\ProgramData\Cortex\Observability\Promtail\promtail-local-config.yaml"
7+
8+
.NOTES
9+
Version : 1.0.0.25410
10+
#>
11+
12+
param(
13+
[string]$PromtailConfig
14+
)
15+
16+
Import-Module "$PSScriptRoot\Install-Alloy.psm1"
17+
Import-Module "$PSScriptRoot\Migrate-Promtail-To-Alloy.psm1"
18+
19+
Install-RSAT
20+
21+
Import-Module ActiveDirectory
22+
Set-Location $PSScriptRoot
23+
24+
$ServiceUser = Get-ServiceUser
25+
26+
Set-LocalSecurityPolicy -Username $($ServiceUser.UserName)
27+
Set-RegistryPermissions -Username $($ServiceUser.UserName)
28+
29+
Install-Alloy -ServiceUser $ServiceUser
30+
Wait-ForAlloyReady -ServiceName "Alloy" -TimeoutSeconds 20
31+
Migrate-Promtail-To-Alloy -PromtailConfig $PromtailConfig
32+
33+
Set-BearerToken-OnMigration -Username $($ServiceUser.UserName)
34+
35+
Restart-Alloy
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
<#
2+
.DESCRIPTION
3+
Functions for migrating Promtail to Grafana Alloy.
4+
5+
.NOTES
6+
Version : 1.0.0.25410
7+
#>
8+
9+
function Set-BearerTokenFilePath-OnMigration {
10+
<#
11+
.DESCRIPTION
12+
Update config.alloy file to insert bearer_token_file after the LAST 'url =' line
13+
in the loki.write endpoint block.
14+
#>
15+
16+
process {
17+
Write-Output "Updating config.alloy file with bearer token file path"
18+
19+
$ConfigFile = Join-Path $PSScriptRoot "config.alloy"
20+
$AuthFile = Join-Path $PSScriptRoot "auth.secret"
21+
22+
if (-not (Test-Path -Path $ConfigFile -PathType Leaf)) {
23+
throw "Config file not found: $ConfigFile"
24+
}
25+
if (-not (Test-Path -Path $AuthFile -PathType Leaf)) {
26+
throw "Auth file not found: $AuthFile"
27+
}
28+
29+
$lines = Get-Content -Path $ConfigFile
30+
31+
# Find the index of the last 'url =' line
32+
$urlIndex = ($lines | ForEach-Object { $_ } | Select-String -Pattern '^\s*url\s*=' | Select-Object -Last 1).LineNumber
33+
if (-not $urlIndex) {
34+
throw "No 'url =' line found in $ConfigFile"
35+
}
36+
37+
# Build the new file contents
38+
$bearerPath = $AuthFile -replace '\\', '/'
39+
$newLines = @()
40+
for ($i = 0; $i -lt $lines.Count; $i++) {
41+
$newLines += $lines[$i]
42+
if ($i -eq ($urlIndex - 1)) {
43+
$newLines += " bearer_token_file = `"$bearerPath`""
44+
}
45+
}
46+
47+
Set-Content -Path $ConfigFile -Value $newLines -Force
48+
49+
Write-Output "Updated config.alloy file"
50+
}
51+
}
52+
53+
function Set-BearerToken-OnMigration {
54+
<#
55+
.DESCRIPTION
56+
Create Bearer Token file and restrict access.
57+
58+
.PARAMETER Username
59+
The user name specified for the Grafana Alloy service to run as e.g. "Domain\Username"
60+
#>
61+
62+
param
63+
(
64+
[Parameter(Mandatory = $true)]
65+
[string]
66+
$Username
67+
)
68+
69+
process {
70+
Write-Output "Creating bearer token file"
71+
72+
$AuthFile = (Join-Path $PSScriptRoot "auth.secret")
73+
74+
$BearerToken = Read-Host -Prompt "Enter bearer token used by Loki for authentication" -AsSecureString
75+
76+
New-Item $AuthFile -ItemType File -Value ([pscredential]::new('BearerToken',$BearerToken).GetNetworkCredential().Password) -Force | Out-Null
77+
78+
Write-Output "Created bearer token file"
79+
80+
Set-BearerTokenFilePermissions -AuthFile $AuthFile -Username $Username
81+
82+
Set-BearerTokenFilePath-OnMigration
83+
}
84+
}
85+
86+
function Migrate-Promtail-To-Alloy {
87+
[CmdletBinding()]
88+
param(
89+
[Parameter(Mandatory = $true)]
90+
[string]$PromtailConfig
91+
)
92+
93+
begin {
94+
$exePath = Join-Path $env:ProgramFiles 'GrafanaLabs\Alloy\alloy-windows-amd64.exe'
95+
$outputPath = Join-Path $env:ProgramData 'Cortex\Observability\Grafana Alloy\config.alloy'
96+
$outputDir = Split-Path -Path $outputPath -Parent
97+
$sourceConfig = (Resolve-Path -Path $PromtailConfig -ErrorAction Stop).Path
98+
}
99+
100+
process {
101+
Write-Output "Starting Promtail to Grafana Alloy config migration"
102+
103+
if (-not (Test-Path -Path $exePath -PathType Leaf)) {
104+
throw "Alloy executable not found at '$exePath'. Ensure Alloy is installed before migrating."
105+
}
106+
if (-not (Test-Path -Path $sourceConfig -PathType Leaf)) {
107+
throw "Promtail config not found at '$sourceConfig'."
108+
}
109+
if (-not (Test-Path -Path $outputDir -PathType Container)) {
110+
Write-Output "Creating output directory: $outputDir"
111+
New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
112+
}
113+
114+
try {
115+
& $exePath convert --source-format=promtail --output=$outputPath $sourceConfig
116+
if ($LASTEXITCODE -ne 0) {
117+
throw "Conversion failed with exit code $LASTEXITCODE."
118+
}
119+
}
120+
catch {
121+
throw "Grafana Alloy convert invocation failed: $($_.Exception.Message)"
122+
}
123+
124+
if (-not (Test-Path -Path $outputPath -PathType Leaf)) {
125+
throw "Conversion completed but '$outputPath' was not created."
126+
}
127+
128+
Write-Output "Migrated Promtail to Grafana Alloy config"
129+
}
130+
}
131+
132+
133+
function Restart-Alloy {
134+
[CmdletBinding()]
135+
param(
136+
[string]$ServiceName = 'alloy'
137+
)
138+
process {
139+
Write-Output "Restarting service '$ServiceName'..."
140+
try {
141+
Restart-Service -Name $ServiceName -Force -ErrorAction Stop
142+
Write-Output "Service '$ServiceName' restarted successfully"
143+
}
144+
catch {
145+
throw "Failed to restart service '$ServiceName': $($_.Exception.Message)"
146+
}
147+
}
148+
}
149+
150+
function Wait-ForAlloyReady {
151+
<#
152+
.SYNOPSIS
153+
Waits until the Alloy service is running.
154+
.PARAMETER ServiceName
155+
Name of the Alloy Windows service. Defaults to 'alloy'.
156+
.PARAMETER TimeoutSeconds
157+
Maximum number of seconds to wait. Defaults to 60.
158+
#>
159+
[CmdletBinding()]
160+
param(
161+
[string]$ServiceName = 'alloy',
162+
[int]$TimeoutSeconds = 60
163+
)
164+
165+
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
166+
while ($stopwatch.Elapsed.TotalSeconds -lt $TimeoutSeconds) {
167+
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
168+
169+
if ($service -and $service.Status -eq 'Running') {
170+
Write-Output "Alloy service is running."
171+
return
172+
}
173+
174+
Start-Sleep -Seconds 1
175+
}
176+
177+
throw "Timeout: Alloy service '$ServiceName' not running after $TimeoutSeconds seconds."
178+
}

0 commit comments

Comments
 (0)