-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsmoke-test.sh
More file actions
executable file
·233 lines (209 loc) · 8.55 KB
/
Copy pathsmoke-test.sh
File metadata and controls
executable file
·233 lines (209 loc) · 8.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'USAGE'
Usage: compose/smoke-test.sh [full|sqlite-local|postgresql-local|sqlite-s3|relay-sqlite-local] [-- <simclient args>]
Runs a Docker Compose smoke stack, waits for the private admin dashboard, then runs
the Go simulator against the containerized server.
Environment:
PROOFLINE_MAIN_PORT Host port for the main API/viewer. Default: 18080
PROOFLINE_ADMIN_PORT Host port for private-admin routes. Default: 18081
PROOFLINE_RELAY_PORT Host port for the stream-ingress relay smoke variant. Default: 18090
PROOFLINE_PRIVATE_PORT Legacy alias for PROOFLINE_MAIN_PORT.
PROOFLINE_PUBLIC_PORT Legacy alias for PROOFLINE_ADMIN_PORT.
PROOFLINE_SMOKE_BOOTSTRAP_SECRET Local bootstrap secret for the container.
PROOFLINE_SMOKE_USERNAME Local account username. Default: admin
PROOFLINE_SMOKE_PASSWORD Local account password.
PROOFLINE_SMOKE_RELAY_SERVICE_TOKEN Local relay-to-core service token.
PROOFLINE_SMOKE_RELAY_CAPABILITY_SECRET Local core relay capability secret.
PROOFLINE_SMOKE_SECRETS_DIR Secret-file directory mounted into TOML stacks.
COMPOSE_PROJECT_NAME Compose project name. Default: proofline-smoke-<variant>
KEEP_COMPOSE=1 Leave containers and volumes running after the test.
USAGE
}
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "$script_dir/.." && pwd)"
variant="full"
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi
if [[ $# -gt 0 && "$1" != "--" ]]; then
variant="$1"
shift
fi
if [[ $# -gt 0 && "$1" == "--" ]]; then
shift
fi
case "$variant" in
full)
compose_file="$script_dir/compose-full.yml"
;;
sqlite-local)
compose_file="$script_dir/compose-sqlite-local.yml"
;;
postgresql-local)
compose_file="$script_dir/compose-postgresql-local.yml"
;;
sqlite-s3)
compose_file="$script_dir/compose-sqlite-s3.yml"
;;
relay-sqlite-local)
compose_file="$script_dir/compose-relay-sqlite-local.yml"
;;
*)
usage >&2
exit 2
;;
esac
if docker compose version >/dev/null 2>&1; then
compose=(docker compose)
elif command -v docker-compose >/dev/null 2>&1; then
compose=(docker-compose)
else
echo "docker compose or docker-compose is required" >&2
exit 1
fi
if ! command -v curl >/dev/null 2>&1; then
echo "curl is required to wait for the containerized private admin dashboard" >&2
exit 1
fi
export PROOFLINE_MAIN_PORT="${PROOFLINE_MAIN_PORT:-${PROOFLINE_PRIVATE_PORT:-18080}}"
export PROOFLINE_ADMIN_PORT="${PROOFLINE_ADMIN_PORT:-${PROOFLINE_PUBLIC_PORT:-18081}}"
export PROOFLINE_RELAY_PORT="${PROOFLINE_RELAY_PORT:-18090}"
export PROOFLINE_SMOKE_BOOTSTRAP_SECRET="${PROOFLINE_SMOKE_BOOTSTRAP_SECRET:-replace-with-local-compose-bootstrap-secret}"
export PROOFLINE_SMOKE_USERNAME="${PROOFLINE_SMOKE_USERNAME:-admin}"
export PROOFLINE_SMOKE_PASSWORD="${PROOFLINE_SMOKE_PASSWORD:-replace-with-a-long-local-password}"
export PROOFLINE_SMOKE_RELAY_SERVICE_TOKEN="${PROOFLINE_SMOKE_RELAY_SERVICE_TOKEN:-replace-with-local-relay-service-token}"
export PROOFLINE_SMOKE_RELAY_CAPABILITY_SECRET="${PROOFLINE_SMOKE_RELAY_CAPABILITY_SECRET:-replace-with-local-relay-capability-secret}"
export PROOFLINE_SMOKE_POSTGRES_DSN="${PROOFLINE_SMOKE_POSTGRES_DSN:-postgres://proofline:proofline@postgres:5432/proofline?sslmode=disable}"
export PROOFLINE_SMOKE_S3_ACCESS_KEY_ID="${PROOFLINE_SMOKE_S3_ACCESS_KEY_ID:-proofline}"
export PROOFLINE_SMOKE_S3_SECRET_ACCESS_KEY="${PROOFLINE_SMOKE_S3_SECRET_ACCESS_KEY:-proofline-minio-password}"
export PROOFLINE_SMOKE_VALKEY_PASSWORD="${PROOFLINE_SMOKE_VALKEY_PASSWORD:-proofline-valkey-password}"
project="${COMPOSE_PROJECT_NAME:-proofline-smoke-${variant}}"
default_runtime_secrets_dir="$script_dir/.smoke-secrets/$project"
export PROOFLINE_SMOKE_SECRETS_DIR="${PROOFLINE_SMOKE_SECRETS_DIR:-$default_runtime_secrets_dir}"
sim_args=("$@")
cleanup() {
status=$?
if [[ "${KEEP_COMPOSE:-0}" == "1" ]]; then
echo "Leaving compose stack running: project=$project file=$compose_file"
exit "$status"
fi
"${compose[@]}" -p "$project" -f "$compose_file" down -v --remove-orphans >/dev/null 2>&1 || true
rm -rf "$default_runtime_secrets_dir" 2>/dev/null || true
exit "$status"
}
trap cleanup EXIT
prepare_smoke_secrets() {
mkdir -p "$PROOFLINE_SMOKE_SECRETS_DIR"
chmod 755 "$PROOFLINE_SMOKE_SECRETS_DIR"
printf '%s\n' "$PROOFLINE_SMOKE_BOOTSTRAP_SECRET" >"$PROOFLINE_SMOKE_SECRETS_DIR/auth-bootstrap-secret.example"
printf '%s\n' "$PROOFLINE_SMOKE_POSTGRES_DSN" >"$PROOFLINE_SMOKE_SECRETS_DIR/postgres-dsn.example"
printf '%s\n' "$PROOFLINE_SMOKE_S3_ACCESS_KEY_ID" >"$PROOFLINE_SMOKE_SECRETS_DIR/s3-access-key-id.example"
printf '%s\n' "$PROOFLINE_SMOKE_S3_SECRET_ACCESS_KEY" >"$PROOFLINE_SMOKE_SECRETS_DIR/s3-secret-access-key.example"
printf '%s\n' "$PROOFLINE_SMOKE_VALKEY_PASSWORD" >"$PROOFLINE_SMOKE_SECRETS_DIR/valkey-password.example"
chmod 644 "$PROOFLINE_SMOKE_SECRETS_DIR"/*.example
}
wait_for_admin_dashboard() {
local url="http://127.0.0.1:${PROOFLINE_ADMIN_PORT}/admin/static/styles.css"
for _ in $(seq 1 60); do
if curl --fail --silent --output /dev/null "$url"; then
return 0
fi
sleep 1
done
return 1
}
wait_for_relay_readiness() {
local live_url="http://127.0.0.1:${PROOFLINE_RELAY_PORT}/health/live"
local ready_url="http://127.0.0.1:${PROOFLINE_RELAY_PORT}/health/ready"
for _ in $(seq 1 60); do
if curl --fail --silent --output /dev/null "$live_url" &&
curl --fail --silent --output /dev/null "$ready_url"; then
return 0
fi
sleep 1
done
return 1
}
assert_relay_does_not_mount_server_routes() {
local route
local status
for route in /admin /admin/api/accounts /v1/incidents /i/viewer-token /metrics; do
status="$(curl --silent --show-error --output /dev/null --write-out "%{http_code}" "http://127.0.0.1:${PROOFLINE_RELAY_PORT}${route}")"
if [[ "$status" != "404" ]]; then
echo "relay route ${route} returned HTTP ${status}, want 404" >&2
return 1
fi
done
}
bootstrap_admin() {
local url="http://127.0.0.1:${PROOFLINE_ADMIN_PORT}/admin/bootstrap"
local response_file
local status
response_file="$(mktemp)"
status="$(curl --silent --show-error --output "$response_file" --write-out "%{http_code}" \
-X POST "$url" \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "bootstrap_secret=${PROOFLINE_SMOKE_BOOTSTRAP_SECRET}" \
--data-urlencode "username=${PROOFLINE_SMOKE_USERNAME}" \
--data-urlencode "password=${PROOFLINE_SMOKE_PASSWORD}")"
case "$status" in
303)
rm -f "$response_file"
return 0
;;
*)
echo "admin bootstrap failed with HTTP ${status}" >&2
sed -n '1,20p' "$response_file" >&2 || true
rm -f "$response_file"
return 1
;;
esac
}
cd "$repo_root"
prepare_smoke_secrets
"${compose[@]}" -p "$project" -f "$compose_file" down -v --remove-orphans >/dev/null 2>&1 || true
if ! "${compose[@]}" -p "$project" -f "$compose_file" up --build -d; then
"${compose[@]}" -p "$project" -f "$compose_file" ps || true
"${compose[@]}" -p "$project" -f "$compose_file" logs --no-color || true
exit 1
fi
if ! wait_for_admin_dashboard; then
"${compose[@]}" -p "$project" -f "$compose_file" ps
"${compose[@]}" -p "$project" -f "$compose_file" logs --no-color
echo "server did not serve the admin dashboard on private-admin port ${PROOFLINE_ADMIN_PORT}" >&2
exit 1
fi
if ! bootstrap_admin; then
"${compose[@]}" -p "$project" -f "$compose_file" ps
"${compose[@]}" -p "$project" -f "$compose_file" logs --no-color
exit 1
fi
if [[ "$variant" == "relay-sqlite-local" ]]; then
if ! wait_for_relay_readiness; then
"${compose[@]}" -p "$project" -f "$compose_file" ps
"${compose[@]}" -p "$project" -f "$compose_file" logs --no-color
echo "stream-ingress relay did not become ready on relay port ${PROOFLINE_RELAY_PORT}" >&2
exit 1
fi
if ! assert_relay_does_not_mount_server_routes; then
"${compose[@]}" -p "$project" -f "$compose_file" ps
"${compose[@]}" -p "$project" -f "$compose_file" logs --no-color
exit 1
fi
echo "relay smoke passed: core admin listener and stream-ingress readiness are available"
exit 0
fi
PROOFLINE_SIM_USERNAME="$PROOFLINE_SMOKE_USERNAME" \
PROOFLINE_SIM_PASSWORD="$PROOFLINE_SMOKE_PASSWORD" \
go run ./cmd/simclient \
--api "http://127.0.0.1:${PROOFLINE_MAIN_PORT}" \
--viewer "http://127.0.0.1:${PROOFLINE_MAIN_PORT}" \
--setup-totp-second-factor \
--chunks 3 \
--interval 0s \
--download-bundle \
"${sim_args[@]}" \
| sed -E 's#(Incident viewer: https?://[^[:space:]]+/(i|e)/)[^[:space:]]+#\1[redacted]#'