-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-test.sh
More file actions
300 lines (261 loc) · 13.4 KB
/
Copy pathdocker-test.sh
File metadata and controls
300 lines (261 loc) · 13.4 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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#!/usr/bin/env bash
# ============================================================================
# PSP Router — Local Docker Test Helper
# ============================================================================
# Spins up a dedicated OpenResty container (psp-router-test) for testing.
# Does NOT touch the existing 'nginx' container or any other containers.
#
# Usage:
# bash docker-test.sh setup # Create container + deploy code
# bash docker-test.sh deploy # Re-deploy code after changes
# bash docker-test.sh start # Start the container
# bash docker-test.sh stop # Stop the container
# bash docker-test.sh restart # Restart the container + OpenResty
# bash docker-test.sh destroy # Remove the container completely
# bash docker-test.sh status # Check container and OpenResty status
# bash docker-test.sh logs # Show OpenResty error logs
# bash docker-test.sh test # Send test requests
# bash docker-test.sh shell # Open shell inside container
# ============================================================================
set -euo pipefail
export MSYS_NO_PATHCONV=1
CONTAINER="${PSP_TEST_CONTAINER:-psp-router-test}"
IMAGE="openresty/openresty:latest"
# Host port to publish. Override when 8081 is already taken on your machine:
# PSP_TEST_PORT=8091 bash docker-test.sh setup
PORT="${PSP_TEST_PORT:-8081}"
# Port OpenResty listens on INSIDE the container. Always 8081 regardless of the
# host mapping — commands run via dexec must use this, not $PORT.
CPORT="8081"
OPENRESTY_BIN="/usr/local/openresty/bin/openresty"
OPENRESTY_NGINX="/usr/local/openresty/nginx"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
dexec() {
docker exec "$CONTAINER" bash -c "$1"
}
# Deploy code + init data files (shared by setup and deploy)
do_deploy() {
# docker cp has no --exclude, and dist/lua ships tracked copies of the data
# files. Snapshot whatever the container has so runtime edits made through
# the admin UI survive a re-deploy, matching deploy.sh's rsync excludes.
dexec '
CORE="/usr/local/openresty/nginx/lua/psp_handlers/core"
rm -rf /tmp/psp-preserve && mkdir -p /tmp/psp-preserve
for f in cloud_routes.json routes.json psp_rules.json settings.json admin_credentials.json; do
[ -f "$CORE/$f" ] && cp "$CORE/$f" "/tmp/psp-preserve/$f"
done
# resolver.conf lives under conf/, and deploy.sh excludes it from its
# rsync — mirror that here so an admin-set DNS resolver is not lost.
R="/usr/local/openresty/nginx/conf/resolver.conf"
[ -f "$R" ] && cp "$R" /tmp/psp-preserve/resolver.conf
exit 0
' >/dev/null 2>&1 || true
echo "Copying code to container..."
# Use subshell with cd to avoid Windows path conversion issues with docker cp
(cd "${SCRIPT_DIR}" && for item in conf lua; do
docker cp "dist/${item}/." "${CONTAINER}:${OPENRESTY_NGINX}/${item}/"
done)
# The shipped server block binds 127.0.0.1:8081 so a real server does not
# expose the admin port. Inside a container that makes `docker run -p`
# unreachable, so bind all interfaces here — same override as the Dockerfile.
dexec "sed -i 's/^\( *\)listen 127\.0\.0\.1:8081;/\1listen 8081;/' \
${OPENRESTY_NGINX}/conf/conf.d/psp-router.conf"
# Same reason as the Dockerfile: there is no sudo in this container, so the
# worker must be root or the admin UI's Reload button silently fails and
# settings changes never take effect.
dexec "sed -i 's/^#user nobody;/user root;/' ${OPENRESTY_NGINX}/conf/nginx.conf"
echo "Restoring runtime data files..."
dexec '
CORE="/usr/local/openresty/nginx/lua/psp_handlers/core"
for f in cloud_routes.json routes.json psp_rules.json settings.json admin_credentials.json; do
[ -f "/tmp/psp-preserve/$f" ] && cp "/tmp/psp-preserve/$f" "$CORE/$f"
done
[ -f /tmp/psp-preserve/resolver.conf ] && \
cp /tmp/psp-preserve/resolver.conf /usr/local/openresty/nginx/conf/resolver.conf
rm -rf /tmp/psp-preserve
exit 0
' >/dev/null 2>&1 || true
echo "Initializing data files..."
dexec '
CORE="/usr/local/openresty/nginx/lua/psp_handlers/core"
# JSON data files — create only if missing (never overwrite)
for f in cloud_routes.json routes.json psp_rules.json; do
[ ! -f "$CORE/$f" ] && echo "{}" > "$CORE/$f"
chmod 666 "$CORE/$f"
done
# Settings — normally arrives from dist/ with working example patterns.
# Only synthesise one if it is somehow absent, and never seed an empty
# pattern list silently: that makes the router match nothing while every
# health check still passes.
SETTINGS="$CORE/settings.json"
if [ ! -f "$SETTINGS" ]; then
echo "{\"patterns\":[]}" > "$SETTINGS"
echo "WARNING: settings.json was missing; seeded an EMPTY pattern list."
echo " Add URI patterns at /admin/settings or nothing will route."
fi
chmod 666 "$SETTINGS"
# Admin credentials — create only if missing (admin/changeme)
CREDS="$CORE/admin_credentials.json"
if [ ! -f "$CREDS" ]; then
echo "{\"user\":\"admin\",\"pass_hash\":\"4cb9c8a8048fd02294477fcb1a41191a\"}" > "$CREDS"
chmod 644 "$CREDS"
fi
# Resolver config — writable by admin settings UI
chmod 666 /usr/local/openresty/nginx/conf/resolver.conf 2>/dev/null || true
# Hosts file — writable so admin hosts editor can save changes
chmod 666 /etc/hosts 2>/dev/null || true
'
}
case "${1:-help}" in
# ── Full setup: create container + deploy ─────────────────────────────
setup)
# Check if container already exists
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
echo "Container '${CONTAINER}' already exists."
echo " Use 'bash docker-test.sh destroy' first, or 'bash docker-test.sh deploy' to update code."
exit 1
fi
echo "=== Step 1/4: Pulling OpenResty image ==="
docker pull "$IMAGE"
echo "=== Step 2/4: Creating container ==="
docker run -d \
--name "$CONTAINER" \
-p "${PORT}:8081" \
"$IMAGE"
echo "=== Step 3/4: Installing curl ==="
dexec "apt-get update -qq && apt-get install -y -qq curl procps > /dev/null 2>&1"
echo "=== Step 4/4: Deploying code ==="
do_deploy
# Test and reload OpenResty
dexec "${OPENRESTY_BIN} -t && ${OPENRESTY_BIN} -s reload"
echo ""
echo "=== Setup complete ==="
echo " Container: ${CONTAINER}"
echo " Port: ${PORT}"
echo " Admin UI: http://localhost:${PORT}/admin"
echo " Health: http://localhost:${PORT}/health"
echo " Credentials: admin / changeme"
echo ""
echo " This is a standalone container — your existing 'nginx' container is untouched."
echo ""
echo " To re-deploy after changes: bash docker-test.sh deploy"
echo " To run tests: bash docker-test.sh test"
;;
# ── Deploy code only (after changes) ──────────────────────────────────
deploy)
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
echo "Container '${CONTAINER}' is not running. Run 'bash docker-test.sh setup' first."
exit 1
fi
do_deploy
dexec "${OPENRESTY_BIN} -t"
if dexec "pgrep -f openresty" > /dev/null 2>&1; then
dexec "${OPENRESTY_BIN} -s reload"
echo "Deployed and reloaded."
else
dexec "${OPENRESTY_BIN}"
echo "Deployed and started."
fi
;;
# ── Destroy: remove container completely ──────────────────────────────
destroy)
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
echo "Removing container '${CONTAINER}'..."
docker rm -f "$CONTAINER"
echo "Container removed."
else
echo "Container '${CONTAINER}' does not exist."
fi
;;
# ── Start/Stop/Restart ────────────────────────────────────────────────
start)
docker start "$CONTAINER" 2>/dev/null || { echo "Container not found. Run 'bash docker-test.sh setup' first."; exit 1; }
sleep 1
dexec "${OPENRESTY_BIN} -t && ${OPENRESTY_BIN} -s reload" 2>/dev/null || dexec "${OPENRESTY_BIN} -t && ${OPENRESTY_BIN}"
echo "Container started, OpenResty running on port ${PORT}."
;;
stop)
docker stop "$CONTAINER" 2>/dev/null || echo "Container not running."
echo "Container stopped."
;;
restart)
docker restart "$CONTAINER"
sleep 1
dexec "${OPENRESTY_BIN} -t && ${OPENRESTY_BIN} -s reload" 2>/dev/null || dexec "${OPENRESTY_BIN} -t && ${OPENRESTY_BIN}"
echo "Container restarted, OpenResty running on port ${PORT}."
;;
# ── Status ────────────────────────────────────────────────────────────
status)
echo "=== Container ==="
if docker ps --format '{{.Names}} {{.Status}}' | grep -q "^${CONTAINER}"; then
docker ps --filter "name=${CONTAINER}" --format " Name: {{.Names}} Status: {{.Status}} Ports: {{.Ports}}"
elif docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
echo " Status: STOPPED"
else
echo " Status: NOT CREATED (run 'bash docker-test.sh setup')"
exit 0
fi
echo ""
echo "=== OpenResty ==="
if dexec "pgrep -f openresty" > /dev/null 2>&1; then
echo " Status: RUNNING"
else
echo " Status: NOT running"
fi
echo ""
echo "=== Health ==="
dexec "curl -s http://127.0.0.1:${CPORT}/health" 2>/dev/null || echo " Not responding"
echo ""
;;
# ── Logs ──────────────────────────────────────────────────────────────
logs)
dexec "cat ${OPENRESTY_NGINX}/logs/error.log" 2>/dev/null || echo "No logs yet."
;;
# ── Test requests ─────────────────────────────────────────────────────
test)
echo "=== 1. Health check ==="
dexec "curl -s http://127.0.0.1:${CPORT}/health" || echo "FAILED"
echo ""
echo ""
echo "=== 2. Admin pages ==="
for page in "" "/routes" "/psp-rules" "/settings" "/tester" "/health" "/hosts" "/logs"; do
STATUS=$(dexec "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:${CPORT}/admin${page}")
printf " /admin%-14s %s\n" "${page}" "${STATUS}"
done
echo ""
echo "=== 3. Unknown PSP (expect passthrough) ==="
dexec "curl -s -w '\nHTTP: %{http_code}\n' -X POST http://127.0.0.1:${CPORT}/api/1.0/notification/unknown_psp -H 'Content-Type: application/json' -d '{}'" || echo "FAILED"
echo ""
# 460 here is normal: this container has no /etc/hosts entries, so the
# route resolves but the hostname does not, and the request passes
# through. Use `bash test.sh <host:port>` for assertions.
echo "=== 4. Valid request (acmepay, customer 126) — 460 expected without hosts entries ==="
dexec "curl -s -w '\nHTTP: %{http_code}\n' -X POST http://127.0.0.1:${CPORT}/api/0.1/user/transfer/deposit/confirm/acmepay -H 'Content-Type: application/json' -d '{\"ref\":\"13126999\",\"amount\":50.00,\"currency\":\"EUR\",\"status\":\"approved\"}'" || echo "FAILED"
;;
# ── Shell access ──────────────────────────────────────────────────────
shell)
docker exec -it "$CONTAINER" bash
;;
# ── Help ──────────────────────────────────────────────────────────────
*)
echo "PSP Router — Docker Test Helper"
echo ""
echo "Runs in a dedicated '${CONTAINER}' container (does NOT touch your existing containers)."
echo ""
echo "Usage: bash docker-test.sh <command>"
echo ""
echo "Setup:"
echo " setup Create container + deploy code (first time)"
echo " deploy Re-deploy code after changes"
echo " destroy Remove the container completely"
echo ""
echo "Operations:"
echo " start Start the container"
echo " stop Stop the container"
echo " restart Restart the container"
echo " status Check container and OpenResty status"
echo " logs Show OpenResty error logs"
echo " test Send test requests"
echo " shell Open shell inside container"
;;
esac