underpost 3.2.28 → 3.2.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ghpkg.ci.yml +87 -0
- package/.github/workflows/npmpkg.ci.yml +9 -6
- package/.github/workflows/pwa-microservices-template-page.cd.yml +0 -7
- package/CHANGELOG.md +161 -1
- package/CLI-HELP.md +17 -6
- package/README.md +2 -2
- package/bin/build.js +30 -0
- package/bin/deploy.js +2 -2
- package/bump.config.js +1 -0
- package/docker-compose.yml +26 -26
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/package.json +10 -10
- package/scripts/disk-clean.sh +85 -60
- package/scripts/test-monitor.sh +3 -5
- package/src/cli/cluster.js +77 -4
- package/src/cli/deploy.js +121 -9
- package/src/cli/docker-compose.js +58 -1
- package/src/cli/env.js +11 -2
- package/src/cli/fs.js +45 -24
- package/src/cli/image.js +129 -51
- package/src/cli/index.js +35 -6
- package/src/cli/release.js +46 -4
- package/src/cli/repository.js +166 -22
- package/src/cli/run.js +273 -118
- package/src/cli/secrets.js +82 -48
- package/src/cli/ssh.js +44 -0
- package/src/client.build.js +0 -2
- package/src/db/mongo/MongoBootstrap.js +12 -12
- package/src/index.js +1 -1
- package/src/server/catalog.js +2 -0
- package/src/server/conf.js +0 -3
- package/src/server/runtime-status.js +18 -1
- package/src/server/start.js +12 -2
- package/src/server.js +5 -1
- package/test/deploy-monitor.test.js +26 -10
package/docker-compose.yml
CHANGED
|
@@ -26,7 +26,7 @@ services:
|
|
|
26
26
|
mongodb:
|
|
27
27
|
image: ${MONGO_IMAGE:-mongo:latest}
|
|
28
28
|
container_name: dd-mongodb
|
|
29
|
-
entrypoint: [
|
|
29
|
+
entrypoint: ['bash', '/docker-init/entrypoint.sh']
|
|
30
30
|
environment:
|
|
31
31
|
MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME:?set MONGO_INITDB_ROOT_USERNAME in docker/compose.env}
|
|
32
32
|
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD:?set MONGO_INITDB_ROOT_PASSWORD in docker/compose.env}
|
|
@@ -38,9 +38,9 @@ services:
|
|
|
38
38
|
networks:
|
|
39
39
|
- dd-internal
|
|
40
40
|
expose:
|
|
41
|
-
-
|
|
41
|
+
- '27017'
|
|
42
42
|
ports:
|
|
43
|
-
-
|
|
43
|
+
- '${MONGO_HOST_PORT:-27017}:27017'
|
|
44
44
|
healthcheck:
|
|
45
45
|
test:
|
|
46
46
|
- CMD-SHELL
|
|
@@ -58,18 +58,18 @@ services:
|
|
|
58
58
|
valkey-service:
|
|
59
59
|
image: ${VALKEY_IMAGE:-valkey/valkey:latest}
|
|
60
60
|
container_name: dd-valkey
|
|
61
|
-
command: [
|
|
61
|
+
command: ['valkey-server', '--port', '6379', '--bind', '0.0.0.0', '--protected-mode', 'no']
|
|
62
62
|
volumes:
|
|
63
63
|
- valkey-data:/data
|
|
64
64
|
networks:
|
|
65
65
|
- dd-internal
|
|
66
66
|
expose:
|
|
67
|
-
-
|
|
67
|
+
- '6379'
|
|
68
68
|
# NodePort equivalent (manifests/valkey/valkey-nodeport.yaml nodePort 32079).
|
|
69
69
|
ports:
|
|
70
|
-
-
|
|
70
|
+
- '${VALKEY_NODEPORT:-32079}:6379'
|
|
71
71
|
healthcheck:
|
|
72
|
-
test: [
|
|
72
|
+
test: ['CMD', 'valkey-cli', '-p', '6379', 'ping']
|
|
73
73
|
interval: 10s
|
|
74
74
|
timeout: 5s
|
|
75
75
|
retries: 10
|
|
@@ -81,7 +81,7 @@ services:
|
|
|
81
81
|
# (dd-default-development-blue). Connection targets use Docker service
|
|
82
82
|
# discovery instead of hardcoded localhost.
|
|
83
83
|
app:
|
|
84
|
-
image: ${APP_IMAGE:-underpost/underpost-engine}:${APP_TAG:-v3.2.
|
|
84
|
+
image: ${APP_IMAGE:-underpost/underpost-engine}:${APP_TAG:-v3.2.70}
|
|
85
85
|
container_name: dd-app
|
|
86
86
|
# The start command is supplied by the generated override docker/compose.app.yml
|
|
87
87
|
# (see `underpost docker-compose --generate --deploy-id <id>`), keeping this
|
|
@@ -100,18 +100,18 @@ services:
|
|
|
100
100
|
networks:
|
|
101
101
|
- dd-internal
|
|
102
102
|
expose:
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
-
|
|
106
|
-
-
|
|
103
|
+
- '4001'
|
|
104
|
+
- '4002'
|
|
105
|
+
- '4003'
|
|
106
|
+
- '4004'
|
|
107
107
|
# Direct access to the LoadBalancer-equivalent ports (manifest 4001-4004).
|
|
108
108
|
ports:
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
109
|
+
- '${APP_PORT_4001:-4001}:4001'
|
|
110
|
+
- '${APP_PORT_4002:-4002}:4002'
|
|
111
|
+
- '${APP_PORT_4003:-4003}:4003'
|
|
112
|
+
- '${APP_PORT_4004:-4004}:4004'
|
|
113
113
|
healthcheck:
|
|
114
|
-
test: [
|
|
114
|
+
test: ['CMD-SHELL', "timeout 2 bash -c '</dev/tcp/127.0.0.1/4001' || exit 1"]
|
|
115
115
|
interval: 15s
|
|
116
116
|
timeout: 5s
|
|
117
117
|
retries: 5
|
|
@@ -134,9 +134,9 @@ services:
|
|
|
134
134
|
networks:
|
|
135
135
|
- dd-internal
|
|
136
136
|
ports:
|
|
137
|
-
-
|
|
137
|
+
- '${PROXY_HTTP_PORT:-80}:80'
|
|
138
138
|
healthcheck:
|
|
139
|
-
test: [
|
|
139
|
+
test: ['CMD', 'wget', '-q', '-O', '-', 'http://127.0.0.1/healthz']
|
|
140
140
|
interval: 15s
|
|
141
141
|
timeout: 5s
|
|
142
142
|
retries: 5
|
|
@@ -162,11 +162,11 @@ services:
|
|
|
162
162
|
networks:
|
|
163
163
|
- dd-internal
|
|
164
164
|
expose:
|
|
165
|
-
-
|
|
165
|
+
- '9090'
|
|
166
166
|
ports:
|
|
167
|
-
-
|
|
167
|
+
- '${PROMETHEUS_PORT:-9090}:9090'
|
|
168
168
|
healthcheck:
|
|
169
|
-
test: [
|
|
169
|
+
test: ['CMD', 'wget', '-q', '-O', '-', 'http://127.0.0.1:9090/-/healthy']
|
|
170
170
|
interval: 15s
|
|
171
171
|
timeout: 5s
|
|
172
172
|
retries: 5
|
|
@@ -185,18 +185,18 @@ services:
|
|
|
185
185
|
environment:
|
|
186
186
|
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
|
|
187
187
|
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:-admin}
|
|
188
|
-
GF_USERS_ALLOW_SIGN_UP:
|
|
188
|
+
GF_USERS_ALLOW_SIGN_UP: 'false'
|
|
189
189
|
volumes:
|
|
190
190
|
- ./docker/grafana/provisioning:/etc/grafana/provisioning:ro
|
|
191
191
|
- grafana-data:/var/lib/grafana
|
|
192
192
|
networks:
|
|
193
193
|
- dd-internal
|
|
194
194
|
expose:
|
|
195
|
-
-
|
|
195
|
+
- '3000'
|
|
196
196
|
ports:
|
|
197
|
-
-
|
|
197
|
+
- '${GRAFANA_PORT:-3000}:3000'
|
|
198
198
|
healthcheck:
|
|
199
|
-
test: [
|
|
199
|
+
test: ['CMD', 'wget', '-q', '-O', '-', 'http://127.0.0.1:3000/api/health']
|
|
200
200
|
interval: 15s
|
|
201
201
|
timeout: 5s
|
|
202
202
|
retries: 5
|
|
@@ -17,7 +17,7 @@ spec:
|
|
|
17
17
|
spec:
|
|
18
18
|
containers:
|
|
19
19
|
- name: dd-default-development-blue
|
|
20
|
-
image: underpost/underpost-engine:v3.2.
|
|
20
|
+
image: underpost/underpost-engine:v3.2.70
|
|
21
21
|
# resources:
|
|
22
22
|
# requests:
|
|
23
23
|
# memory: "124Ki"
|
|
@@ -98,7 +98,7 @@ spec:
|
|
|
98
98
|
spec:
|
|
99
99
|
containers:
|
|
100
100
|
- name: dd-default-development-green
|
|
101
|
-
image: underpost/underpost-engine:v3.2.
|
|
101
|
+
image: underpost/underpost-engine:v3.2.70
|
|
102
102
|
# resources:
|
|
103
103
|
# requests:
|
|
104
104
|
# memory: "124Ki"
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"type": "module",
|
|
3
3
|
"main": "src/index.js",
|
|
4
4
|
"name": "underpost",
|
|
5
|
-
"version": "3.2.
|
|
5
|
+
"version": "3.2.70",
|
|
6
6
|
"description": "Underpost Platform — end-to-end CI/CD and application-delivery toolchain CLI. Covers bare metal, Kubernetes, K3s, kubeadm, LXD, container/image orchestration, secrets, databases, cron jobs, monitoring, SSH, runners, PWA + Workbox delivery, and release orchestration. Extensible via downstream CLIs.",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"start": "node --max-old-space-size=8192 src/server",
|
|
@@ -71,14 +71,14 @@
|
|
|
71
71
|
},
|
|
72
72
|
"homepage": "https://github.com/underpostnet/pwa-microservices-template#readme",
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@fortawesome/fontawesome-free": "^7.
|
|
74
|
+
"@fortawesome/fontawesome-free": "^7.3.0",
|
|
75
75
|
"@fullcalendar/rrule": "^6.1.21",
|
|
76
76
|
"@grpc/grpc-js": "^1.14.4",
|
|
77
77
|
"@grpc/proto-loader": "^0.8.1",
|
|
78
78
|
"@neodrag/vanilla": "^2.3.1",
|
|
79
|
-
"adm-zip": "^0.5.
|
|
80
|
-
"ag-grid-community": "^
|
|
81
|
-
"axios": "^1.18.
|
|
79
|
+
"adm-zip": "^0.5.18",
|
|
80
|
+
"ag-grid-community": "^36.0.0",
|
|
81
|
+
"axios": "^1.18.1",
|
|
82
82
|
"bumpp": "^11.1.0",
|
|
83
83
|
"chai": "^6.2.2",
|
|
84
84
|
"clipboardy": "^5.3.1",
|
|
@@ -100,11 +100,11 @@
|
|
|
100
100
|
"express-slow-down": "^3.1.0",
|
|
101
101
|
"fast-json-stable-stringify": "^2.1.0",
|
|
102
102
|
"favicons": "^7.3.0",
|
|
103
|
-
"fs-extra": "^11.3.
|
|
103
|
+
"fs-extra": "^11.3.6",
|
|
104
104
|
"fullcalendar": "^6.1.21",
|
|
105
105
|
"helmet": "^8.2.0",
|
|
106
106
|
"html-minifier-terser": "^7.2.0",
|
|
107
|
-
"http-proxy-middleware": "^4.
|
|
107
|
+
"http-proxy-middleware": "^4.2.0",
|
|
108
108
|
"ignore-walk": "^9.0.0",
|
|
109
109
|
"iovalkey": "^0.3.3",
|
|
110
110
|
"json-colorizer": "^3.0.1",
|
|
@@ -112,9 +112,9 @@
|
|
|
112
112
|
"mariadb": "^3.5.3",
|
|
113
113
|
"marked": "^18.0.5",
|
|
114
114
|
"mocha": "^11.7.6",
|
|
115
|
-
"mongoose": "^9.7.
|
|
115
|
+
"mongoose": "^9.7.3",
|
|
116
116
|
"morgan": "^1.11.0",
|
|
117
|
-
"nodemailer": "^9.0.
|
|
117
|
+
"nodemailer": "^9.0.3",
|
|
118
118
|
"nodemon": "^3.0.1",
|
|
119
119
|
"peer": "^1.0.2",
|
|
120
120
|
"peerjs": "^1.5.5",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"split-file": "^2.3.0",
|
|
129
129
|
"swagger-autogen": "^2.23.7",
|
|
130
130
|
"swagger-ui-express": "^5.0.0",
|
|
131
|
-
"typedoc": "^0.28.
|
|
131
|
+
"typedoc": "^0.28.20",
|
|
132
132
|
"typescript": "^6.0.3",
|
|
133
133
|
"validator": "^13.15.35",
|
|
134
134
|
"vanilla-jsoneditor": "^3.12.0",
|
package/scripts/disk-clean.sh
CHANGED
|
@@ -7,20 +7,20 @@ set -euo pipefail
|
|
|
7
7
|
|
|
8
8
|
VACUUM_SIZE="200M" # journalctl vacuum target
|
|
9
9
|
LARGE_LOG_SIZE="+100M" # threshold for truncation (find syntax)
|
|
10
|
-
TMP_AGE_DAYS=
|
|
11
|
-
CACHE_AGE_DAYS=
|
|
10
|
+
TMP_AGE_DAYS=1 # remove files older than this from /tmp and /var/tmp
|
|
11
|
+
CACHE_AGE_DAYS=5 # remove caches older than this from /var/cache
|
|
12
12
|
KEEP_KERNELS=2 # keep this many latest kernels
|
|
13
13
|
REMOVE_OPT=0 # ALWAYS allow removing /opt entries (user requested)
|
|
14
14
|
|
|
15
15
|
timestamp() { date +"%F %T"; }
|
|
16
16
|
log() {
|
|
17
|
-
|
|
17
|
+
echo "$(timestamp) $*"
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
# must be root
|
|
21
21
|
if [ "$EUID" -ne 0 ]; then
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
echo "This script must be run as root. Exiting."
|
|
23
|
+
exit 1
|
|
24
24
|
fi
|
|
25
25
|
|
|
26
26
|
log "=== Starting Rocky Linux 9 automated cleanup (batch mode) ==="
|
|
@@ -46,8 +46,8 @@ journalctl --vacuum-size="$VACUUM_SIZE"
|
|
|
46
46
|
# 3) Truncate very large logs in /var/log (safer than delete)
|
|
47
47
|
log "Truncating logs in /var/log larger than ${LARGE_LOG_SIZE} (keeps zero-sized file so services don't break)..."
|
|
48
48
|
find /var/log -type f -size "$LARGE_LOG_SIZE" -print0 2>/dev/null | while IFS= read -r -d '' f; do
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
echo "Truncating $f"
|
|
50
|
+
: > "$f" || echo "Failed to truncate $f"
|
|
51
51
|
done
|
|
52
52
|
|
|
53
53
|
# 4) Clean /tmp and /var/tmp older than TMP_AGE_DAYS
|
|
@@ -62,87 +62,110 @@ find /var/cache -mindepth 1 -mtime +"$CACHE_AGE_DAYS" -print0 2>/dev/null | xarg
|
|
|
62
62
|
# 6) Clean user caches (~/.cache) and Downloads older than CACHE_AGE_DAYS
|
|
63
63
|
log "Cleaning user caches and old downloads (home dirs)..."
|
|
64
64
|
for homedir in /home/* /root; do
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
65
|
+
[ -d "$homedir" ] || continue
|
|
66
|
+
usercache="$homedir/.cache"
|
|
67
|
+
userdownloads="$homedir/Downloads"
|
|
68
|
+
usertrash="$homedir/.local/share/Trash"
|
|
69
|
+
|
|
70
|
+
if [ -d "$usercache" ]; then
|
|
71
|
+
log "Removing contents of $usercache"
|
|
72
|
+
rm -rf "${usercache:?}/"* 2>/dev/null
|
|
73
|
+
fi
|
|
74
|
+
if [ -d "$userdownloads" ]; then
|
|
75
|
+
log "Removing files older than ${CACHE_AGE_DAYS} days from $userdownloads"
|
|
76
|
+
find "$userdownloads" -type f -mtime +"$CACHE_AGE_DAYS" -print0 2>/dev/null | xargs -0r rm -f -- 2>/dev/null
|
|
77
|
+
fi
|
|
78
|
+
if [ -d "$usertrash" ]; then
|
|
79
|
+
log "Emptying trash in $usertrash"
|
|
80
|
+
rm -rf "${usertrash:?}/"* 2>/dev/null
|
|
81
|
+
fi
|
|
82
82
|
done
|
|
83
83
|
|
|
84
|
-
# 7) Docker / Podman cleanup (if present)
|
|
84
|
+
# 7) Docker / Podman cleanup (if present) — this is what actually reclaims the
|
|
85
|
+
# overlay storage behind those duplicated `overlay` df lines.
|
|
85
86
|
if command -v docker >/dev/null 2>&1; then
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
log "Docker detected: pruning images/containers/volumes/build cache (aggressive)..."
|
|
88
|
+
docker system df || true
|
|
89
|
+
docker system prune -a --volumes -f || true
|
|
90
|
+
docker builder prune -a -f || true
|
|
89
91
|
fi
|
|
90
92
|
|
|
91
93
|
if command -v podman >/dev/null 2>&1; then
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
log "Podman detected: pruning images/containers/volumes (aggressive)..."
|
|
95
|
+
podman system df || true
|
|
96
|
+
podman system prune -a --volumes -f || true
|
|
95
97
|
fi
|
|
96
98
|
|
|
99
|
+
if command -v buildah >/dev/null 2>&1; then
|
|
100
|
+
log "Buildah detected: removing leftover working containers..."
|
|
101
|
+
buildah rm --all || true
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# 7b) Unmount leaked container overlay 'merged' mounts. Pruning frees the data
|
|
105
|
+
# but leaves these mountpoints attached, so they keep flooding `df -h` with
|
|
106
|
+
# identical `overlay ... /merged` rows. Only unmount overlays not backing a
|
|
107
|
+
# still-existing container, so running workloads are never disturbed.
|
|
108
|
+
log "Unmounting orphaned container overlay mounts..."
|
|
109
|
+
if command -v podman >/dev/null 2>&1; then
|
|
110
|
+
podman umount --all >/dev/null 2>&1 || true
|
|
111
|
+
fi
|
|
112
|
+
active_merged="$(podman ps -aq 2>/dev/null | xargs -r -I{} podman inspect --format '{{.GraphDriver.Data.MergedDir}}' {} 2>/dev/null || true)"
|
|
113
|
+
findmnt -rn -o TARGET 2>/dev/null | grep -E '/var/lib/(containers/storage|docker)/overlay.*/merged' | sort -r | while IFS= read -r m; do
|
|
114
|
+
if ! printf '%s\n' "$active_merged" | grep -qxF "$m"; then
|
|
115
|
+
echo "Unmounting orphaned overlay: $m"
|
|
116
|
+
umount -l "$m" 2>/dev/null || true
|
|
117
|
+
fi
|
|
118
|
+
done
|
|
119
|
+
|
|
97
120
|
# 8) Flatpak unused runtimes/apps (if present)
|
|
98
121
|
if command -v flatpak >/dev/null 2>&1; then
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
122
|
+
log "Flatpak detected: trying to uninstall unused runtimes/apps..."
|
|
123
|
+
flatpak uninstall --unused -y || flatpak uninstall --unused
|
|
124
|
+
flatpak repair
|
|
102
125
|
fi
|
|
103
126
|
|
|
104
127
|
# 9) Python Pip cleanup
|
|
105
128
|
if command -v pip3 >/dev/null 2>&1 || command -v pip >/dev/null 2>&1; then
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
129
|
+
log "Python Pip detected: cleaning cache..."
|
|
130
|
+
if command -v pip3 >/dev/null 2>&1; then
|
|
131
|
+
pip3 cache purge
|
|
132
|
+
elif command -v pip >/dev/null 2>&1; then
|
|
133
|
+
pip cache purge
|
|
134
|
+
fi
|
|
112
135
|
fi
|
|
113
136
|
|
|
114
137
|
# 10) Conda cleanup
|
|
115
138
|
if command -v conda >/dev/null 2>&1; then
|
|
116
|
-
|
|
117
|
-
|
|
139
|
+
log "Conda detected: cleaning all..."
|
|
140
|
+
conda clean --all -y
|
|
118
141
|
fi
|
|
119
142
|
|
|
120
143
|
# 11) Remove old kernels but keep the last KEEP_KERNELS (safe)
|
|
121
144
|
log "Removing old kernels, keeping the last $KEEP_KERNELS kernels..."
|
|
122
145
|
OLD_KERNELS=$(dnf repoquery --installonly --latest-limit=-$KEEP_KERNELS -q 2>/dev/null)
|
|
123
146
|
if [ -n "$OLD_KERNELS" ]; then
|
|
124
|
-
|
|
125
|
-
|
|
147
|
+
log "Old kernels to remove: $OLD_KERNELS"
|
|
148
|
+
dnf -y remove $OLD_KERNELS
|
|
126
149
|
else
|
|
127
|
-
|
|
150
|
+
log "No old kernels found by DNF repoquery. Only $KEEP_KERNELS or fewer are currently installed."
|
|
128
151
|
fi
|
|
129
152
|
|
|
130
153
|
# 12) /opt review and removal (ON by default now)
|
|
131
154
|
if [ -d /opt ]; then
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
log "/opt usage (top entries):"
|
|
156
|
+
du -sh /opt/* 2>/dev/null | sort -h | head -n 20
|
|
157
|
+
|
|
158
|
+
if [ "$REMOVE_OPT" = "1" ]; then
|
|
159
|
+
OPT_TARGETS=(/opt/local-path-provisioner)
|
|
160
|
+
for t in "${OPT_TARGETS[@]}"; do
|
|
161
|
+
if [ -d "$t" ]; then
|
|
162
|
+
log "Removing $t as REMOVE_OPT=1"
|
|
163
|
+
rm -rf "$t"
|
|
164
|
+
fi
|
|
165
|
+
done
|
|
166
|
+
else
|
|
167
|
+
log "Automatic /opt removals disabled (set REMOVE_OPT=1 to enable)."
|
|
168
|
+
fi
|
|
146
169
|
fi
|
|
147
170
|
|
|
148
171
|
# 13) Find large files > 100MB (report only)
|
|
@@ -150,8 +173,10 @@ log "Listing files larger than 100MB (report only):"
|
|
|
150
173
|
find / -xdev -type f -size +100M -printf '%s\t%p\n' 2>/dev/null | sort -nr | head -n 50 | awk '{printf "%.1fMB\t%s\n",$1/1024/1024,$2}'
|
|
151
174
|
|
|
152
175
|
# Final disk usage
|
|
153
|
-
log "Disk usage
|
|
176
|
+
log "Disk usage cleanup:"
|
|
154
177
|
df -h
|
|
178
|
+
log "Top-level usage ( / ):"
|
|
179
|
+
du -xh --max-depth=1 / | sort -rh | head -n 20
|
|
155
180
|
|
|
156
181
|
log "=== Cleanup finished ==="
|
|
157
182
|
exit 0
|
package/scripts/test-monitor.sh
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# test-monitor.sh — end-to-end deploy + two-phase monitor smoke test.
|
|
4
4
|
#
|
|
5
|
-
# Two deployment shapes are supported
|
|
6
|
-
# src/client/public/nexodev/docs/references/Deploy-Monitor-PRD.md and
|
|
7
|
-
# 'Deploy custom instance to K8S.md'):
|
|
5
|
+
# Two deployment shapes are supported:
|
|
8
6
|
#
|
|
9
7
|
# --mode runtime `underpost start` deploy (e.g. dd-test). Monitored with the
|
|
10
8
|
# HTTP gate: /_internal/ready probes + port-forward status.
|
|
@@ -26,11 +24,11 @@ MODE=runtime # runtime | instance
|
|
|
26
24
|
ENV=development # development | production
|
|
27
25
|
DEPLOY_ID=dd-test # deploy id (instance mode: parent of conf.instances.json)
|
|
28
26
|
INSTANCE_IDS= # instance mode: csv of ids (default: all in conf.instances.json)
|
|
29
|
-
IMAGE=underpost/wp:v3.2.
|
|
27
|
+
IMAGE=underpost/wp:v3.2.70 # runtime mode image (instance mode reads image from conf)
|
|
30
28
|
VERSIONS=green # csv of blue/green versions
|
|
31
29
|
REPLICAS=1 # replicas per deployment
|
|
32
30
|
NAMESPACE=default # k8s namespace
|
|
33
|
-
CLUSTER=
|
|
31
|
+
CLUSTER=kind # kind | kubeadm | k3s | "" (auto/none)
|
|
34
32
|
TIMEOUT_RESPONSE=300000ms # HTTPProxy per-route response timeout
|
|
35
33
|
TEMPLATE_REPO=underpostnet/pwa-microservices-template-private # runtime mode link repo
|
|
36
34
|
ENVOY_NAMESPACE=projectcontour # ingress namespace (instance TLS exposure)
|
package/src/cli/cluster.js
CHANGED
|
@@ -876,6 +876,74 @@ net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-k3s.conf > /dev/null`,
|
|
|
876
876
|
}
|
|
877
877
|
},
|
|
878
878
|
|
|
879
|
+
/**
|
|
880
|
+
* @method _pruneContainerCaches
|
|
881
|
+
* @description Reclaims container-runtime disk left behind after a cluster
|
|
882
|
+
* teardown: stopped containers, unused images, build cache and anonymous
|
|
883
|
+
* volumes. Best-effort across every runtime present on the host (docker,
|
|
884
|
+
* podman, and optionally the CRI runtime via crictl). Each block is guarded
|
|
885
|
+
* by a command-existence check, so it is safe to call when a runtime is
|
|
886
|
+
* absent. This is what turns a "cluster deleted" into "disk actually freed":
|
|
887
|
+
* `kind delete` / `kubeadm reset` remove the cluster but leave gigabytes of
|
|
888
|
+
* images and overlay layers under /var/lib/{docker,containers}.
|
|
889
|
+
* @param {object} [options]
|
|
890
|
+
* @param {boolean} [options.all=true] - Remove all unused images, not just dangling ones.
|
|
891
|
+
* @param {boolean} [options.crictl=false] - Also prune the CRI runtime via crictl.
|
|
892
|
+
* @param {string} [options.criSocket] - Optional crictl --runtime-endpoint override.
|
|
893
|
+
* @private
|
|
894
|
+
*/
|
|
895
|
+
_pruneContainerCaches(options = {}) {
|
|
896
|
+
const all = options.all !== false;
|
|
897
|
+
const a = all ? '-a ' : '';
|
|
898
|
+
logger.info(` -> Pruning container-runtime caches (all=${all})...`);
|
|
899
|
+
// Docker (also matches the podman-docker shim when docker is symlinked to podman).
|
|
900
|
+
shellExec(
|
|
901
|
+
`if command -v docker >/dev/null 2>&1; then sudo docker system prune ${a}--volumes -f; sudo docker builder prune ${a}-f; fi`,
|
|
902
|
+
{ silentOnError: true },
|
|
903
|
+
);
|
|
904
|
+
// Podman native — on this host images/overlays live under /var/lib/containers/storage.
|
|
905
|
+
shellExec(
|
|
906
|
+
`if command -v podman >/dev/null 2>&1; then sudo podman system prune ${a}--volumes -f; fi`,
|
|
907
|
+
{ silentOnError: true },
|
|
908
|
+
);
|
|
909
|
+
if (options.crictl) {
|
|
910
|
+
const ep = options.criSocket ? `--runtime-endpoint ${options.criSocket} ` : '';
|
|
911
|
+
shellExec(
|
|
912
|
+
`if command -v crictl >/dev/null 2>&1; then sudo env PATH="$PATH:/usr/local/bin:/usr/bin" crictl ${ep}rmi --prune; fi`,
|
|
913
|
+
{ silentOnError: true },
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
Underpost.cluster._unmountOrphanContainerOverlays();
|
|
917
|
+
},
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* @method _unmountOrphanContainerOverlays
|
|
921
|
+
* @description Unmounts leaked container overlay 'merged' mounts under
|
|
922
|
+
* /var/lib/{containers/storage,docker}/overlay. Pruning images/containers
|
|
923
|
+
* frees the backing data but leaves these mountpoints attached, so they
|
|
924
|
+
* keep showing up as identical `overlay ... /merged` rows in `df -h` long
|
|
925
|
+
* after the containers are gone. Only overlays NOT backing a still-existing
|
|
926
|
+
* container are unmounted, so running workloads are never disturbed.
|
|
927
|
+
* Best-effort; safe to call when no runtime is present.
|
|
928
|
+
* @private
|
|
929
|
+
*/
|
|
930
|
+
_unmountOrphanContainerOverlays() {
|
|
931
|
+
logger.info(' -> Unmounting orphaned container overlay mounts...');
|
|
932
|
+
shellExec(`if command -v podman >/dev/null 2>&1; then sudo podman umount --all >/dev/null 2>&1 || true; fi`, {
|
|
933
|
+
silentOnError: true,
|
|
934
|
+
});
|
|
935
|
+
shellExec(
|
|
936
|
+
`active="$(sudo podman ps -aq 2>/dev/null | xargs -r -I{} sudo podman inspect --format '{{.GraphDriver.Data.MergedDir}}' {} 2>/dev/null || true)"
|
|
937
|
+
findmnt -rn -o TARGET 2>/dev/null | grep -E '/var/lib/(containers/storage|docker)/overlay.*/merged' | sort -r | while IFS= read -r m; do
|
|
938
|
+
if ! printf '%s\\n' "$active" | grep -qxF "$m"; then
|
|
939
|
+
echo "Unmounting orphaned overlay: $m"
|
|
940
|
+
sudo umount -l "$m" 2>/dev/null || true
|
|
941
|
+
fi
|
|
942
|
+
done`,
|
|
943
|
+
{ silentOnError: true },
|
|
944
|
+
);
|
|
945
|
+
},
|
|
946
|
+
|
|
879
947
|
/**
|
|
880
948
|
* @method _lazyUmountKubeletMounts
|
|
881
949
|
* @description Lazy-unmounts every mount under /var/lib/kubelet so a
|
|
@@ -910,7 +978,7 @@ net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-k3s.conf > /dev/null`,
|
|
|
910
978
|
if (options.removeVolumeHostPaths) Underpost.cluster._cleanHostPathPvs();
|
|
911
979
|
else logger.info(' -> Skipping (pass --remove-volume-host-paths to enable).');
|
|
912
980
|
|
|
913
|
-
logger.info('Phase 3/
|
|
981
|
+
logger.info('Phase 3/6: Deleting all Kind clusters...');
|
|
914
982
|
shellExec(`clusters=$(kind get clusters)
|
|
915
983
|
if [ -n "$clusters" ]; then
|
|
916
984
|
for c in $clusters; do
|
|
@@ -919,11 +987,14 @@ if [ -n "$clusters" ]; then
|
|
|
919
987
|
done
|
|
920
988
|
fi`);
|
|
921
989
|
|
|
922
|
-
logger.info('Phase 4/
|
|
990
|
+
logger.info('Phase 4/6: Cleaning kubeconfig and Kind Docker networks...');
|
|
923
991
|
shellExec(`rm -rf "$HOME/.kube"`);
|
|
924
992
|
Underpost.cluster.recoverKindDockerNetworks();
|
|
925
993
|
|
|
926
|
-
logger.info('Phase 5/
|
|
994
|
+
logger.info('Phase 5/6: Pruning container-runtime caches (kindest/node images, build cache, volumes)...');
|
|
995
|
+
Underpost.cluster._pruneContainerCaches({ all: true });
|
|
996
|
+
|
|
997
|
+
logger.info('Phase 6/6: Re-applying host configuration (Docker, containerd, sysctl).');
|
|
927
998
|
Underpost.cluster.config();
|
|
928
999
|
|
|
929
1000
|
logger.info('=== KIND SAFE RESET COMPLETE ===');
|
|
@@ -995,7 +1066,7 @@ fi`);
|
|
|
995
1066
|
shellExec(`if ip link show tunl0 >/dev/null 2>&1; then sudo ip link del tunl0; fi`);
|
|
996
1067
|
shellExec(`sudo iptables -F`);
|
|
997
1068
|
shellExec(`sudo iptables -t nat -F`);
|
|
998
|
-
|
|
1069
|
+
Underpost.cluster._pruneContainerCaches({ all: true, crictl: true });
|
|
999
1070
|
|
|
1000
1071
|
logger.info('Phase 7/7: Re-applying host configuration (Docker, containerd, sysctl).');
|
|
1001
1072
|
Underpost.cluster.config();
|
|
@@ -1042,6 +1113,8 @@ fi`);
|
|
|
1042
1113
|
shellExec(`if [ -d /etc/rancher/k3s ]; then sudo rm -rf /etc/rancher/k3s; fi`);
|
|
1043
1114
|
shellExec(`if ip link show flannel.1 >/dev/null 2>&1; then sudo ip link del flannel.1; fi`);
|
|
1044
1115
|
shellExec(`if ip link show cni0 >/dev/null 2>&1; then sudo ip link del cni0; fi`);
|
|
1116
|
+
// k3s-uninstall.sh removes /var/lib/rancher/k3s; still prune any host docker/podman leftovers.
|
|
1117
|
+
Underpost.cluster._pruneContainerCaches({ all: true });
|
|
1045
1118
|
|
|
1046
1119
|
logger.info('Phase 5/5: Re-applying minimal K3s host config.');
|
|
1047
1120
|
Underpost.cluster.configMinimalK3s();
|