mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
fix(installer): replace a stale installer before upgrading (#3235)
This commit is contained in:
@@ -2198,6 +2198,7 @@ async function verifyInstallerExecution(installerRoot: string): Promise<Array<st
|
|||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
PATH: `${stubBin}${path.delimiter}${process.env.PATH ?? ''}`,
|
PATH: `${stubBin}${path.delimiter}${process.env.PATH ?? ''}`,
|
||||||
|
FLUXER_INSTALLER_REFRESHED: '1',
|
||||||
...(cwd == null ? {} : {PWD: cwd}),
|
...(cwd == null ? {} : {PWD: cwd}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -128,6 +128,8 @@ Removing the line from `.env` also lets the upgrade run, and it is the wrong fix
|
|||||||
|
|
||||||
Keep the installer beside the stack files. [Get started](/operator/get-started/#step-4-bring-up-the-instance) has the download and the checksum check for a fresh copy.
|
Keep the installer beside the stack files. [Get started](/operator/get-started/#step-4-bring-up-the-instance) has the download and the checksum check for a fresh copy.
|
||||||
|
|
||||||
|
`--update` first compares the installer against the digest at `https://fluxer.dev/install.sh.sha256`. When the copy differs, it downloads the current one, checks it against that digest, and asks before it replaces the copy and runs it with the same options. Answering no, `--non-interactive`, or a run without a terminal stops before anything changes. On Windows the same check reads `https://fluxer.dev/install.ps1.sha256`.
|
||||||
|
|
||||||
See the plan first:
|
See the plan first:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -59,11 +59,17 @@ param(
|
|||||||
[string[]]$Rest = @()
|
[string[]]$Rest = @()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
$FluxerScriptArguments = @{}
|
||||||
|
foreach ($entry in $PSBoundParameters.GetEnumerator()) {
|
||||||
|
$FluxerScriptArguments[$entry.Key] = $entry.Value
|
||||||
|
}
|
||||||
|
|
||||||
Set-StrictMode -Version Latest
|
Set-StrictMode -Version Latest
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
$ProgressPreference = 'SilentlyContinue'
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
|
||||||
$FluxerRawBase = 'https://raw.githubusercontent.com/fluxerapp/fluxer'
|
$FluxerRawBase = 'https://raw.githubusercontent.com/fluxerapp/fluxer'
|
||||||
|
$FluxerInstallerUrl = 'https://fluxer.dev/install.ps1'
|
||||||
$FluxerStackPath = 'deploy/self-hosting'
|
$FluxerStackPath = 'deploy/self-hosting'
|
||||||
$FluxerHealthPath = '/_health'
|
$FluxerHealthPath = '/_health'
|
||||||
$FluxerInitService = 'seaweedfs-init'
|
$FluxerInitService = 'seaweedfs-init'
|
||||||
@@ -1980,6 +1986,71 @@ function Assert-FluxerComposeFiles([string]$TargetDir, [string]$EnvPath) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-FluxerSha256([string]$Path) {
|
||||||
|
return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
}
|
||||||
|
|
||||||
|
function Update-FluxerInstaller {
|
||||||
|
if ($env:FLUXER_INSTALLER_REFRESHED) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$self = $PSCommandPath
|
||||||
|
if (-not $self) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$selfDir = Split-Path -Parent $self
|
||||||
|
if ($DryRun) {
|
||||||
|
$staging = New-FluxerStagingDirectory ([System.IO.Path]::GetTempPath())
|
||||||
|
} else {
|
||||||
|
$staging = New-FluxerStagingDirectory $selfDir
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$digestPath = Join-Path $staging 'install.ps1.sha256'
|
||||||
|
try {
|
||||||
|
Invoke-WebRequest -Uri "$FluxerInstallerUrl.sha256" -OutFile $digestPath -UseBasicParsing -MaximumRedirection 5 -TimeoutSec 60
|
||||||
|
} catch {
|
||||||
|
Write-FluxerLine "Could not reach $FluxerInstallerUrl.sha256, so this run goes on with $self."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$published = ([System.IO.File]::ReadAllText($digestPath).Trim() -split '\s+')[0].ToLowerInvariant()
|
||||||
|
if ($published -notmatch '^[0-9a-f]{64}$') {
|
||||||
|
Stop-Fluxer "$FluxerInstallerUrl.sha256 holds no sha256 digest. Nothing was changed." $FluxerExitDownload
|
||||||
|
}
|
||||||
|
if ((Get-FluxerSha256 $self) -eq $published) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$fresh = Join-Path $staging 'install.ps1'
|
||||||
|
try {
|
||||||
|
Invoke-WebRequest -Uri $FluxerInstallerUrl -OutFile $fresh -UseBasicParsing -MaximumRedirection 5 -TimeoutSec 120
|
||||||
|
} catch {
|
||||||
|
Stop-Fluxer "Download failed for $FluxerInstallerUrl. Nothing was changed." $FluxerExitDownload
|
||||||
|
}
|
||||||
|
if ((Get-FluxerSha256 $fresh) -ne $published) {
|
||||||
|
Stop-Fluxer "$FluxerInstallerUrl does not match the digest in $FluxerInstallerUrl.sha256. Nothing was changed." $FluxerExitDownload
|
||||||
|
}
|
||||||
|
Write-FluxerLine "$self differs from the installer $FluxerInstallerUrl serves. The stack files an upgrade downloads can require .env keys that only the current installer writes."
|
||||||
|
if ($DryRun) {
|
||||||
|
Write-FluxerLine 'The run asks to replace it with the current installer before it changes anything. The plan below is the one this copy would follow.'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ($NonInteractive -or [Console]::IsInputRedirected) {
|
||||||
|
Stop-Fluxer "Nothing was changed. Download the current installer and run it:`n Invoke-WebRequest -Uri $FluxerInstallerUrl -OutFile install.ps1 -UseBasicParsing" $FluxerExitRefused
|
||||||
|
}
|
||||||
|
$answer = Read-Host -Prompt "Replace $self with the current installer and run that? [y/N]"
|
||||||
|
if ($null -eq $answer -or $answer.Trim() -notmatch '^(y|yes)$') {
|
||||||
|
Stop-Fluxer "Kept $self. Nothing was changed. Read the current installer at $FluxerInstallerUrl and run it once it is in place." $FluxerExitRefused
|
||||||
|
}
|
||||||
|
Move-Item -LiteralPath $fresh -Destination $self -Force
|
||||||
|
} finally {
|
||||||
|
Remove-FluxerStagingDirectory $staging
|
||||||
|
}
|
||||||
|
Write-FluxerLine "Replaced $self. Running it."
|
||||||
|
$env:FLUXER_INSTALLER_REFRESHED = '1'
|
||||||
|
$global:LASTEXITCODE = 0
|
||||||
|
& $self @FluxerScriptArguments
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
function Invoke-FluxerInstall {
|
function Invoke-FluxerInstall {
|
||||||
if ($Help) {
|
if ($Help) {
|
||||||
Show-FluxerUsage
|
Show-FluxerUsage
|
||||||
@@ -2022,6 +2093,10 @@ function Invoke-FluxerInstall {
|
|||||||
|
|
||||||
Invoke-FluxerPreflight
|
Invoke-FluxerPreflight
|
||||||
|
|
||||||
|
if ($Update) {
|
||||||
|
Update-FluxerInstaller
|
||||||
|
}
|
||||||
|
|
||||||
$targetPath = $Dir
|
$targetPath = $Dir
|
||||||
$adoptedCwd = $false
|
$adoptedCwd = $false
|
||||||
$fellBack = $false
|
$fellBack = $false
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ LC_ALL=C
|
|||||||
export LC_ALL
|
export LC_ALL
|
||||||
|
|
||||||
FLUXER_RAW_BASE='https://raw.githubusercontent.com/fluxerapp/fluxer'
|
FLUXER_RAW_BASE='https://raw.githubusercontent.com/fluxerapp/fluxer'
|
||||||
|
FLUXER_INSTALLER_URL='https://fluxer.dev/install.sh'
|
||||||
FLUXER_STACK_PATH='deploy/self-hosting'
|
FLUXER_STACK_PATH='deploy/self-hosting'
|
||||||
FLUXER_MIN_ENGINE='24.0.0'
|
FLUXER_MIN_ENGINE='24.0.0'
|
||||||
# Podman numbers its releases on its own scale, so the Docker Engine floor says
|
# Podman numbers its releases on its own scale, so the Docker Engine floor says
|
||||||
@@ -305,6 +306,18 @@ opt_no_volume_compression=0
|
|||||||
opt_skip_backup=0
|
opt_skip_backup=0
|
||||||
opt_allow_root=0
|
opt_allow_root=0
|
||||||
|
|
||||||
|
fluxer_self=''
|
||||||
|
if [ -f "$0" ]; then
|
||||||
|
case $0 in
|
||||||
|
/*) fluxer_self=$0 ;;
|
||||||
|
*) fluxer_self="$(pwd)/$0" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fluxer_self_args=''
|
||||||
|
for fluxer_arg in "$@"; do
|
||||||
|
fluxer_self_args="$fluxer_self_args '$(printf '%s' "$fluxer_arg" | sed "s/'/'\\\\''/g")'"
|
||||||
|
done
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
--domain)
|
--domain)
|
||||||
@@ -651,6 +664,74 @@ fluxer_prompt() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fluxer_sha256() {
|
||||||
|
openssl dgst -sha256 < "$1" | awk '{print $NF}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fluxer_drop_scratch() {
|
||||||
|
fluxer_cleanup
|
||||||
|
fluxer_scratch=''
|
||||||
|
}
|
||||||
|
|
||||||
|
fluxer_refresh_installer() {
|
||||||
|
[ -z "${FLUXER_INSTALLER_REFRESHED:-}" ] || return 0
|
||||||
|
[ -n "$fluxer_self" ] || return 0
|
||||||
|
fluxer_self_dir=$(dirname "$fluxer_self")
|
||||||
|
if [ "$opt_dry_run" -eq 1 ]; then
|
||||||
|
fluxer_open_scratch "${TMPDIR:-/tmp}"
|
||||||
|
elif [ -w "$fluxer_self_dir" ]; then
|
||||||
|
fluxer_open_scratch "$fluxer_self_dir"
|
||||||
|
else
|
||||||
|
fluxer_say "$fluxer_self_dir is not writable, so this run cannot check $fluxer_self against $FLUXER_INSTALLER_URL and goes on with it."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if ! curl -fsSL --proto '=https' --tlsv1.2 -o "$fluxer_scratch/install.sh.sha256" "$FLUXER_INSTALLER_URL.sha256"; then
|
||||||
|
fluxer_say "Could not reach $FLUXER_INSTALLER_URL.sha256, so this run goes on with $fluxer_self."
|
||||||
|
fluxer_drop_scratch
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fluxer_published=$(awk 'NR == 1 {print $1}' "$fluxer_scratch/install.sh.sha256")
|
||||||
|
case $fluxer_published in
|
||||||
|
''|*[!0-9a-f]*) fluxer_fail 4 "$FLUXER_INSTALLER_URL.sha256 holds no sha256 digest. Nothing was changed." ;;
|
||||||
|
esac
|
||||||
|
if [ "$(fluxer_sha256 "$fluxer_self")" = "$fluxer_published" ]; then
|
||||||
|
fluxer_drop_scratch
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if ! curl -fsSL --proto '=https' --tlsv1.2 -o "$fluxer_scratch/install.sh" "$FLUXER_INSTALLER_URL"; then
|
||||||
|
fluxer_fail 4 "Download failed for $FLUXER_INSTALLER_URL. Nothing was changed."
|
||||||
|
fi
|
||||||
|
if [ "$(fluxer_sha256 "$fluxer_scratch/install.sh")" != "$fluxer_published" ]; then
|
||||||
|
fluxer_fail 4 "$FLUXER_INSTALLER_URL does not match the digest in $FLUXER_INSTALLER_URL.sha256. Nothing was changed."
|
||||||
|
fi
|
||||||
|
fluxer_say "$fluxer_self differs from the installer $FLUXER_INSTALLER_URL serves. The stack files an upgrade downloads can require .env keys that only the current installer writes."
|
||||||
|
if [ "$opt_dry_run" -eq 1 ]; then
|
||||||
|
fluxer_say 'The run asks to replace it with the current installer before it changes anything. The plan below is the one this copy would follow.'
|
||||||
|
fluxer_drop_scratch
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [ "$opt_non_interactive" -eq 1 ] || [ ! -t 0 ]; then
|
||||||
|
fluxer_fail 3 "Nothing was changed. Download the current installer and run it:
|
||||||
|
curl -fsSLO $FLUXER_INSTALLER_URL"
|
||||||
|
fi
|
||||||
|
printf 'Replace %s with the current installer and run that? [y/N] ' "$fluxer_self" >&2
|
||||||
|
fluxer_answer=''
|
||||||
|
read -r fluxer_answer || true
|
||||||
|
case $fluxer_answer in
|
||||||
|
y|Y|yes|Yes|YES) ;;
|
||||||
|
*) fluxer_fail 3 "Kept $fluxer_self. Nothing was changed. Read the current installer at $FLUXER_INSTALLER_URL and run it once it is in place." ;;
|
||||||
|
esac
|
||||||
|
if [ -x "$fluxer_self" ]; then
|
||||||
|
chmod +x "$fluxer_scratch/install.sh"
|
||||||
|
fi
|
||||||
|
mv "$fluxer_scratch/install.sh" "$fluxer_self"
|
||||||
|
fluxer_drop_scratch
|
||||||
|
fluxer_say "Replaced $fluxer_self. Running it."
|
||||||
|
FLUXER_INSTALLER_REFRESHED=1
|
||||||
|
export FLUXER_INSTALLER_REFRESHED
|
||||||
|
eval "exec sh \"\$fluxer_self\" $fluxer_self_args"
|
||||||
|
}
|
||||||
|
|
||||||
fluxer_resolve_values() {
|
fluxer_resolve_values() {
|
||||||
if [ "$opt_update" -eq 1 ] || [ "$opt_rollback" -eq 1 ]; then
|
if [ "$opt_update" -eq 1 ] || [ "$opt_rollback" -eq 1 ]; then
|
||||||
return 0
|
return 0
|
||||||
@@ -2100,6 +2181,10 @@ fluxer_preflight
|
|||||||
fluxer_validate_options
|
fluxer_validate_options
|
||||||
fluxer_resolve_values
|
fluxer_resolve_values
|
||||||
|
|
||||||
|
if [ "$opt_update" -eq 1 ]; then
|
||||||
|
fluxer_refresh_installer
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$opt_update" -eq 1 ] || [ "$opt_rollback" -eq 1 ]; then
|
if [ "$opt_update" -eq 1 ] || [ "$opt_rollback" -eq 1 ]; then
|
||||||
fluxer_require_instance
|
fluxer_require_instance
|
||||||
fluxer_resolve_ref
|
fluxer_resolve_ref
|
||||||
|
|||||||
Reference in New Issue
Block a user