NPM: locate proxy host via python3 JSON parse, not brittle grep

The proxy-host lookup grepped for '"id":N,"domain_names":[...]' in a
fixed field order that NPM's JSON doesn't guarantee, so the host was never
found ("proxy host not found"). Replace both the cashup and hk-planner
inline blocks with a shared npm_add_location() helper that parses the
proxy-hosts list with python3 and matches DOMAIN inside domain_names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-02 14:21:01 +00:00
parent eadbb383e7
commit 70ffd218a1

View file

@ -926,53 +926,7 @@ ${build_out}"
|| msg_warn "Cashup may need extra time — check LXC 117" || msg_warn "Cashup may need extra time — check LXC 117"
# Add /cashup/ location to the existing NPM proxy host (idempotent) # Add /cashup/ location to the existing NPM proxy host (idempotent)
msg_info "Adding /cashup/ to NPM proxy" npm_add_location "/cashup/" "10.10.10.117" 3083
local npm_token
npm_token=$(npm_get_token)
local npm_ip="10.10.10.3" # stable internal NPM IP (vmbr1) — API only needs internal reach
if [[ -n "$npm_token" ]]; then
# Find the proxy host for our domain
local host_id
host_id=$(curl -sf "http://${npm_ip}:81/api/nginx/proxy-hosts" \
-H "Authorization: Bearer ${npm_token}" 2>/dev/null \
| grep -o '"id":[0-9]*,"domain_names":\["'"${DOMAIN}"'"\]' \
| grep -o '"id":[0-9]*' | cut -d: -f2) || true
if [[ -n "$host_id" ]]; then
# Fetch existing host, merge /cashup/ location, PUT back
local existing
existing=$(curl -sf "http://${npm_ip}:81/api/nginx/proxy-hosts/${host_id}" \
-H "Authorization: Bearer ${npm_token}" 2>/dev/null) || true
if [[ -n "$existing" ]] && ! echo "$existing" | grep -q '"/cashup/"'; then
# Build merged locations by appending cashup entry
local merged_locations
merged_locations=$(echo "$existing" | python3 -c "
import sys, json
d = json.load(sys.stdin)
locs = d.get('locations') or []
locs.append({'path':'/cashup/','forward_scheme':'http','forward_host':'10.10.10.117','forward_port':3083,'advanced_config':''})
print(json.dumps(locs))
" 2>/dev/null) || true
if [[ -n "$merged_locations" ]]; then
curl -sf -X PUT "http://${npm_ip}:81/api/nginx/proxy-hosts/${host_id}" \
-H "Authorization: Bearer ${npm_token}" \
-H "Content-Type: application/json" \
-d "{\"locations\":${merged_locations}}" &>/dev/null \
&& msg_ok "NPM location /cashup/ added" \
|| msg_warn "NPM update failed — add /cashup/ → 10.10.10.117:3083 manually in NPM admin"
fi
else
msg_ok "NPM location /cashup/ already present"
fi
else
msg_warn "NPM proxy host for ${DOMAIN} not found — add /cashup/ → 10.10.10.117:3083 manually"
fi
else
msg_warn "NPM API unavailable — add /cashup/ → 10.10.10.117:3083 manually in NPM admin"
fi
} }
# ════════════════════════════════════════════════════════════════════════════ # ════════════════════════════════════════════════════════════════════════════
@ -1034,45 +988,7 @@ ${build_out}"
|| msg_warn "HK Planner may need extra time — check LXC 118" || msg_warn "HK Planner may need extra time — check LXC 118"
# Add /hk-planner/ location to NPM proxy host # Add /hk-planner/ location to NPM proxy host
msg_info "Adding /hk-planner/ to NPM proxy" npm_add_location "/hk-planner/" "10.10.10.118" 3080
local npm_token; npm_token=$(npm_get_token)
local npm_ip="10.10.10.3" # stable internal NPM IP (vmbr1) — API only needs internal reach
if [[ -n "$npm_token" ]]; then
local host_id
host_id=$(curl -sf "http://${npm_ip}:81/api/nginx/proxy-hosts" \
-H "Authorization: Bearer ${npm_token}" 2>/dev/null \
| grep -o '"id":[0-9]*,"domain_names":\["'"${DOMAIN}"'"\]' \
| grep -o '"id":[0-9]*' | cut -d: -f2) || true
if [[ -n "$host_id" ]]; then
local existing
existing=$(curl -sf "http://${npm_ip}:81/api/nginx/proxy-hosts/${host_id}" \
-H "Authorization: Bearer ${npm_token}" 2>/dev/null) || true
if [[ -n "$existing" ]] && ! echo "$existing" | grep -q '"/hk-planner/"'; then
local merged_locations
merged_locations=$(echo "$existing" | python3 -c "
import sys, json
d = json.load(sys.stdin)
locs = d.get('locations') or []
locs.append({'path':'/hk-planner/','forward_scheme':'http','forward_host':'10.10.10.118','forward_port':3080,'advanced_config':''})
print(json.dumps(locs))
" 2>/dev/null) || true
if [[ -n "$merged_locations" ]]; then
curl -sf -X PUT "http://${npm_ip}:81/api/nginx/proxy-hosts/${host_id}" \
-H "Authorization: Bearer ${npm_token}" \
-H "Content-Type: application/json" \
-d "{\"locations\":${merged_locations}}" &>/dev/null \
&& msg_ok "NPM location /hk-planner/ added" \
|| msg_warn "NPM update failed — add /hk-planner/ → 10.10.10.118:3080 manually"
fi
else
msg_ok "NPM location /hk-planner/ already present"
fi
else
msg_warn "NPM proxy host for ${DOMAIN} not found — add /hk-planner/ → 10.10.10.118:3080 manually"
fi
else
msg_warn "NPM API unavailable — add /hk-planner/ → 10.10.10.118:3080 manually in NPM admin"
fi
} }
# ════════════════════════════════════════════════════════════════════════════ # ════════════════════════════════════════════════════════════════════════════
@ -1118,6 +1034,73 @@ npm_get_token() {
echo "" echo ""
} }
# Idempotently add a custom location (path → forward_host:port) to the NPM
# proxy host that serves $DOMAIN. Robust JSON handling via python3 — the proxy
# host is located by matching $DOMAIN inside its domain_names array (field
# order in NPM's JSON is not guaranteed, so grep-based matching is unreliable).
npm_add_location() {
local path=$1 fwd_host=$2 fwd_port=$3
local npm_ip="10.10.10.3"
msg_info "Adding ${path} to NPM proxy"
local token; token=$(npm_get_token)
if [[ -z "$token" ]]; then
msg_warn "NPM API unavailable — add ${path}${fwd_host}:${fwd_port} manually in NPM admin"
return
fi
local hosts_json host_id
hosts_json=$(curl -sf "http://${npm_ip}:81/api/nginx/proxy-hosts" \
-H "Authorization: Bearer ${token}" 2>/dev/null) || true
host_id=$(echo "$hosts_json" | python3 -c "
import sys, json
try: hosts = json.load(sys.stdin)
except Exception: sys.exit(0)
dom = '${DOMAIN}'
for h in hosts:
if dom in (h.get('domain_names') or []):
print(h['id']); break
" 2>/dev/null) || true
if [[ -z "$host_id" ]]; then
msg_warn "NPM proxy host for ${DOMAIN} not found — add ${path}${fwd_host}:${fwd_port} manually"
return
fi
local existing merged
existing=$(curl -sf "http://${npm_ip}:81/api/nginx/proxy-hosts/${host_id}" \
-H "Authorization: Bearer ${token}" 2>/dev/null) || true
merged=$(echo "$existing" | python3 -c "
import sys, json
try: h = json.load(sys.stdin)
except Exception: sys.exit(0)
path, fh, fp = '${path}', '${fwd_host}', ${fwd_port}
locs = h.get('locations') or []
if any(l.get('path') == path for l in locs):
print('EXISTS'); sys.exit(0)
locs.append({'path':path,'forward_scheme':'http','forward_host':fh,'forward_port':fp,'advanced_config':''})
print(json.dumps(locs))
" 2>/dev/null) || true
if [[ "$merged" == "EXISTS" ]]; then
msg_ok "NPM location ${path} already present"
return
fi
if [[ -z "$merged" ]]; then
msg_warn "NPM merge failed — add ${path}${fwd_host}:${fwd_port} manually"
return
fi
if curl -sf -X PUT "http://${npm_ip}:81/api/nginx/proxy-hosts/${host_id}" \
-H "Authorization: Bearer ${token}" \
-H "Content-Type: application/json" \
-d "{\"locations\":${merged}}" &>/dev/null; then
msg_ok "NPM location ${path} added"
else
msg_warn "NPM update failed — add ${path}${fwd_host}:${fwd_port} manually"
fi
}
configure_npm_proxy_hosts() { configure_npm_proxy_hosts() {
msg_step "Configuring NPM proxy hosts" msg_step "Configuring NPM proxy hosts"
msg_info "Waiting for NPM API to be ready" msg_info "Waiting for NPM API to be ready"