Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ To install into a custom directory:
$env:RUNTIME = 'docker'; $env:TOKEN = 'YOUR_AGENT_TOKEN'; & .\install.ps1 -InstallDir C:\path\to\dir
```

The installer detects the Docker container mode. Linux-container mode, including Windows 10/11 with Docker Desktop and WSL2, uses the explicit Ubuntu image tag `<version>-ubuntu-26.04`. Existing Linux installations that pin the legacy numeric tag `<version>` continue to work and are upgraded using the explicit Ubuntu tag. Windows-container mode detects the Windows Server LTSC version and selects the matching image tag. To override detection for a host known to support a specific Windows image, pass `-WindowsVersion ltsc2019`, `-WindowsVersion ltsc2022`, or `-WindowsVersion ltsc2025`.
The installer pins the plain agent version (for example `1.2.9`) in the `version` file, and the management script appends the image tag suffix for the Docker container mode when it starts the container. Linux-container mode, including Windows 10/11 with Docker Desktop and WSL2, uses the Ubuntu image tag `<version>-ubuntu-26.04`. Windows-container mode detects the Windows Server LTSC version and selects the matching `<version>-windows-<ltsc>` image tag. Existing installations whose `version` file contains a full image tag keep working; the file is rewritten to the plain version on the next `start` or `upgrade`. To override detection for a host known to support a specific Windows image, pass `-WindowsVersion ltsc2019`, `-WindowsVersion ltsc2022`, or `-WindowsVersion ltsc2025`.

Windows Server hosts use an exact LTSC mapping: Server 2019 selects `ltsc2019`, Server 2022 selects `ltsc2022`, and Server 2025 selects `ltsc2025`. The `-WindowsVersion` option is an operator-controlled override and does not validate host/image compatibility; confirm the supported Windows container version and required isolation mode before using it.
Windows Server hosts use an exact LTSC mapping: Server 2019 selects `ltsc2019`, Server 2022 selects `ltsc2022`, and Server 2025 selects `ltsc2025`. The `-WindowsVersion` option is an operator-controlled override and does not validate host/image compatibility; confirm the supported Windows container version and required isolation mode before using it. The override is saved as `$WINDOWS_VERSION` in `settings.ps1`, so `upgrade` keeps using it.

Linux releases continue to use `proxy-agent:<version>` for backward compatibility and are also published as `proxy-agent:<version>-ubuntu-26.04`. Both tags reference the same Linux multi-architecture image. Windows releases use the explicit `proxy-agent:<version>-windows-ltsc2019`, `proxy-agent:<version>-windows-ltsc2022`, or `proxy-agent:<version>-windows-ltsc2025` tags.

Expand All @@ -84,15 +84,15 @@ $HOME/fivetran-proxy-agent/
├── config/
│ └── config.json --> Agent configuration (permissions: 600)
├── logs/ --> Agent and manager logs
└── version --> Pinned agent image tag
└── version --> Pinned agent version (for example 1.2.9)

# Windows
%USERPROFILE%\fivetran-proxy-agent\
├── proxy-agent-manager.ps1 --> Management script
├── config\
│ └── config.json --> Agent configuration (owner read/write; SYSTEM and Administrators read)
├── logs\ --> Agent and manager logs
└── version --> Pinned agent image tag
└── version --> Pinned agent version (for example 1.2.9)
```

## Managing the agent
Expand Down
14 changes: 10 additions & 4 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ param(

$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
if ($WindowsVersion) { $WindowsVersion = $WindowsVersion.ToLowerInvariant() }

# ── Constants ────────────────────────────────────────────────────────────────

Expand Down Expand Up @@ -240,7 +241,7 @@ function Get-LatestVersion {
exit 1
}

return ($versions | Sort-Object { [version]($_ -replace $releasePattern, '') } | Select-Object -Last 1)
return ($versions | ForEach-Object { $_ -replace $releasePattern, '' } | Sort-Object { [version]$_ } | Select-Object -Last 1)
}

