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
13 changes: 11 additions & 2 deletions tests/test-lifecycle-ownership.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,13 @@ case "$1" in
rm) ;;
*) exit 2 ;;
esac ;;
rm|rmi) ;;
rm) ;;
rmi)
if [ "${FAIL_SHARED_RELEASE_REMOVE:-0}" = 1 ] \
&& [ "$2" = 'ghcr.io/squarewavesystems/squarebox@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ]; then
echo 'shared release image is in use' >&2
exit 42
fi ;;
*) exit 2 ;;
esac
EOF
Expand Down Expand Up @@ -192,14 +198,17 @@ fi
grep -q -- '--force is required' "$TMP/force.out"
test -d "$TMP/custom"

"$ROOT/uninstall.sh" --purge --yes --force
export FAIL_SHARED_RELEASE_REMOVE=1
"$ROOT/uninstall.sh" --purge --yes --force >"$TMP/purge.out"
test ! -e "$TMP/custom"
test -f "$TMP/home/squarebox/DO-NOT-DELETE"
test -f "$TMP/external-workspace/project.txt"
test ! -e "$TMP/home/.squarebox-shell-init"
! grep -qF '# >>> squarebox >>>' "$TMP/home/.bashrc"
grep -q '^rm -f squarebox$' "$TMP/runtime.log"
grep -q '^rmi squarebox$' "$TMP/runtime.log"
! grep -q '^rmi ghcr.io/squarewavesystems/squarebox@sha256:' "$TMP/runtime.log"
grep -q 'Retaining shared Candidate image ref' "$TMP/purge.out"
grep -q '^volume rm custom-home$' "$TMP/runtime.log"

