mirror of
https://scm.tikali.ai/tikali/applications/monky/monky-deployd.git
synced 2026-09-18 08:16:17 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7343970e2e | |||
| 96c5dbbeb5 | |||
| fead1f999b | |||
| 037782e1ff | |||
| fe7b0c6922 | |||
| 4ff2e29fbc |
@@ -1,6 +1,32 @@
|
|||||||
<!-- xlate:verbatim-fences -->
|
<!-- xlate:verbatim-fences -->
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.1.10 — sites `fmt|pdx|roam`, and a read grant that outlives the tunneller (2026-09-13)
|
||||||
|
|
||||||
|
- **Install kits for every backend registered since 2026-09-08 died at `--site`** (deployd#3,
|
||||||
|
DD-0620): tenancy 0.7.x issues `fmt | pdx | roam`, deployd still enforced `cbs | pdx`. `SITES`,
|
||||||
|
`install.sh` and `config.example.yaml` now accept `fmt | cbs | pdx | roam` (`cbs` = the deprecated
|
||||||
|
alias of `fmt` on rows registered before the rename) and a test pins the set to tenancy's.
|
||||||
|
- **The agent's read on the ziti identity now survives a tunneller rewrite for real.** 0.1.8 made
|
||||||
|
`monky-deployd` a member of the `ziti` group; that is not enough: `ziti-edge-tunnel` re-creates the
|
||||||
|
file with mode `0600`, which sets the ACL mask to `---` and defeats the group read and the named-user
|
||||||
|
entry alike (env-dev-08, 2026-09-11 → 09-13: two days of *"identity is not readable"* ticks under a
|
||||||
|
healthy tunnel; the backend went `offline`). New `identity-acl.sh` re-applies the entries **and the
|
||||||
|
mask**; `monky-deployd-identity-acl.path` re-runs it whenever the identity directory changes;
|
||||||
|
`install.sh` and the package postinstall arm it.
|
||||||
|
|
||||||
|
## 0.1.9 — an upgrade no longer stops the agent (2026-09-09)
|
||||||
|
|
||||||
|
- **`dpkg -i` over a running agent disabled it.** dpkg calls the OLD package's `prerm` on an
|
||||||
|
**upgrade** as well as on a removal (rpm passes a remaining-instance count), and `preremove.sh`
|
||||||
|
ran `systemctl disable --now monky-deployd.timer` unconditionally. Upgrading env-dev-01 and
|
||||||
|
env-dev-08 from 0.1.6/0.1.7 to 0.1.8 stopped and **disabled** both agents. It is silent: the box
|
||||||
|
stays up, the containers keep running, and nothing reports that check-ins have ceased — the
|
||||||
|
backend simply stops converging. `preremove.sh` now returns early for every upgrade shape
|
||||||
|
(`upgrade`, `failed-upgrade`, `deconfigure`, rpm's `1`), and `postinstall.sh` `try-restart`s the
|
||||||
|
long-lived proxy unit so it picks up the new code. A fleet upgrade would have taken every agent
|
||||||
|
offline at once.
|
||||||
|
|
||||||
## 0.1.8 — onboarding: keep the identity readable, refuse a full disk (2026-09-09)
|
## 0.1.8 — onboarding: keep the identity readable, refuse a full disk (2026-09-09)
|
||||||
|
|
||||||
Three faults from one onboarding (env-dev-08, agent-managed, 2026-09-09), each of which sent the
|
Three faults from one onboarding (env-dev-08, agent-managed, 2026-09-09), each of which sent the
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
# simple lists, comments. Keys not listed here are a config error.
|
# simple lists, comments. Keys not listed here are a config error.
|
||||||
|
|
||||||
env_id: env-qa-02 # env-<tier>-<nn> (or a grandfathered legacy id); MUST match the token's env
|
env_id: env-qa-02 # env-<tier>-<nn> (or a grandfathered legacy id); MUST match the token's env
|
||||||
site: cbs # cbs | pdx (lowercase DC code)
|
site: cbs # fmt | pdx | roam as tenancy issues it (cbs = deprecated alias of fmt, still on rows registered before 2026-09-08)
|
||||||
transport: sdk # sdk (OpenZiti Python SDK, default) | proxy (monky-deployd-proxy.service) | system (tunneler `run` mode / plain DNS)
|
transport: sdk # sdk (OpenZiti Python SDK, default) | proxy (monky-deployd-proxy.service) | system (tunneler `run` mode / plain DNS)
|
||||||
identity: /opt/openziti/etc/identities/monky-host.env-qa-02.json # the box's host identity (read via ACL)
|
identity: /opt/openziti/etc/identities/monky-host.env-qa-02.json # the box's host identity (read via ACL)
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -9,6 +9,7 @@
|
|||||||
| `monky-deployd.service` | `Type=oneshot`, `monky-deployd run --once` as user `monky-deployd` (+ `docker` group); `SuccessExitStatus=75`; hardened (`NoNewPrivileges`, `ProtectSystem=strict`, `ReadWritePaths=/var/lib/monky-deployd /etc/monky-deployd /run/docker.sock`, `UMask=0077`, no capabilities) |
|
| `monky-deployd.service` | `Type=oneshot`, `monky-deployd run --once` as user `monky-deployd` (+ `docker` group); `SuccessExitStatus=75`; hardened (`NoNewPrivileges`, `ProtectSystem=strict`, `ReadWritePaths=/var/lib/monky-deployd /etc/monky-deployd /run/docker.sock`, `UMask=0077`, no capabilities) |
|
||||||
| `monky-deployd-proxy.service` | only with `transport: proxy`: `ziti tunnel proxy -i <identity> monky.tenancy.deploy:18443 openbao:18200` as user `ziti`; `EnvironmentFile=/etc/monky-deployd/proxy.env` |
|
| `monky-deployd-proxy.service` | only with `transport: proxy`: `ziti tunnel proxy -i <identity> monky.tenancy.deploy:18443 openbao:18200` as user `ziti`; `EnvironmentFile=/etc/monky-deployd/proxy.env` |
|
||||||
| `ziti-edge-tunnel.service` | the host identity's tunneler in **`run-host`** mode (drop-in `run-host.conf` written by `install.sh`) |
|
| `ziti-edge-tunnel.service` | the host identity's tunneler in **`run-host`** mode (drop-in `run-host.conf` written by `install.sh`) |
|
||||||
|
| `monky-deployd-identity-acl.path` | re-runs `identity-acl.sh` whenever `/opt/openziti/etc/identities` changes, so the agent keeps its read after the tunneller rewrites the identity (0.1.10) |
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
systemctl status monky-deployd.timer monky-deployd.service
|
systemctl status monky-deployd.timer monky-deployd.service
|
||||||
@@ -30,6 +31,10 @@ the `ziti` **group**, plus an explicit ACL `u:monky-deployd:r` and a default ACL
|
|||||||
> first refresh and then fails every tick (env-dev-08, 2026-09-09). On a host where the tunneller was
|
> first refresh and then fails every tick (env-dev-08, 2026-09-09). On a host where the tunneller was
|
||||||
> installed independently of the kit, check `id monky-deployd` for `ziti` before anything else.
|
> installed independently of the kit, check `id monky-deployd` for `ziti` before anything else.
|
||||||
|
|
||||||
|
> **Upgrading the agent.** `dpkg -i` keeps the timer enabled from 0.1.9 on. On a box upgraded from
|
||||||
|
> 0.1.8 or earlier the old package's `prerm` already ran and **disabled** it — check
|
||||||
|
> `systemctl is-enabled monky-deployd.timer` after the upgrade and `systemctl enable --now` it if needed.
|
||||||
|
|
||||||
## Reading the journal
|
## Reading the journal
|
||||||
|
|
||||||
| line | meaning |
|
| line | meaning |
|
||||||
@@ -40,7 +45,7 @@ the `ziti` **group**, plus an explicit ACL `u:monky-deployd:r` and a default ACL
|
|||||||
| `refused: DISK_INSUFFICIENT: image storage (…) has N MiB free, …` | free space: grow the disk or prune. The paths in the message are every filesystem a pull can fill — docker's data-root AND containerd's root, which docker 29 fills with image layers and which is often a different disk (env-dev-08). A bundle that declares no size must still clear `disk.headroom_bytes` |
|
| `refused: DISK_INSUFFICIENT: image storage (…) has N MiB free, …` | free space: grow the disk or prune. The paths in the message are every filesystem a pull can fill — docker's data-root AND containerd's root, which docker 29 fills with image layers and which is often a different disk (env-dev-08). A bundle that declares no size must still clear `disk.headroom_bytes` |
|
||||||
| `refused: PRIVILEGED_REFUSED` / `ROLLBACK_REFUSED` | the bundle needs `allow_privileged` / `allow_rollback` in its `agent` profile |
|
| `refused: PRIVILEGED_REFUSED` / `ROLLBACK_REFUSED` | the bundle needs `allow_privileged` / `allow_rollback` in its `agent` profile |
|
||||||
| `temporary network failure` (exit 75) | mesh/tenancy unreachable — check `ziti-edge-tunnel`, the identity's terminators, `monky.tenancy.deploy` health |
|
| `temporary network failure` (exit 75) | mesh/tenancy unreachable — check `ziti-edge-tunnel`, the identity's terminators, `monky.tenancy.deploy` health |
|
||||||
| `transport sdk: identity … is not readable by this user` | the agent lost its read on the identity file (usually a tunneller rewrite dropping the ACL) — `usermod -a -G ziti monky-deployd` |
|
| `transport sdk: identity … is not readable by this user` | the agent lost its read on the identity file — `ziti-edge-tunnel` re-created it with mode `0600`, which sets the ACL mask to `---` (group membership does not help then). Run `/usr/share/monky-deployd/identity-acl.sh` and check `systemctl is-active monky-deployd-identity-acl.path` (0.1.10 re-applies it on every directory change) |
|
||||||
| `AGENT_UNAUTHENTICATED: bearer refused` (exit 1) | the grant was superseded (kit re-revealed / retire) or the token revoked → re-run the install kit |
|
| `AGENT_UNAUTHENTICATED: bearer refused` (exit 1) | the grant was superseded (kit re-revealed / retire) or the token revoked → re-run the install kit |
|
||||||
| `AGENT_ENV_MISMATCH` (exit 78) | the token belongs to another env than `config.yaml` — fix the config or re-issue the identity; the timer keeps firing but every tick exits 78 immediately (no storm) |
|
| `AGENT_ENV_MISMATCH` (exit 78) | the token belongs to another env than `config.yaml` — fix the config or re-issue the identity; the timer keeps firing but every tick exits 78 immediately (no storm) |
|
||||||
| `failed: docker compose pull failed (rc=1)` | registry/pull problem; compose output is in the report's tail and in the journal |
|
| `failed: docker compose pull failed (rc=1)` | registry/pull problem; compose output is in the report's tail and in the journal |
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ Dials monky-tenancy over the mesh with the box's host identity, fetches the rend
|
|||||||
leases a deploy grant, logs in to OpenBao, reads its own secrets, runs `docker compose`,
|
leases a deploy grant, logs in to OpenBao, reads its own secrets, runs `docker compose`,
|
||||||
reports. Stdlib only; the optional `openziti` SDK is the `sdk` transport."""
|
reports. Stdlib only; the optional `openziti` SDK is the `sdk` transport."""
|
||||||
|
|
||||||
__version__ = "0.1.8"
|
__version__ = "0.1.10"
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ from pathlib import Path
|
|||||||
DEFAULT_CONFIG_PATH = "/etc/monky-deployd/config.yaml"
|
DEFAULT_CONFIG_PATH = "/etc/monky-deployd/config.yaml"
|
||||||
TRANSPORTS = ("sdk", "proxy", "system")
|
TRANSPORTS = ("sdk", "proxy", "system")
|
||||||
ENV_ID_RE = re.compile(r"^env-(dev|qa|stage|prod)-[0-9]{2,3}$|^(dev-env-2|prod-cedar)$")
|
ENV_ID_RE = re.compile(r"^env-(dev|qa|stage|prod)-[0-9]{2,3}$|^(dev-env-2|prod-cedar)$")
|
||||||
SITES = ("cbs", "pdx")
|
# tenancy 0.7.x issues `fmt | pdx | roam` (doc 24 §1.4a); `cbs` is the deprecated alias of `fmt`
|
||||||
|
# that every row registered before 2026-09-08 still carries. Keep the two sets in step (deployd#3).
|
||||||
|
SITES = ("fmt", "cbs", "pdx", "roam")
|
||||||
|
|
||||||
|
|
||||||
class ConfigError(Exception):
|
class ConfigError(Exception):
|
||||||
|
|||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# monky-deployd: (re)grant the agent read access to the host's ziti identity file(s).
|
||||||
|
# Idempotent; safe to run at any time. Invoked by install.sh, the package postinstall and the
|
||||||
|
# monky-deployd-identity-acl.path unit (whenever the identity directory changes).
|
||||||
|
#
|
||||||
|
# Why a re-runnable script and not a one-time ACL: ziti-edge-tunnel re-creates the identity on
|
||||||
|
# every controller config update with mode 0600. On a file with an ACL that sets the mask to ---,
|
||||||
|
# so the named-user entry AND the ziti-group read both become ineffective. Only re-applying the
|
||||||
|
# entries after each rewrite keeps the agent alive.
|
||||||
|
set -eu
|
||||||
|
DIR="${1:-/opt/openziti/etc/identities}"
|
||||||
|
[ -d "$DIR" ] || exit 0
|
||||||
|
command -v setfacl >/dev/null 2>&1 || exit 0
|
||||||
|
setfacl -m u:monky-deployd:rx,m::rx "$DIR" 2>/dev/null || true
|
||||||
|
setfacl -d -m u:monky-deployd:r,m::r "$DIR" 2>/dev/null || true
|
||||||
|
for f in "$DIR"/*.json; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
setfacl -m u:monky-deployd:r,m::r "$f" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
# T=<read-only GitLab deploy token, scope read_package_registry> # from the install kit / OpenBao
|
# T=<read-only GitLab deploy token, scope read_package_registry> # from the install kit / OpenBao
|
||||||
# curl -sSf -H "DEPLOY-TOKEN: $T" \
|
# curl -sSf -H "DEPLOY-TOKEN: $T" \
|
||||||
# https://scm.tikali.ai/api/v4/projects/69/packages/generic/monky-deployd/0.1.6/install.sh \
|
# https://scm.tikali.ai/api/v4/projects/69/packages/generic/monky-deployd/0.1.6/install.sh \
|
||||||
# | sudo bash -s -- --env env-qa-02 --site cbs --token "$T" --bootstrap-file bootstrap.jwt \
|
# | sudo bash -s -- --env env-qa-02 --site fmt --token "$T" --bootstrap-file bootstrap.jwt \
|
||||||
# [--transport sdk|proxy|system] [--version 0.1.6] [--enrol-jwt /path/monky-host.env-qa-02.jwt] \
|
# [--transport sdk|proxy|system] [--version 0.1.6] [--enrol-jwt /path/monky-host.env-qa-02.jwt] \
|
||||||
# [--laptop] [--source gitlab|gitea] [--docker-data-root /home/docker-data]
|
# [--laptop] [--source gitlab|gitea] [--docker-data-root /home/docker-data]
|
||||||
#
|
#
|
||||||
@@ -77,7 +77,7 @@ done
|
|||||||
[ -n "$SITE" ] || die "--site is required"
|
[ -n "$SITE" ] || die "--site is required"
|
||||||
[[ "$ENV_ID" =~ ^env-(dev|qa|stage|prod)-[0-9]{2,3}$|^(dev-env-2|prod-cedar)$ ]] || die "env id $ENV_ID is not env-<tier>-<nn>"
|
[[ "$ENV_ID" =~ ^env-(dev|qa|stage|prod)-[0-9]{2,3}$|^(dev-env-2|prod-cedar)$ ]] || die "env id $ENV_ID is not env-<tier>-<nn>"
|
||||||
SITE="${SITE,,}"
|
SITE="${SITE,,}"
|
||||||
[[ "$SITE" =~ ^(cbs|pdx)$ ]] || die "site must be cbs|pdx"
|
[[ "$SITE" =~ ^(fmt|cbs|pdx|roam)$ ]] || die "site must be fmt|cbs|pdx|roam (tenancy issues fmt|pdx|roam; cbs = the deprecated alias of fmt)"
|
||||||
[[ "$TRANSPORT" =~ ^(sdk|proxy|system)$ ]] || die "transport must be sdk|proxy|system"
|
[[ "$TRANSPORT" =~ ^(sdk|proxy|system)$ ]] || die "transport must be sdk|proxy|system"
|
||||||
[[ "$SOURCE" =~ ^(gitlab|gitea)$ ]] || die "source must be gitlab|gitea"
|
[[ "$SOURCE" =~ ^(gitlab|gitea)$ ]] || die "source must be gitlab|gitea"
|
||||||
# never let the token leak through xtrace / the environment of children
|
# never let the token leak through xtrace / the environment of children
|
||||||
@@ -219,10 +219,14 @@ install -d -m 0700 -o monky-deployd -g monky-deployd /var/lib/monky-deployd
|
|||||||
# window before the agent's next login and hosts where the file has another group.
|
# window before the agent's next login and hosts where the file has another group.
|
||||||
# A default ACL on the directory carries the grant onto a freshly created identity file.
|
# A default ACL on the directory carries the grant onto a freshly created identity file.
|
||||||
if getent group ziti >/dev/null; then usermod -a -G ziti monky-deployd || true; fi
|
if getent group ziti >/dev/null; then usermod -a -G ziti monky-deployd || true; fi
|
||||||
setfacl -m u:monky-deployd:r "$IDENTITY"
|
|
||||||
setfacl -m u:monky-deployd:rx "$IDENTITY_DIR"
|
|
||||||
setfacl -d -m u:monky-deployd:r "$IDENTITY_DIR" 2>/dev/null || true
|
|
||||||
setfacl -m u:monky-deployd:x /opt/openziti/etc 2>/dev/null || true
|
setfacl -m u:monky-deployd:x /opt/openziti/etc 2>/dev/null || true
|
||||||
|
# The grant must OUTLIVE the tunneller: ziti-edge-tunnel re-creates the identity file on every
|
||||||
|
# controller config update with mode 0600, which sets the ACL mask to --- and defeats both the
|
||||||
|
# named-user entry and the ziti-group read (env-dev-08, 2026-09-11..13: two days of "identity is
|
||||||
|
# not readable" ticks while the tunnel was healthy). identity-acl.sh re-applies the entries and the
|
||||||
|
# mask; the .path unit re-runs it whenever the directory changes.
|
||||||
|
/usr/share/monky-deployd/identity-acl.sh "$IDENTITY_DIR"
|
||||||
|
systemctl enable --now monky-deployd-identity-acl.path 2>/dev/null || true
|
||||||
if [ -n "$BAO_CA" ]; then
|
if [ -n "$BAO_CA" ]; then
|
||||||
install -m 0644 "$BAO_CA" "$ETC/openbao-ca.pem"
|
install -m 0644 "$BAO_CA" "$ETC/openbao-ca.pem"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -33,6 +33,14 @@ contents:
|
|||||||
dst: /usr/lib/systemd/system/monky-deployd.timer
|
dst: /usr/lib/systemd/system/monky-deployd.timer
|
||||||
- src: ./packaging/systemd/monky-deployd-proxy.service
|
- src: ./packaging/systemd/monky-deployd-proxy.service
|
||||||
dst: /usr/lib/systemd/system/monky-deployd-proxy.service
|
dst: /usr/lib/systemd/system/monky-deployd-proxy.service
|
||||||
|
- src: ./packaging/systemd/monky-deployd-identity-acl.path
|
||||||
|
dst: /usr/lib/systemd/system/monky-deployd-identity-acl.path
|
||||||
|
- src: ./packaging/systemd/monky-deployd-identity-acl.service
|
||||||
|
dst: /usr/lib/systemd/system/monky-deployd-identity-acl.service
|
||||||
|
- src: ./packaging/bin/identity-acl.sh
|
||||||
|
dst: /usr/share/monky-deployd/identity-acl.sh
|
||||||
|
file_info:
|
||||||
|
mode: 0755
|
||||||
- src: ./packaging/monky-deployd.sysusers
|
- src: ./packaging/monky-deployd.sysusers
|
||||||
dst: /usr/lib/sysusers.d/monky-deployd.conf
|
dst: /usr/lib/sysusers.d/monky-deployd.conf
|
||||||
- src: ./packaging/monky-deployd.tmpfiles
|
- src: ./packaging/monky-deployd.tmpfiles
|
||||||
|
|||||||
@@ -18,10 +18,18 @@ if getent group docker >/dev/null; then usermod -a -G docker monky-deployd || tr
|
|||||||
# POSIX ACL granting the agent read — group membership is the grant that survives it.
|
# POSIX ACL granting the agent read — group membership is the grant that survives it.
|
||||||
# (env-dev-08, 2026-09-09: the agent went from applied to "no intercept" 6 minutes after a refresh.)
|
# (env-dev-08, 2026-09-09: the agent went from applied to "no intercept" 6 minutes after a refresh.)
|
||||||
if getent group ziti >/dev/null; then usermod -a -G ziti monky-deployd || true; fi
|
if getent group ziti >/dev/null; then usermod -a -G ziti monky-deployd || true; fi
|
||||||
|
# ...and group membership does NOT survive it either once the rewrite lands with mode 0600 (the ACL
|
||||||
|
# mask goes to ---). Re-apply the grant now and on every directory change (0.1.10, deployd#3 beat).
|
||||||
|
[ -x /usr/share/monky-deployd/identity-acl.sh ] && /usr/share/monky-deployd/identity-acl.sh /opt/openziti/etc/identities || true
|
||||||
# the venv is relocatable only to the path it was built at; refuse a broken interpreter early
|
# the venv is relocatable only to the path it was built at; refuse a broken interpreter early
|
||||||
/opt/monky-deployd/venv/bin/python -c 'import monky_deployd' || { echo "monky-deployd: venv unusable (python3 mismatch?)" >&2; exit 1; }
|
/opt/monky-deployd/venv/bin/python -c 'import monky_deployd' || { echo "monky-deployd: venv unusable (python3 mismatch?)" >&2; exit 1; }
|
||||||
if [ -d /run/systemd/system ]; then
|
if [ -d /run/systemd/system ]; then
|
||||||
systemctl daemon-reload || true
|
systemctl daemon-reload || true
|
||||||
# do NOT enable the timer here: install.sh / the ansible role do it after the config exists
|
# do NOT enable the timer here: install.sh / the ansible role do it after the config exists.
|
||||||
|
# An UPGRADE is different — the timer is already enabled and must keep running, so restart the
|
||||||
|
# long-lived proxy unit onto the new code. `try-restart` is a no-op when it is not running.
|
||||||
|
systemctl try-restart monky-deployd-proxy.service 2>/dev/null || true
|
||||||
|
# an UPGRADE of a box that already has its config: arm the identity-ACL watcher
|
||||||
|
if [ -s /etc/monky-deployd/config.yaml ]; then systemctl enable --now monky-deployd-identity-acl.path 2>/dev/null || true; fi
|
||||||
fi
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
# dpkg calls the OLD package's prerm on an UPGRADE as well as on a removal, and rpm calls it with
|
||||||
|
# an install count. Disabling the timer unconditionally therefore stopped the agent on every
|
||||||
|
# upgrade and left it disabled — silently, because the box stays reachable and nothing else
|
||||||
|
# notices that check-ins have ceased (env-dev-01 and env-dev-08, 2026-09-09).
|
||||||
|
# dpkg: "$1" is `remove`, `upgrade <new-version>`, `deconfigure …` or `failed-upgrade`
|
||||||
|
# rpm : "$1" is the number of instances that will remain — 1 on upgrade, 0 on uninstall
|
||||||
|
case "${1:-}" in
|
||||||
|
upgrade | failed-upgrade | deconfigure | 1) exit 0 ;;
|
||||||
|
esac
|
||||||
if [ -d /run/systemd/system ]; then
|
if [ -d /run/systemd/system ]; then
|
||||||
systemctl disable --now monky-deployd.timer 2>/dev/null || true
|
systemctl disable --now monky-deployd.timer 2>/dev/null || true
|
||||||
systemctl disable --now monky-deployd-proxy.service 2>/dev/null || true
|
systemctl disable --now monky-deployd-proxy.service 2>/dev/null || true
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Re-grant monky-deployd read access when the ziti identity directory changes
|
||||||
|
Documentation=file:/usr/share/doc/monky-deployd/OPERATIONS.md
|
||||||
|
|
||||||
|
[Path]
|
||||||
|
PathChanged=/opt/openziti/etc/identities
|
||||||
|
PathModified=/opt/openziti/etc/identities
|
||||||
|
Unit=monky-deployd-identity-acl.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Re-grant monky-deployd read access to the ziti identity file(s)
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/share/monky-deployd/identity-acl.sh /opt/openziti/etc/identities
|
||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "monky-deployd"
|
name = "monky-deployd"
|
||||||
version = "0.1.8"
|
version = "0.1.10"
|
||||||
description = "Monky backend pull agent: checkin -> bundle -> lease -> OpenBao -> docker compose -> report, over the ziti mesh (MONKY-ADR-0028)"
|
description = "Monky backend pull agent: checkin -> bundle -> lease -> OpenBao -> docker compose -> report, over the ziti mesh (MONKY-ADR-0028)"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|||||||
@@ -74,6 +74,15 @@ def test_config_rejects_approle_and_unknown_keys():
|
|||||||
c.from_dict({"env_id": "env-dev-06", "site": "sfo"})
|
c.from_dict({"env_id": "env-dev-06", "site": "sfo"})
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_sites_match_tenancy():
|
||||||
|
"""tenancy 0.7.x registers `fmt | pdx | roam`; `cbs` stays as the deprecated alias every row
|
||||||
|
registered before 2026-09-08 carries (deployd#3: kits died with 'site must be cbs|pdx')."""
|
||||||
|
assert set(c.SITES) == {"fmt", "cbs", "pdx", "roam"}
|
||||||
|
for site in ("fmt", "roam", "pdx", "cbs"):
|
||||||
|
assert c.from_dict({"env_id": "env-dev-06", "site": site}).site == site
|
||||||
|
assert c.from_dict({"env_id": "env-dev-06", "site": "FMT"}).site == "fmt"
|
||||||
|
|
||||||
|
|
||||||
def test_sdk_identity_defaults_to_host_identity():
|
def test_sdk_identity_defaults_to_host_identity():
|
||||||
cfg = c.from_dict({"env_id": "env-dev-07", "site": "cbs"})
|
cfg = c.from_dict({"env_id": "env-dev-07", "site": "cbs"})
|
||||||
assert cfg.identity == "/opt/openziti/etc/identities/monky-host.env-dev-07.json"
|
assert cfg.identity == "/opt/openziti/etc/identities/monky-host.env-dev-07.json"
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
"""The maintainer scripts must not stop the agent on an upgrade.
|
||||||
|
|
||||||
|
dpkg calls the OLD package's prerm on an upgrade as well as on a removal, and rpm calls it with
|
||||||
|
an install count. `systemctl disable --now` there stopped the agent on every upgrade and left it
|
||||||
|
disabled — silently, because the box stays reachable and nothing else notices that check-ins have
|
||||||
|
ceased (env-dev-01 and env-dev-08, 2026-09-09).
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
PREREMOVE = Path(__file__).resolve().parents[1] / "packaging" / "scripts" / "preremove.sh"
|
||||||
|
|
||||||
|
|
||||||
|
def _run(arg: str, tmp_path: Path) -> list[str]:
|
||||||
|
"""Run preremove with a fake `systemctl` on PATH and report the calls it made."""
|
||||||
|
calls = tmp_path / "systemctl.log"
|
||||||
|
fake = tmp_path / "bin"
|
||||||
|
fake.mkdir(exist_ok=True)
|
||||||
|
(fake / "systemctl").write_text(f'#!/bin/sh\necho "$@" >> {calls}\nexit 0\n')
|
||||||
|
(fake / "systemctl").chmod(0o755)
|
||||||
|
env = {"PATH": f"{fake}:/usr/bin:/bin"}
|
||||||
|
r = subprocess.run(["sh", str(PREREMOVE), arg], env=env, capture_output=True, text=True)
|
||||||
|
assert r.returncode == 0, r.stderr
|
||||||
|
return calls.read_text().splitlines() if calls.exists() else []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(not Path("/run/systemd/system").is_dir(), reason="needs a systemd host to reach the disable branch")
|
||||||
|
@pytest.mark.parametrize("arg", ["remove", "0"])
|
||||||
|
def test_a_real_removal_disables_the_units(arg, tmp_path):
|
||||||
|
assert any("disable" in c for c in _run(arg, tmp_path))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("arg", ["upgrade", "failed-upgrade", "deconfigure", "1"])
|
||||||
|
def test_an_upgrade_leaves_the_units_alone(arg, tmp_path):
|
||||||
|
assert _run(arg, tmp_path) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_script_is_shell_clean():
|
||||||
|
assert shutil.which("sh")
|
||||||
|
subprocess.run(["sh", "-n", str(PREREMOVE)], check=True)
|
||||||
Reference in New Issue
Block a user