function Get-LatestLinuxVersion {
Expand All @@ -259,7 +260,7 @@ function Get-LatestLinuxVersion {
exit 1
}

return ($versions | Sort-Object { [version]($_ -replace $releasePattern, '') } | Select-Object -Last 1)
return ($versions | ForEach-Object { $_ -replace $releasePattern, '' } | Sort-Object { [version]$_ } | Select-Object -Last 1)
}

# ── Entry point ──────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -373,8 +374,13 @@ try {
$null = New-Item -ItemType Directory -Force -Path (Join-Path $InstallDir 'config')
$null = New-Item -ItemType Directory -Force -Path (Join-Path $InstallDir 'logs')

# Persist chosen container memory for proxy-agent-manager.ps1 to read
Set-Content -LiteralPath (Join-Path $InstallDir $SETTINGS_FILE) -Value "`$MEMORY_ALLOCATION_MB = $memoryMB" -Encoding ascii
# Persist settings for proxy-agent-manager.ps1 to read: the container memory
# and, when given, the Windows image variant override.
$settings = @("`$MEMORY_ALLOCATION_MB = $memoryMB")
if ($WindowsVersion) {
$settings += "`$WINDOWS_VERSION = '$WindowsVersion'"
Comment thread
fivetran-paulharper marked this conversation as resolved.
Resolved
}
Set-Content -LiteralPath (Join-Path $InstallDir $SETTINGS_FILE) -Value $settings -Encoding ascii

