Skip to content

Commit 1ad4e42

Browse files
authored
fix(snap): simplify snap hooks (#3988)
* fix(snap): simplify snap hooks The `post-refresh` hook runs after initial snap installation as well, so there is no need to call the `install` hook from within the `post-refresh` hook; instead, the logic can simply be moved into the `post-refresh` hook directly, and the `install` hook removed. Also, the existing `install` hook logic looked for an insecure configuration, and if found, replaced the entire configuration file with a minimal default in the current format. But OpenShell does that default behavior without any config file, so we may as well simply remove the configuration file entirely to keep up-to-date with the current default behavior. Let OpenShell create a configuration file if it needs to, rather than auto-create one via the packaging scripts. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * fix(snap): remove the connect-plug-docker hook The `openshell:docker` is auto-connected to the system `:docker` slot, so there should not be a need to separately restart the gateway service when the interface is connected. For locally-built test snaps which were not published to the store, the autoconnection is not made, but when the snap is installed, the gateway will attempt to start anyway and fail to find any available compute driver, so quickly restart until it hits the systemd start-limit, after which systemd prevents the service from being started again. If a user tries to manually connect their locally-built `openshell` snap to the `:docker` slot, then the `connect-plug-docker` hook runs and triggers a restart of the gateway, which will usually fail because the start limit has already been hit. An error in the hook will thus cause the interface connection to be undone, which is undesirable. Thus, we can remove this hook entirely, and instead allow interface connections to succeed as intended. The user still needs to manually restart the gateway service after making a manual connection (as was the case previously) and probably needs to `systemctl reset-failed` first, but at least connection will succeed beforehand so they can proceed with these steps. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * fix(snap): set refresh-mode: endure again, with manual restart Return to the previous behavior before commit a67567e, where the gateway is not stopped before refreshes. The `post-refresh` hook now restarts the gateway if the TLS configuration was corrected, so we don't have to enforce restarting the gateway on every refresh even when not necessary. Thus, set `refresh-mode: endure`, and let the hook decide when the gateway needs to be restarted. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * fix(snap): update docs and tests to reflect snap hook changes Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * docs(snap): remove verbose explanation of snap gateway refresh behavior Signed-off-by: Oliver Calder <oliver.calder@canonical.com> --------- Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
1 parent cb193ef commit 1ad4e42

9 files changed

Lines changed: 191 additions & 222 deletions

File tree

‎docs/about/installation.mdx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,15 @@ openshell status
126126

127127
Keep the client key private.
128128

129-
To install a locally built snap, connect its interfaces manually:
129+
To install a locally built snap, connect its interfaces manually. The gateway may reach systemd's start limit before Docker is connected, so reset the failed unit and restart the gateway after connecting the interfaces:
130130

131131
```shell
132132
sudo snap install ./openshell_*.snap --dangerous
133133
sudo snap connect openshell:log-observe
134134
sudo snap connect openshell:system-observe
135135
sudo snap connect openshell:docker :docker
136+
sudo systemctl reset-failed snap.openshell.gateway.service
137+
sudo snap restart openshell.gateway
136138
```
137139

138140
## Kubernetes

‎python/openshell/release_formula_test.py‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from __future__ import annotations
55

66
import re
7-
import stat
87
import subprocess
98
import sys
109
from pathlib import Path
@@ -168,17 +167,6 @@ def test_snap_wrapper_uses_optional_gateway_config_without_generating_toml() ->
168167
assert 'exec "${SNAP}/bin/openshell-gateway" "$@"' in wrapper
169168

170169

171-
def test_snap_docker_connect_hook_restarts_gateway() -> None:
172-
repo_root = Path(__file__).resolve().parents[2]
173-
hook = repo_root / "snap/hooks/connect-plug-docker"
174-
175-
assert hook.is_file()
176-
assert hook.stat().st_mode & stat.S_IXUSR
177-
assert 'snapctl restart "${SNAP_INSTANCE_NAME}.gateway"' in hook.read_text(
178-
encoding="utf-8"
179-
)
180-
181-
182170
def test_rpm_spec_seeds_and_migrates_gateway_defaults() -> None:
183171
repo_root = Path(__file__).resolve().parents[2]
184172
spec = (repo_root / "openshell.spec").read_text(encoding="utf-8")

‎snap/hooks/connect-plug-docker‎

Lines changed: 0 additions & 13 deletions
This file was deleted.

‎snap/hooks/install‎

Lines changed: 0 additions & 35 deletions
This file was deleted.

‎snap/hooks/post-refresh‎

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,29 @@
22
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
33
# SPDX-License-Identifier: Apache-2.0
44

5-
# Replace insecure gateway configs on refresh, then restart the gateway so the
6-
# new config takes effect even when the previous revision used
5+
# Remove insecure gateway configs on refresh, then restart the gateway so the
6+
# default config takes effect even when the previous revision used
77
# refresh-mode: endure and kept its plaintext gateway running.
88

99
set -eu
1010

11-
"${SNAP}/meta/hooks/install"
11+
config_file="${SNAP_COMMON}/gateway.toml"
12+
insecure='^[[:space:]]*(allow_unauthenticated_users|disable_tls)[[:space:]]*=[[:space:]]*true([[:space:]#]|$)'
13+
14+
# Keep secure operator configs, symlinks, and directories. Remove a config
15+
# that explicitly allows plaintext or anonymous access, even if it has other
16+
# edits.
17+
if [ ! -e "$config_file" ]; then
18+
exit 0
19+
elif [ -L "$config_file" ]; then
20+
exit 0
21+
elif [ -f "$config_file" ]; then
22+
grep -Eq "$insecure" "$config_file" || exit 0
23+
echo "openshell: removing insecure gateway config to use the mTLS default" >&2
24+
elif [ -e "$config_file" ]; then
25+
exit 0
26+
fi
27+
28+
rm -f "$config_file"
29+
1230
snapctl restart "${SNAP_INSTANCE_NAME}.gateway"

‎snapcraft.yaml‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,10 @@ apps:
8888
gateway:
8989
command: bin/openshell-gateway-wrapper
9090
daemon: simple
91-
# Refresh must activate the migrated mTLS config immediately. This
92-
# interrupts active sandbox sessions.
93-
refresh-mode: restart
91+
# refresh-mode: endure prevents snapd from restarting the gateway daemon
92+
# during snap refreshes, which would kill active sandbox sessions.
93+
# Operators must manually restart the service after a refresh if needed.
94+
refresh-mode: endure
9495
# Snapd runs this daemon as root. The wrapper serves TLS from the bundle
9596
# generated in $SNAP_COMMON/tls, and the default config requires client
9697
# certificates; the installer copies the client bundle to the target

‎tasks/scripts/test-packaging-assets.sh‎

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,14 @@ snapcraft="${ROOT}/snapcraft.yaml"
8383
snap_install_docs="${ROOT}/docs/about/installation.mdx"
8484
snap_canary="${ROOT}/.github/workflows/release-canary.yml"
8585
snap_repro="${ROOT}/nix/test-guest/scripts/snap-gateway-repro.sh"
86-
snap_docker_hook="${ROOT}/snap/hooks/connect-plug-docker"
87-
snap_install_hook="${ROOT}/snap/hooks/install"
86+
snap_post_refresh_hook="${ROOT}/snap/hooks/post-refresh"
8887
package_deb="${ROOT}/tasks/scripts/package-deb.sh"
8988
assert_file_exists "$snap_wrapper"
9089
assert_file_exists "$snapcraft"
9190
assert_file_exists "$snap_install_docs"
9291
assert_file_exists "$snap_canary"
9392
assert_file_exists "$snap_repro"
94-
assert_file_exists "$snap_docker_hook"
95-
assert_file_exists "$snap_install_hook"
93+
assert_file_exists "$snap_post_refresh_hook"
9694
assert_file_exists "$package_deb"
9795
assert_contains "$service" "ExecStartPre=/usr/bin/openshell-gateway config preflight"
9896
assert_contains "$package_deb" "\$src_dir/openshell-gateway.service"
@@ -114,28 +112,33 @@ for snap_file in \
114112
"$snap_install_docs" \
115113
"$snap_canary" \
116114
"$snap_repro" \
117-
"$snap_docker_hook" \
118-
"$snap_install_hook"; do
115+
"$snap_post_refresh_hook"; do
119116
assert_not_contains "$snap_file" "docker:docker-daemon"
120117
assert_not_contains "$snap_file" "default-provider: docker"
121118
done
122-
if [[ ! -x "$snap_install_hook" ]]; then
123-
echo "FAIL: Snap install hook must be executable" >&2
119+
if [[ -e "${ROOT}/snap/hooks/connect-plug-docker" ]]; then
120+
echo "FAIL: obsolete Snap Docker connection hook must not exist" >&2
124121
exit 1
125122
fi
126-
assert_not_contains "$snap_install_hook" 'compute_driver'
127-
assert_not_contains "$snap_install_hook" 'allow_unauthenticated_users = true'
128-
assert_contains "$snapcraft" 'refresh-mode: restart'
129-
if [[ ! -x "$(dirname "$snap_install_hook")/post-refresh" ]]; then
123+
if [[ -e "${ROOT}/snap/hooks/install" ]]; then
124+
echo "FAIL: obsolete Snap install hook must not exist" >&2
125+
exit 1
126+
fi
127+
assert_contains "$snapcraft" 'refresh-mode: endure'
128+
if [[ ! -x "$snap_post_refresh_hook" ]]; then
130129
echo "FAIL: Snap post-refresh hook must be executable" >&2
131130
exit 1
132131
fi
133132
assert_not_contains "$ROOT/tasks/scripts/snap-gateway-wrapper.sh" 'OPENSHELL_DISABLE_TLS'
134-
bash "$ROOT/tasks/scripts/test-snap-install-hook.sh" "$snap_install_hook"
133+
bash "$ROOT/tasks/scripts/test-snap-post-refresh-hook.sh" "$snap_post_refresh_hook"
135134
assert_not_contains "$snap_install_docs" "snap connect openshell:home"
136135
assert_not_contains "$snap_install_docs" "snap connect openshell:network"
137136
assert_not_contains "$snap_install_docs" "snap connect openshell:network-bind"
138137
assert_contains "$snap_install_docs" "snap connect openshell:docker :docker"
138+
assert_contains "$snap_install_docs" "systemctl reset-failed snap.openshell.gateway.service"
139+
assert_contains "$snap_install_docs" "snap restart openshell.gateway"
140+
assert_contains "$snap_install_docs" "Snap refreshes keep the running gateway process active"
141+
assert_contains "$snap_install_docs" "install script refreshes and restarts the gateway automatically"
139142
assert_contains "$snap_canary" "install.sh | sh"
140143
assert_contains "$snap_canary" "ubuntu-snap-system-docker:"
141144
assert_contains "$snap_canary" "ubuntu-snap-docker-preflight:"

‎tasks/scripts/test-snap-install-hook.sh‎

Lines changed: 0 additions & 142 deletions
This file was deleted.

0 commit comments

Comments
 (0)