kampodine 0.4.0 → 0.6.0

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/scripts/status.sh CHANGED
@@ -1,44 +1,164 @@
1
1
  #!/usr/bin/env bash
2
- # status.sh — one command: what is LIVE (through the proxy) + the blue/green
3
- # pair view (instances, reserved IP, health).
2
+ # status.sh — one command: deployment count (ledger), what is LIVE (through
3
+ # the proxy), the VM's disk/image/service state (with --host), and the
4
+ # blue/green pair view.
4
5
  #
5
6
  # Usage:
6
- # kampodine status
7
+ # kampodine status [--host root@<ip>] [--ssh-key <path>]
7
8
  #
8
- # Env: APP_HOST_HEADER (default: app.example.com), OCI_PROFILE, OCI_COMPARTMENT.
9
+ # Without --host: live health + the deployment count (all hosts). With
10
+ # --host: adds VM disk usage (LOUD warning above 90%), the sha-tagged image
11
+ # count with a reclaimable-by-prune estimate, and service states
12
+ # (kampodine-api, kamal-proxy, walshipper if present).
13
+ #
14
+ # Env: APP_HOST_HEADER (default: app.example.com), KAMPODINE_HOST,
15
+ # KAMPODINE_SSH_KEY, OCI_PROFILE, OCI_COMPARTMENT.
9
16
  set -euo pipefail
10
17
  HERE="$(cd "$(dirname "$0")" && pwd)"
11
- HOST="${APP_HOST_HEADER:-app.example.com}"
18
+ # shellcheck source=common.sh
19
+ source "$HERE/common.sh"
20
+
21
+ HOST_HEADER="${PROFILE_PROXY_HOST:-${APP_HOST_HEADER:-app.example.com}}"
22
+ IMAGE="127.0.0.1:5000/kampodine-api"
23
+ DISK_PATH="/var/lib/containers"
24
+ KAMPODINE_HOST="${KAMPODINE_HOST:-}"
25
+ if [ -n "${KAMPODINE_SSH_KEY:-}" ]; then
26
+ SSH_KEY="$KAMPODINE_SSH_KEY"
27
+ else
28
+ SSH_KEY=""
29
+ fi
30
+ PROFILE_FLAG=""
31
+ HOST_FLAG=""
32
+ KEY_FLAG=""
33
+ VERBOSE=0
12
34
 
13
35
  say() { printf '%s\n' "$*"; }
14
36
  die() { printf '[status] FAIL: %s\n' "$*" >&2; exit 1; }
15
37
  usage() {
16
38
  cat <<'EOF'
17
39
  Usage:
18
- kampodine status
40
+ kampodine status [--host root@<ip>] [--profile <name>] [--ssh-key <path>] [--verbose]
19
41
 
20
42
  Examples:
21
- kampodine status # live health (proxy host) + the blue/green pair view
43
+ kampodine status # deployments (ledger) + live health + blue/green pair
44
+ kampodine status --host root@203.0.113.10 # + VM disk usage, image/prune estimate, service states
45
+ kampodine status --profile prod # resolve host/key from a config profile
46
+ kampodine status --host root@203.0.113.10 --verbose # + the full metrics snapshot
47
+ # (load, memory, disk breakdown, containers, top procs)
22
48
 
23
- Env: APP_HOST_HEADER (default app.example.com), OCI_PROFILE, OCI_COMPARTMENT.
49
+ Env: APP_HOST_HEADER (default app.example.com), KAMPODINE_HOST,
50
+ KAMPODINE_SSH_KEY, KAMPODINE_PROFILE, OCI_PROFILE, OCI_COMPARTMENT.
24
51
  EOF
25
52
  exit 0
26
53
  }
27
54
 
28
55
  while [[ $# -gt 0 ]]; do
29
56
  case "$1" in
57
+ --host) HOST_FLAG="$2"; KAMPODINE_HOST="$2"; shift 2 ;;
58
+ --ssh-key) KEY_FLAG="$2"; SSH_KEY="$2"; shift 2 ;;
59
+ --profile) PROFILE_FLAG="$2"; shift 2 ;;
60
+ --verbose) VERBOSE=1; shift ;;
30
61
  -h|--help) usage ;;
31
62
  *) die "unknown argument: $1 (--help)" ;;
32
63
  esac
33
64
  done
34
65
 