echo 'ok - lifecycle deletion requires identity, reachability, adoption force, and recorded paths'
2 changes: 2 additions & 0 deletions tests/test-lifecycle-static.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ grep -q '\$HomeVolume -cne \$State.HOME_VOLUME' install.ps1
grep -q '\$owner.Trim() -cne '\''__INSTALL_ID__' install.ps1
grep -q '\$script:RollbackArmed' install.ps1
grep -q 'changed ownership after confirmation' uninstall.ps1
grep -q 'Retaining shared Candidate image ref' uninstall.sh
grep -q 'Retaining shared Candidate image ref' uninstall.ps1
! grep -Eq '\$owner([.]Trim[(][)])?[[:space:]]+-ne[[:space:]]+\$InstallId' install.ps1 uninstall.ps1
! grep -Eq 'sudo[[:space:]]+rm[[:space:]]+-rf' uninstall.sh
for file in install.sh uninstall.sh; do
Expand Down
19 changes: 11 additions & 8 deletions uninstall.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ $ContainerName = if ($State) { $State.CONTAINER_NAME } else { 'squarebox' }
$ImageAlias = if ($State) { $State.IMAGE_ALIAS } else { 'squarebox' }
$ImageRef = if ($State) { $State.IMAGE_REF } else { 'squarebox' }
$ImageId = if ($State) { $State.IMAGE_ID } else { '' }
$SharedImageRef = $State -and $State.BUILD -ceq '0' -and $ImageRef -cne $ImageAlias
$HomeVolume = if ($State) { $State.HOME_VOLUME } elseif ($env:SQUAREBOX_HOME_VOLUME) { $env:SQUAREBOX_HOME_VOLUME } else { 'squarebox-home' }
$HomeVolumeAdopted = $State -and $State.HOME_VOLUME_ADOPTED -eq '1'
$ProfilePath = if ($State -and $State.SHELL_RC) { $State.SHELL_RC } else { $PROFILE.CurrentUserAllHosts }
Expand Down Expand Up @@ -280,7 +281,7 @@ Write-Host ''
Write-Host 'Will remove:'
$Anything = $false
if ($ContainerOwned) { Write-Host " - Managed Box: $ContainerName"; $Anything = $true }
if ($ImageOwned) { Write-Host " - Recorded image refs: $ImageAlias and $ImageRef"; $Anything = $true }
if ($ImageOwned) { Write-Host " - Recorded image alias: $ImageAlias"; $Anything = $true }
if ($HasProfile) { Write-Host " - PowerShell adapter(s): $($ProfilePaths -join ', ')"; $Anything = $true }
if ($Purge -and (Test-Path $InstallDir)) { Write-Host " - Recorded install directory: $InstallDir"; $Anything = $true }
if ($Purge -and $VolumeOwned) { Write-Host " - Managed home: $HomeVolume"; $Anything = $true }
Expand Down Expand Up @@ -323,14 +324,16 @@ if ($ContainerOwned) {
if ($LASTEXITCODE -ne 0) { Abort "Failed to remove managed Box '$ContainerName'." }
}
if ($ImageOwned) {
foreach ($ref in @($ImageAlias, $ImageRef) | Select-Object -Unique) {
& $Runtime image inspect $ref 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) { continue }
$refId = (& $Runtime image inspect -f '{{.Id}}' $ref).Trim()
if ($State -and $refId -cne $ImageId) { Abort "Image ref '$ref' changed ownership during uninstall." }
& $Runtime rmi $ref | Out-Null
if ($LASTEXITCODE -ne 0) { Abort "Image ref '$ref' is still in use or could not be removed." }
& $Runtime image inspect $ImageAlias 2>$null | Out-Null
if ($LASTEXITCODE -eq 0) {
$refId = (& $Runtime image inspect -f '{{.Id}}' $ImageAlias).Trim()
if ($State -and $refId -cne $ImageId) { Abort "Image alias '$ImageAlias' changed ownership during uninstall." }
& $Runtime rmi $ImageAlias | Out-Null
if ($LASTEXITCODE -ne 0) { Abort "Image alias '$ImageAlias' is still in use or could not be removed." }
}
# Published refs identify shared Candidate cache, not a resource owned by
# this Install identity. Another Box may still depend on the same digest.
if ($SharedImageRef) { Write-Host "Retaining shared Candidate image ref $ImageRef." }
}
if ($HasProfile) {
foreach ($path in $ProfileBlocks) { Remove-SquareboxProfileBlock $path }
Expand Down
28 changes: 15 additions & 13 deletions uninstall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ echo ""
echo "Will remove:"
anything=0
[ "$container_owned" = 1 ] && { echo " - Managed Box: $CONTAINER_NAME"; anything=1; }
[ "$image_owned" = 1 ] && { echo " - Recorded image refs: $IMAGE_ALIAS ${IMAGE_REF:+and $IMAGE_REF}"; anything=1; }
[ "$image_owned" = 1 ] && { echo " - Recorded image alias: $IMAGE_ALIAS"; anything=1; }
[ "$has_shell_init" = 1 ] && { echo " - Shell adapter: $SHELL_INIT"; anything=1; }
for _rc in "${rc_files[@]}"; do echo " - Shell sentinel: $_rc"; anything=1; done
[ "$has_bridge" = 1 ] && { echo " - Git Bash bridge: $HOME/.bash_profile"; anything=1; }
Expand Down Expand Up @@ -411,19 +411,21 @@ if [ "$container_owned" = 1 ]; then
fi

if [ "$image_owned" = 1 ]; then
echo "Removing recorded image references..."
_refs=("$IMAGE_ALIAS"); [ -n "$IMAGE_REF" ] && [ "$IMAGE_REF" != "$IMAGE_ALIAS" ] && _refs+=("$IMAGE_REF")
for _ref in "${_refs[@]}"; do
if rt_cmd image inspect "$_ref" >/dev/null 2>&1; then
_ref_id="$(rt_cmd image inspect -f '{{.Id}}' "$_ref")"
if [ "$HAD_STATE" = 1 ] && [ "$_ref_id" != "$IMAGE_ID" ]; then
echo "Error: image ref '$_ref' changed ownership during uninstall; refusing removal." >&2; exit 1
fi
rt_cmd rmi "$_ref" >/dev/null || {
echo "Error: image ref '$_ref' is still in use or could not be removed." >&2; exit 1;
}
echo "Removing recorded image alias..."
if rt_cmd image inspect "$IMAGE_ALIAS" >/dev/null 2>&1; then
_ref_id="$(rt_cmd image inspect -f '{{.Id}}' "$IMAGE_ALIAS")"
if [ "$HAD_STATE" = 1 ] && [ "$_ref_id" != "$IMAGE_ID" ]; then
echo "Error: image alias '$IMAGE_ALIAS' changed ownership during uninstall; refusing removal." >&2; exit 1
fi
done
rt_cmd rmi "$IMAGE_ALIAS" >/dev/null || {
echo "Error: image alias '$IMAGE_ALIAS' is still in use or could not be removed." >&2; exit 1;
}
fi
# Published refs identify shared Candidate cache, not a resource owned by
# this Install identity. Another Box may still depend on the same digest.
if [ "$HAD_STATE" = 1 ] && [ "$BUILD" = 0 ] && [ -n "$IMAGE_REF" ] && [ "$IMAGE_REF" != "$IMAGE_ALIAS" ]; then
echo "Retaining shared Candidate image ref $IMAGE_REF."
fi
fi

rm -f "$SHELL_INIT"
Expand Down