# Download management script from public repo (temp file → move for atomicity)
Write-Host "Downloading management script..."
Expand Down
2 changes: 1 addition & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ get_latest_version() {
local version
version=$(echo "$tags_json" \
| grep -oE '"[0-9]+\.[0-9]+\.[0-9]+-ubuntu-26\.04"' \
| tr -d '"' \
| grep -oE '[0-9]+\.[0-9]+\.[0-9]+' \
| sort -V \
| tail -1 \
|| true)
Expand Down
169 changes: 82 additions & 87 deletions proxy-agent-manager.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ $VERSION_FILE = Join-Path $BASE_DIR 'version'
$LOGFILE = Join-Path $BASE_DIR 'logs\proxy-agent-manager.log'
$CONTAINER_LOG_DIR = '/app/logs'
$SETTINGS_FILE = Join-Path $BASE_DIR 'settings.ps1'
# Appended to the plain agent version to form the Linux image tag.
$LINUX_IMAGE_TAG_SUFFIX = '-ubuntu-26.04'

# settings.ps1 may set $MEMORY_ALLOCATION_MB and, for Windows containers,
# $WINDOWS_VERSION (an LTSC variant that overrides host detection).
if (Test-Path -LiteralPath $SETTINGS_FILE) {
. $SETTINGS_FILE
}
# Unset or empty only, so 0 is rejected like any other invalid setting.
if ("$MEMORY_ALLOCATION_MB" -eq '') { $MEMORY_ALLOCATION_MB = 5120 }
if (-not $WINDOWS_VERSION) { $WINDOWS_VERSION = $null }

# ── Startup validation ───────────────────────────────────────────────────────

Expand Down Expand Up @@ -55,8 +60,8 @@ if (-not (Test-Path $VERSION_FILE)) {
exit 1
}

$CURRENT_VERSION = (Get-Content $VERSION_FILE -Raw).Trim()
if (-not $CURRENT_VERSION) {
$PINNED_VERSION = (Get-Content $VERSION_FILE -Raw).Trim()
if (-not $PINNED_VERSION) {
Write-Host "ERROR: $VERSION_FILE is empty." -ForegroundColor Red
exit 1
}
Expand Down Expand Up @@ -105,65 +110,71 @@ function Get-WindowsLtscVersion {
throw "Unsupported Windows Server build '$($operatingSystem.BuildNumber)' ('$($operatingSystem.Caption)')."
}

function Get-ImageTagType {
# Returns the plain agent version for a version file entry. Accepts a plain
# version (1.2.9) or a legacy image tag (1.2.9-ubuntu-26.04, 1.2.9-windows-ltsc2022).
function Get-ReleaseVersion {
param([Parameter(Mandatory)][string]$Tag)

if ($Tag -match '^\d+\.\d+\.\d+-windows-(?:ltsc2019|ltsc2022|ltsc2025)$') {
return 'windows'
}
if ($Tag -match '^\d+\.\d+\.\d+-ubuntu-26\.04$') {
return 'linux'
}
if ($Tag -match '^\d+\.\d+\.\d+$') {
return 'legacy-linux'
if ($Tag -match '^(?<version>\d+\.\d+\.\d+)(?:-ubuntu-26\.04|-windows-(?:ltsc2019|ltsc2022|ltsc2025))?$') {
return $Matches.version
}

throw "Invalid proxy-agent image tag '$Tag'."
throw "Invalid proxy agent version '$Tag' in $VERSION_FILE. Expected <major>.<minor>.<patch>."
}

function Get-ImageTagVariant {
param([Parameter(Mandatory)][string]$Tag)
# Returns the LTSC variant to use for Windows containers, or $null for Linux
# containers. A variant pinned by a legacy Windows image tag in the version file
# wins and is saved to settings.ps1, then the $WINDOWS_VERSION setting, then the
# variant detected from the host.
function Resolve-WindowsVersion {
param([Parameter(Mandatory)][ValidateSet('linux', 'windows')][string]$ContainerOsType)

if ($Tag -match '^\d+\.\d+\.\d+-windows-(?<variant>ltsc2019|ltsc2022|ltsc2025)$') {
return $Matches.variant
$pinnedWindowsVariant = $null
if ($PINNED_VERSION -match '-windows-(?<variant>ltsc2019|ltsc2022|ltsc2025)$') {
$pinnedWindowsVariant = $Matches.variant
}

throw "Invalid Windows proxy-agent image tag '$Tag'. Expected <version>-windows-ltsc2019, <version>-windows-ltsc2022, or <version>-windows-ltsc2025."
}

function Resolve-ImageTag {
param(
[Parameter(Mandatory)][string]$Tag,
[Parameter(Mandatory)][ValidateSet('linux', 'windows')][string]$ContainerOsType
)

$tagType = Get-ImageTagType -Tag $Tag

if ($Tag -match '^\d+\.\d+\.\d+$') {
if ($ContainerOsType -eq 'windows') {
return "$Tag-windows-$(Get-WindowsLtscVersion)"
if ($ContainerOsType -ne 'windows') {
if ($pinnedWindowsVariant) {
throw "Windows proxy-agent image tags require Docker to run Windows containers."
}
return $Tag
return $null
}

if ($tagType -eq 'windows' -and $ContainerOsType -ne 'windows') {
throw "Windows proxy-agent image tags require Docker to run Windows containers."
if ($PINNED_VERSION -match '-ubuntu-26\.04$') {
Write-Log "WARNING: $VERSION_FILE pins the Linux image tag $PINNED_VERSION, but Docker is running Windows containers. Using the Windows image for version $CURRENT_VERSION instead."
}
if ($tagType -eq 'linux' -and $ContainerOsType -ne 'linux') {
throw "Linux proxy-agent image tags require Docker to run Linux containers."
if ($pinnedWindowsVariant) {
$legacyVariant = $pinnedWindowsVariant
if ($WINDOWS_VERSION -ne $legacyVariant) {
Add-Content -Path $SETTINGS_FILE -Value "`n`$WINDOWS_VERSION = '$legacyVariant'" -Encoding ascii
$script:WINDOWS_VERSION = $legacyVariant
}
return $legacyVariant
}

return $Tag
if ($WINDOWS_VERSION) {
return $WINDOWS_VERSION
}
return Get-WindowsLtscVersion
}

function Get-ReleaseVersion {
param([Parameter(Mandatory)][string]$Tag)
function Get-ImageTag {
param(
[Parameter(Mandatory)][string]$Version,
[Parameter(Mandatory)][ValidateSet('linux', 'windows')][string]$ContainerOsType,
[string]$WindowsVersion
)

if ($Tag -match '^(?<version>\d+\.\d+\.\d+)(?:(?:-ubuntu-26\.04)|(?:-windows-(?:ltsc2019|ltsc2022|ltsc2025)))?$') {
return $Matches.version
if ($ContainerOsType -eq 'windows') {
return "$Version-windows-$WindowsVersion"
}
return "$Version$LINUX_IMAGE_TAG_SUFFIX"
}

throw "Invalid proxy-agent image tag '$Tag'."
function Set-PinnedVersion {
param([Parameter(Mandatory)][string]$Version)
if ($Version -ne $PINNED_VERSION) {
Set-Content -Path $VERSION_FILE -Value $Version -Encoding ascii
$script:PINNED_VERSION = $Version
}
}

function Get-LatestVersion {
Expand Down Expand Up @@ -204,15 +215,12 @@ function Get-LatestVersion {
exit 1
}

$latest = $versions | Sort-Object { [version]($_ -replace $releasePattern, '') } | Select-Object -Last 1
return $latest
return ($versions | ForEach-Object { $_ -replace $releasePattern, '' } | Sort-Object { [version]$_ } | Select-Object -Last 1)
}

function Compare-SemVer {
param([string]$A, [string]$B)
$aVer = [version](Get-ReleaseVersion -Tag $A)
$bVer = [version](Get-ReleaseVersion -Tag $B)
return $aVer.CompareTo($bVer)
return ([version]$A).CompareTo([version]$B)
}

# Only the commands that start a container check the setting, so stop, status
Expand All @@ -235,10 +243,10 @@ function Stop-ProxyAgent {

function Start-ProxyAgent {
param(
[Parameter(Mandatory)][string]$Version,
[Parameter(Mandatory)][string]$ImageTag,
[Parameter(Mandatory)][ValidateSet('linux', 'windows')][string]$ContainerOsType
)
Write-Log "Starting $CONTAINER_NAME (version: $Version)..."
Write-Log "Starting $CONTAINER_NAME (image tag: $ImageTag)..."

Stop-ProxyAgent

Expand Down Expand Up @@ -283,7 +291,7 @@ function Start-ProxyAgent {
'--health-timeout', '15s',
'-v', "${configDirectoryMount}:C:/config:ro",
'-v', "${logsMount}:$containerLogDir",
"${IMAGE}:${Version}",
"${IMAGE}:${ImageTag}",
'-i', $containerConfigPath
)
} else {
Expand All @@ -296,7 +304,7 @@ function Start-ProxyAgent {
'--health-timeout', '3s',
'-v', "${configFileMount}:/config/config.json:ro",
'-v', "${logsMount}:$containerLogDir",
"${IMAGE}:${Version}",
"${IMAGE}:${ImageTag}",
'-i', $containerConfigPath
)
}
Expand Down Expand Up @@ -348,55 +356,39 @@ function Start-ProxyAgent {

function Start-CurrentProxyAgent {
$containerOsType = Get-ContainerOsType
$resolvedVersion = Resolve-ImageTag -Tag $CURRENT_VERSION -ContainerOsType $containerOsType
$windowsVersion = Resolve-WindowsVersion -ContainerOsType $containerOsType
$imageTag = Get-ImageTag -Version $CURRENT_VERSION -ContainerOsType $containerOsType -WindowsVersion $windowsVersion
Set-PinnedVersion $CURRENT_VERSION

if (-not (Start-ProxyAgent -Version $resolvedVersion -ContainerOsType $containerOsType)) {
if (-not (Start-ProxyAgent -ImageTag $imageTag -ContainerOsType $containerOsType)) {
return $false
}

if ($resolvedVersion -ne $CURRENT_VERSION) {
Set-Content -Path $VERSION_FILE -Value $resolvedVersion -Encoding ascii
}

return $true
}

function Invoke-Upgrade {
Write-Host "Checking for latest version..."
$containerOsType = Get-ContainerOsType
$currentVersion = Resolve-ImageTag -Tag $CURRENT_VERSION -ContainerOsType $containerOsType
if ($containerOsType -eq 'windows') {
$windowsVersion = Get-ImageTagVariant -Tag $currentVersion
$latestVersion = Get-LatestVersion -ContainerOsType windows -WindowsVersion $windowsVersion
} else {
$tagType = Get-ImageTagType -Tag $currentVersion
if ($tagType -eq 'windows') {
throw "Windows proxy-agent image tags require Docker to run Windows containers."
}
$latestVersion = Get-LatestVersion -ContainerOsType linux
}

if ((Compare-SemVer $latestVersion $currentVersion) -eq 0) {
if ($currentVersion -ne $CURRENT_VERSION) {
Write-Log "Switching image tag from $CURRENT_VERSION to $currentVersion..."
if (-not (Start-ProxyAgent -Version $currentVersion -ContainerOsType $containerOsType)) {
exit 1
}
Set-Content -Path $VERSION_FILE -Value $currentVersion -Encoding ascii
}
$windowsVersion = Resolve-WindowsVersion -ContainerOsType $containerOsType
$latestVersion = Get-LatestVersion -ContainerOsType $containerOsType -WindowsVersion $windowsVersion

Write-Host "Already running the latest version ($currentVersion)."
if ((Compare-SemVer $latestVersion $CURRENT_VERSION) -eq 0) {
Set-PinnedVersion $CURRENT_VERSION
Write-Host "Already running the latest version ($CURRENT_VERSION)."
exit 0
}

Write-Log "Upgrading from $currentVersion to $latestVersion..."
Set-Content -Path $VERSION_FILE -Value $latestVersion -Encoding ascii
Write-Log "Upgrading from $CURRENT_VERSION to $latestVersion..."
Set-PinnedVersion $latestVersion

if (-not (Start-ProxyAgent -Version $latestVersion -ContainerOsType $containerOsType)) {
Write-Log "Upgrade failed, rolling back to $currentVersion..."
Set-Content -Path $VERSION_FILE -Value $currentVersion -Encoding ascii
if (-not (Start-ProxyAgent -Version $currentVersion -ContainerOsType $containerOsType)) {
Write-Log "Rollback to $currentVersion failed."
$latestTag = Get-ImageTag -Version $latestVersion -ContainerOsType $containerOsType -WindowsVersion $windowsVersion
if (-not (Start-ProxyAgent -ImageTag $latestTag -ContainerOsType $containerOsType)) {
Write-Log "Upgrade failed, rolling back to $CURRENT_VERSION..."
Set-PinnedVersion $CURRENT_VERSION
$currentTag = Get-ImageTag -Version $CURRENT_VERSION -ContainerOsType $containerOsType -WindowsVersion $windowsVersion
if (-not (Start-ProxyAgent -ImageTag $currentTag -ContainerOsType $containerOsType)) {
Write-Log "Rollback to $CURRENT_VERSION failed."
}
exit 1
}
Expand All @@ -406,6 +398,7 @@ function Invoke-Upgrade {

switch ($Command) {
'start' {
$CURRENT_VERSION = Get-ReleaseVersion -Tag $PINNED_VERSION
Assert-MemoryAllocation
if (-not (Start-CurrentProxyAgent)) { exit 1 }
}
Expand All @@ -414,11 +407,13 @@ switch ($Command) {
Stop-ProxyAgent
}
'restart' {
$CURRENT_VERSION = Get-ReleaseVersion -Tag $PINNED_VERSION
Assert-MemoryAllocation
Write-Log "Restarting $CONTAINER_NAME..."
if (-not (Start-CurrentProxyAgent)) { exit 1 }
}
'upgrade' {
$CURRENT_VERSION = Get-ReleaseVersion -Tag $PINNED_VERSION
Assert-MemoryAllocation
Invoke-Upgrade
}
Expand Down
Loading
Loading