35
- say "== live (through the proxy: https://$HOST) =="
36
- if body="$(curl -sf -m 8 "https://$HOST/api/auth/ok" 2>/dev/null)"; then
66
+ # profile resolution (flag > KAMPODINE_PROFILE > defaultProfile); an explicit
67
+ # --host/--ssh-key flag always beats the profile
68
+ profile_resolve "$PROFILE_FLAG" "$HOST_FLAG" "$KEY_FLAG"
69
+ SSH_KEY="${KEY_FLAG:-${KAMPODINE_SSH_KEY:-}}"
70
+
71
+ # --- deployment count (the owner's "total deployments", always visible) -------
72
+ if [[ -n "$KAMPODINE_HOST" ]]; then
73
+ say "== deployments (ledger: $(ledger_file)) =="
74
+ ledger_total_line "$(ledger_count "$KAMPODINE_HOST")" "deployments to $KAMPODINE_HOST"
75
+ else
76
+ say "== deployments (ledger: $(ledger_file)) =="
77
+ ledger_total_line "$(ledger_count)" "across all hosts — pass --host root@<ip> for VM state"
78
+ if [[ $VERBOSE -eq 1 ]]; then
79
+ say "metrics snapshot: needs a target — add --host root@<ip> (or --profile <name>)"
80
+ fi
81
+ fi
82
+ say
83
+
84
+ say "== live (through the proxy: https://$HOST_HEADER) =="
85
+ if body="$(curl -sf -m 8 "https://$HOST_HEADER/api/auth/ok" 2>/dev/null)"; then
37
86
  say "HEALTH OK: $body"
38
- say "build-id : $(curl -sf -m 8 "https://$HOST/build-id.txt" 2>/dev/null || echo unreachable)"
87
+ say "build-id : $(curl -sf -m 8 "https://$HOST_HEADER/build-id.txt" 2>/dev/null || echo unreachable)"
39
88
  else
40
89
  say "UNREACHABLE or unhealthy — check the VM (ssh) and kamal-proxy"
41
90
  fi
91
+
92
+ if [[ -n "$KAMPODINE_HOST" ]]; then
93
+ SSH_ARGS=(-o ConnectTimeout=10 -o BatchMode=yes)
94
+ [[ -n "$SSH_KEY" ]] && SSH_ARGS+=(-i "$SSH_KEY")
95
+ # $1 is a composed remote command — client-side expansion is the design.
96
+ # shellcheck disable=SC2029
97
+ vm() { ssh "${SSH_ARGS[@]}" "$KAMPODINE_HOST" "$1"; }
98
+ if [[ "$(uname -s)" == "Darwin" ]]; then
99
+ SSH_AUTH_SOCK="$(launchctl getenv SSH_AUTH_SOCK 2>/dev/null || true)"
100
+ export SSH_AUTH_SOCK
101
+ fi
102
+
103
+ say
104
+ say "== VM ($KAMPODINE_HOST) =="
105
+ df_out="$(vm "df -P $DISK_PATH 2>/dev/null" || true)"
106
+ pct="$(disk_pct_from_df "$df_out")"
107
+ case "$(disk_verdict "$pct" "")" in
108
+ ok) say "disk : ${pct}% used on $DISK_PATH" ;;
109
+ warn)
110
+ say "disk : ${pct}% used on $DISK_PATH"
111
+ say "WARNING : VM disk above 90% — old sha-tagged deploy images pile up (~1GB each); reclaim: kampodine deploy prune --dry-run"
112
+ ;;
113
+ *) say "disk : unknown (df unreadable)" ;;
114
+ esac
115
+
116
+ images_raw="$(vm "podman images --format '{{.Tag}}|{{.CreatedAt}}|{{.Size}}' $IMAGE 2>/dev/null" || true)"
117
+ images="$(printf '%s\n' "$images_raw" | grep -E '^[0-9a-f]{7,40}\|' || true)"
118
+ running="$(vm "podman ps --format '{{.Image}}' 2>/dev/null" || true)"
119
+ img_count="$(printf '%s\n' "$images" | grep -c . || true)"
120
+ reclaim="$(prune_select "$images" "$running" 2 || true)"
121
+ reclaim_n="0"
122
+ reclaim_tags="(none)"
123
+ reclaim_size="~0 MB"
124
+ if [[ -n "$reclaim" ]]; then
125
+ reclaim_n="$(printf '%s\n' "$reclaim" | grep -c . || true)"
126
+ reclaim_tags="$(printf '%s\n' "$reclaim" | cut -d'|' -f1 | paste -sd, -)"
127
+ reclaim_size="$(sum_sizes_human "$(printf '%s\n' "$reclaim" | cut -d'|' -f2)")"
128
+ fi
129
+ say "images : ${img_count:-0} sha-tagged deploy image(s); prune would remove ${reclaim_n} ${reclaim_tags} (${reclaim_size}): kampodine deploy prune --dry-run"
130
+
131
+ # init detection (groundwork for non-Alpine targets): the roll call keeps
132
+ # the historical shape on Alpine (byte-identical "for s in … rc-service …")
133
+ # and swaps the probe command on systemd hosts.
134
+ init_detect vm >/dev/null 2>&1 || true
135
+ case "$INIT_SYSTEM" in
136
+ systemd) svc_probe='systemctl status "$s"' ;;
137
+ *) svc_probe='rc-service "$s" status' ;;
138
+ esac
139
+ say "services:"
140
+ vm "for s in kampodine-api kamal-proxy walshipper; do if $svc_probe >/dev/null 2>&1; then echo \"\$s: running\"; else echo \"\$s: not-running\"; fi; done" \
141
+ || say "(service roll call failed)"
142
+
143
+ if [[ $VERBOSE -eq 1 ]]; then
144
+ say
145
+ say "== metrics snapshot =="
146
+ if metrics_raw="$(vm "$METRICS_REMOTE_CMD" 2>/dev/null)"; then
147
+ metrics_render "$metrics_raw"
148
+ metrics_pct="$(disk_pct_from_df "$M_DISK")"
149
+ if [[ -n "$metrics_pct" ]] && [[ "$metrics_pct" -gt 90 ]]; then
150
+ say "WARNING : root disk above 90% — reclaim: kampodine deploy prune --dry-run"
151
+ fi
152
+ else
153
+ say "(metrics snapshot failed — VM unreachable?)"
154
+ fi
155
+ fi
156
+ fi
157
+
42
158
  say
