Files
local-ci-cd-system/scripts/_Transport.psm1
T

183 lines
4.8 KiB
PowerShell

#Requires -Version 5.1
<#
.SYNOPSIS
SSH/SCP transport helpers for Linux build VMs.
.DESCRIPTION
SSH-only transport layer for the Linux branch of the CI/CD system.
The existing WinRM transport (used by Windows VMs) is NOT modified.
Exported functions:
Invoke-SshCommand — run a command in a Linux guest via ssh.exe
Copy-SshItem — copy files to/from a Linux guest via scp.exe
Test-SshReady — poll until SSH is ready (port 22 open + login succeeds)
Requirements:
- ssh.exe and scp.exe in PATH (default on Windows 11 / Server 2022)
- SSH private key at the path provided
- Guest user must be set up for key-based auth (no passphrase)
#>
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue' # suppress Write-Progress (Test-NetConnection, IWR, etc.)
function Invoke-SshCommand {
<#
.SYNOPSIS
Run a command in a Linux guest via ssh.exe
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string] $IP,
[string] $User = 'ci_build',
[string] $KeyPath = 'F:\CI\keys\ci_linux',
[Parameter(Mandatory)]
[string] $Command,
[int] $ConnectTimeout = 10,
# Capture + return stdout/stderr instead of printing to console.
[switch] $PassThru,
# Don't throw on non-zero exit — just return the output.
[switch] $AllowFail
)
$sshArgs = @(
'-i', $KeyPath,
'-o', 'StrictHostKeyChecking=no',
'-o', 'UserKnownHostsFile=NUL',
'-o', "ConnectTimeout=$ConnectTimeout",
'-o', 'BatchMode=yes',
"$User@$IP",
$Command
)
if ($PassThru) {
$output = & ssh @sshArgs 2>&1
$exit = $LASTEXITCODE
}
else {
& ssh @sshArgs
$exit = $LASTEXITCODE
$output = @()
}
if ($exit -ne 0 -and -not $AllowFail) {
throw "[SSH] Command failed (exit $exit): $Command"
}
return [pscustomobject]@{
ExitCode = [int]$exit
Output = [string[]]$output
}
}
function Copy-SshItem {
<#
.SYNOPSIS
Copy files to/from Linux guest via scp.exe
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string] $Source,
[Parameter(Mandatory)]
[string] $Destination,
# Guest IP — used to build user@host prefix when Direction is set.
[string] $IP = '',
[string] $User = 'ci_build',
[Parameter(Mandatory)]
[string] $KeyPath,
[ValidateSet('ToGuest', 'FromGuest', 'Direct')]
[string] $Direction = 'Direct',
# Pass -r to scp (recursive copy).
[switch] $Recurse,
[int] $ConnectTimeout = 10
)
if ($Direction -eq 'ToGuest') {
$Destination = "$User@${IP}:$Destination"
}
elseif ($Direction -eq 'FromGuest') {
$Source = "$User@${IP}:$Source"
}
# Direction = 'Direct': use Source + Destination as-is
$scpArgs = @(
'-i', $KeyPath,
'-o', 'StrictHostKeyChecking=no',
'-o', 'UserKnownHostsFile=NUL',
'-o', "ConnectTimeout=$ConnectTimeout"
)
if ($Recurse) { $scpArgs += '-r' }
$scpArgs += @($Source, $Destination)
& scp @scpArgs
if ($LASTEXITCODE -ne 0) {
throw "[SCP] Copy failed (exit $LASTEXITCODE): $Source -> $Destination"
}
}
function Test-SshReady {
<#
.SYNOPSIS
Poll until SSH port 22 is open and a login command succeeds.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string] $IP,
[string] $User = 'ci_build',
[string] $KeyPath = 'F:\CI\keys\ci_linux',
[int] $TimeoutSec = 300,
[int] $PollSec = 10
)
$deadline = (Get-Date).AddSeconds($TimeoutSec)
# Phase 1: wait for port 22 to be open
$portOpen = $false
while (-not $portOpen -and (Get-Date) -lt $deadline) {
$portOpen = (Test-NetConnection -ComputerName $IP -Port 22 `
-InformationLevel Quiet -WarningAction SilentlyContinue `
-ErrorAction SilentlyContinue)
if (-not $portOpen) {
Start-Sleep -Seconds $PollSec
}
}
if (-not $portOpen) {
throw "[Test-SshReady] Timed out after ${TimeoutSec}s waiting for SSH at $IP"
}
# Phase 2: try ssh echo — success when output contains 'ready'
while ((Get-Date) -lt $deadline) {
$result = Invoke-SshCommand -IP $IP -User $User -KeyPath $KeyPath `
-Command 'echo ready' -AllowFail -PassThru
if ($result.ExitCode -eq 0 -and ($result.Output -join '') -like '*ready*') {
return $true
}
Start-Sleep -Seconds $PollSec
}
throw "[Test-SshReady] Timed out after ${TimeoutSec}s waiting for SSH at $IP"
}
Export-ModuleMember -Function Invoke-SshCommand, Copy-SshItem, Test-SshReady