43
159
  say "== blue/green pair =="
44
- exec bash "$HERE/bluegreen.sh" status
160
+ if [[ -n "$PROFILE_FLAG" ]]; then
161
+ exec bash "$HERE/bluegreen.sh" status --profile "$PROFILE_FLAG"
162
+ else
163
+ exec bash "$HERE/bluegreen.sh" status
164
+ fi
@@ -35,6 +35,7 @@
35
35
  # not a restart).
36
36
  #
37
37
  # kampodine vm-prepare --host root@<new-ip>
38
+ # kampodine vm-prepare --profile <name> # host/key from ~/.kampodine/config.json
38
39
  # ... --pull-images # + pre-pull the app image over the registry tunnel
39
40
  # ... --ssh-key <path> # ssh identity (default: agent / KAMPODINE_SSH_KEY)
40
41
  set -euo pipefail
@@ -42,35 +43,48 @@ set -euo pipefail
42
43
  HOST=""
43
44
  DO_PULL=0
44
45
  SSH_KEY="${KAMPODINE_SSH_KEY:-}"
46
+ PROFILE_FLAG=""
47
+ HOST_FLAG=""
48
+ KEY_FLAG=""
49
+ HERE="$(cd "$(dirname "$0")" && pwd)"
50
+ # shellcheck source=common.sh
51
+ source "$HERE/common.sh"
45
52
 
46
53
  say() { printf '\033[1;32m[vm-prepare]\033[0m %s\n' "$*"; }
47
54
  die() { printf '\033[1;31m[vm-prepare] FAIL:\033[0m %s\n' "$*" >&2; exit 1; }
48
55
  usage() {
49
56
  cat <<'EOF'
50
57
  Usage:
51
- kampodine vm-prepare --host root@<new-ip> [--pull-images] [--ssh-key <path>]
58
+ kampodine vm-prepare --host root@<new-ip> [--pull-images] [--ssh-key <path>] [--profile <name>]
52
59
 
53
60
  Examples:
54
61
  EOF
55
62
  grep '^# kampodine vm-prepare' "$0" | sed 's/^# //'
56
63
  cat <<'EOF'
57
64
 
58
- Host/key resolution: --host | (no env default — explicit flag);
59
- --ssh-key | KAMPODINE_SSH_KEY | ssh-agent / ~/.ssh/config.
65
+ Host/key resolution: --host | --profile <name> | KAMPODINE_PROFILE |
66
+ config defaultProfile; --ssh-key | profile sshKey | KAMPODINE_SSH_KEY |
67
+ ssh-agent / ~/.ssh/config.
60
68
  EOF
61
69
  exit 0
62
70
  }
63
71
 
64
72
  while [[ $# -gt 0 ]]; do
65
73
  case "$1" in
66
- --host) HOST="$2"; shift 2 ;;
74
+ --host) HOST_FLAG="$2"; HOST="$2"; shift 2 ;;
67
75
  --pull-images) DO_PULL=1; shift ;;
68
- --ssh-key) SSH_KEY="$2"; shift 2 ;;
76
+ --ssh-key) KEY_FLAG="$2"; SSH_KEY="$2"; shift 2 ;;
77
+ --profile) PROFILE_FLAG="$2"; shift 2 ;;
69
78
  -h|--help) usage ;;
70
79
  *) die "unknown argument: $1 (--help)" ;;
71
80
  esac
72
81
  done
73
- [[ -n "$HOST" ]] || die "--host root@<ip> required (--help for usage)"
82
+ # profile resolution (flag > KAMPODINE_PROFILE > defaultProfile); the explicit
83
+ # --host/--ssh-key flags always beat the profile
84
+ profile_resolve "$PROFILE_FLAG" "${HOST_FLAG:-}" "${KEY_FLAG:-}"
85
+ SSH_KEY="${KEY_FLAG:-${KAMPODINE_SSH_KEY:-}}"
86
+ [[ -z "$HOST" ]] && HOST="${KAMPODINE_HOST:-}"
87
+ [[ -n "$HOST" ]] || die "--host root@<ip> required (--profile <name> or KAMPODINE_HOST also work; --help for usage)"
74
88
 
75
89
  SSH_ARGS=(-o ConnectTimeout=10 -o BatchMode=yes -o StrictHostKeyChecking=accept-new)
76
90
  [[ -n "$SSH_KEY" ]] && SSH_ARGS+=(-i "$SSH_KEY")