Files
universe/k8s/migrate-namespaces.sh
zeekayandGitHub d8ba8af1f0 chore(exchange): collapse 3 divergent overlays into shared base + env overlays (#14)
* deploy(lux-devnet): bump luxd → v1.27.23 (proto v1.0.2 unblocks build)

v1.27.22 had a build error from the kill-subnet rename in
luxfi/node#116: proto/p2p/p2p_zap.go aliased p2p.ChainUptime but
the upstream luxfi/proto package still exported SubnetUptime —
"undefined: p2p.ChainUptime" broke every `go build ./...` for
the whole node tree. Companion PR luxfi/proto#6 (commit
e96f95cd86) merged the upstream rename to ChainUptime; tagging
luxfi/proto v1.0.2 and bumping the node module pin (215f4e3d7b)
makes main HEAD build clean. v1.27.23 tag produced ghcr.io/
luxfi/node:v1.27.23 via the Docker workflow (run 26689130579).

Carries v1.27.22 content: canonical evmAddr/utxoAddr (genesis
v1.12.15), kill-subnet vocabulary, kill-fuji vocabulary.

Devnet rollout:
  - Scale STS 5→0, delete all 5 luxd PVCs (devnet expendable
    per PR #88 path-1 fix already re-runs from scratch)
  - kubectl replace luxd-genesis CM from canonical source
    ~/work/lux/genesis/configs/devnet/genesis.json (evmAddr/
    utxoAddr only, no legacy luxAddr/ethAddr translation)
  - Patch STS image + scale 0→5
  - All 5 luxd pods Ready on v1.27.23, P-chain producing blocks
    (h≥3 observed), C-Chain healthy, BLS + bootstrapped OK,
    sybil protection ON
  - Deployer key idx=5 (P-dev1jx9p2hxfemcgdlylth05zj20klsn4t06s0t5kv,
    0x9011E888251AB053B7bD1cdB598Db4f9DEd94714) unlocked
    balance: 50000000000000 nLUX = 50K LUX (per source unlockSchedule
    locktime=0)

L2 bootstrap: BLOCKED on consensus quirk where the P-chain
proposer doesn't auto-accept its own block. Two CreateNetworkTx
landed in blocks 2 + 3 from the cluster's view, but bootstrap-l2
hangs polling getTxStatus on the proposer's local view — same
pattern as the 2026-05-30T09:30Z `spc-pending-consensus-retry`
remark, now observed on every L2 attempt not just spc. 0/4 L2
EVMs live. Needs a separate investigation into the luxd
proposer-accept path (alpha=2 k=3 validatorCount=5 sample/quorum
math, BFT vote-back loop) before 4/4 L2 EVMs can land on a
v1.27.x devnet.

* chore(exchange): collapse 3 divergent overlays into shared base + env overlays

Before: three divergent exchange manifests scattered across the tree —
  - k8s/lux-mainnet/exchange.yaml + exchange-proxy.yaml
  - k8s/lux-explorer/exchange.yaml + exchange-proxy.yaml + exchange-whitelabel.yaml
  - k8s/zoo-exchange/deployment.yaml

After: one canonical base + per-env overlays under k8s/exchange/.
  base/                  Deployment, Service, Middleware, namespaceless
  overlays/lux-mainnet/  lux.exchange + markets/exchange.lux.network + exchange-proxy
  overlays/lux-testnet/  exchange-testnet.lux.network + lux-test.exchange
  overlays/lux-devnet/   exchange-devnet.lux.network + lux-dev.exchange
  overlays/zoo-mainnet/  zoo.exchange (zooai/exchange image, KMSSecret)
  overlays/pars-mainnet/ pars.market (lux image + brand config.json)

Common: container args, ports (3000), probes, resources, labels (app: exchange).
Per overlay: namespace, image tag, env vars, brand patch.sh, IngressRoute hosts.

Verified:
  - kubectl --dry-run=client apply -k k8s/exchange/overlays/<env>/ clean for all 5
  - kubectl diff against do-sfo3-lux-k8s shows zero diffs for production hostnames
    (zoo.exchange, lux.exchange still routed via existing in-cluster resources)

Side updates:
  - lux-k8s/kustomization.yaml: drop ../lux-explorer/exchange.yaml ref
  - migrate-namespaces.sh: point at -k k8s/exchange/overlays/lux-mainnet
  - STACK.md: replace old paths with k8s/exchange/overlays/<env>
2026-05-30 20:40:45 -07:00

158 lines
6.1 KiB
Bash
Executable File

#!/bin/bash
# Migration script: lux-explorer → lux-mainnet / lux-testnet / lux-devnet
#
# This script migrates resources from the monolithic lux-explorer namespace
# into per-network namespaces. Run with --apply to execute, otherwise dry-run.
#
# Prerequisites:
# - kubectl configured with do-sfo3-lux-k8s context
# - ghcr-luxfi imagePullSecret already exists in target namespaces
#
# Migration order:
# 1. Create secrets (ghcr-luxfi, blockscout-postgres-*) in new namespaces
# 2. Apply ConfigMaps and Services first
# 3. Apply Deployments/StatefulSets
# 4. Apply IngressRoutes (takes over traffic)
# 5. Verify health
# 6. Scale down old namespace resources
# 7. (Manual) Delete lux-explorer namespace after verification
set -euo pipefail
CTX="do-sfo3-lux-k8s"
K="kubectl --context $CTX"
DIR="$(cd "$(dirname "$0")" && pwd)"
MODE="${1:-dry-run}"
log() { echo "[$(date +%H:%M:%S)] $*"; }
if [ "$MODE" != "--apply" ]; then
log "DRY RUN — pass --apply to execute"
K="$K --dry-run=client"
fi
###############################################################################
# Phase 1: Copy required secrets to new namespaces
###############################################################################
log "Phase 1: Ensuring secrets exist in target namespaces"
copy_secret() {
local name=$1 src=$2 dst=$3
if $K get secret "$name" -n "$dst" &>/dev/null; then
log " Secret $name already exists in $dst"
else
log " Copying secret $name from $src to $dst"
$K get secret "$name" -n "$src" -o json \
| jq "del(.metadata.namespace,.metadata.resourceVersion,.metadata.uid,.metadata.creationTimestamp,.metadata.annotations)" \
| jq ".metadata.namespace = \"$dst\"" \
| $K apply -f -
fi
}
# ghcr-luxfi already exists in all targets (confirmed)
# Copy blockscout postgres secrets
for ns in lux-mainnet lux-testnet lux-devnet; do
for secret in blockscout-postgres-mainnet blockscout-postgres-testnet blockscout-postgres-devnet blockscout-postgres-zoo blockscout-postgres-hanzo blockscout-postgres-spc blockscout-postgres-pars indexer-postgres-secret; do
if $K get secret "$secret" -n lux-explorer &>/dev/null; then
copy_secret "$secret" "lux-explorer" "$ns" 2>/dev/null || true
fi
done
done
###############################################################################
# Phase 2: Apply lux-mainnet resources
###############################################################################
log "Phase 2: Applying lux-mainnet resources"
# ExternalName service first (dependencies need it)
$K apply -f "$DIR/lux-mainnet/lux-sql.yaml"
# ConfigMaps
$K apply -f "$DIR/lux-mainnet/configmap.yaml"
$K apply -f "$DIR/lux-mainnet/configmap-chains.yaml"
# Stateful infrastructure (graph-node + postgres)
$K apply -f "$DIR/lux-mainnet/graph-node.yaml"
# Microservices (needed by explorer)
$K apply -f "$DIR/lux-mainnet/microservices.yaml"
# Explorer backends + frontends
$K apply -f "$DIR/lux-mainnet/explorer-mainnet.yaml"
$K apply -f "$DIR/lux-mainnet/frontend-mainnet.yaml"
$K apply -f "$DIR/lux-mainnet/explorer-chains.yaml"
$K apply -f "$DIR/lux-mainnet/frontend-chains.yaml"
# Exchange stack — deduplicated into k8s/exchange/ (base + per-env overlays).
$K apply -k "$DIR/exchange/overlays/lux-mainnet"
# Indexers
$K apply -f "$DIR/lux-mainnet/indexer-mainnet.yaml"
$K apply -f "$DIR/lux-mainnet/indexer-all-chains.yaml"
# Sites
$K apply -f "$DIR/lux-mainnet/lux-build.yaml"
$K apply -f "$DIR/lux-mainnet/lux-market.yaml"
# Maintenance page
$K apply -f "$DIR/lux-mainnet/maintenance.yaml"
# IngressRoutes (traffic cutover)
$K apply -f "$DIR/lux-mainnet/ingress.yaml"
$K apply -f "$DIR/lux-mainnet/ingress-chains.yaml"
###############################################################################
# Phase 3: Apply lux-testnet resources
###############################################################################
log "Phase 3: Applying lux-testnet resources"
$K apply -f "$DIR/lux-testnet/configmap.yaml"
$K apply -f "$DIR/lux-testnet/frontend-testnet.yaml"
$K apply -f "$DIR/lux-testnet/indexer-testnet.yaml"
$K apply -f "$DIR/lux-testnet/ingress.yaml"
###############################################################################
# Phase 4: Apply lux-devnet resources
###############################################################################
log "Phase 4: Applying lux-devnet resources"
$K apply -f "$DIR/lux-devnet/configmap.yaml"
$K apply -f "$DIR/lux-devnet/frontend-devnet.yaml"
$K apply -f "$DIR/lux-devnet/indexer-devnet.yaml"
$K apply -f "$DIR/lux-devnet/ingress.yaml"
###############################################################################
# Phase 5: Health check
###############################################################################
if [ "$MODE" = "--apply" ]; then
log "Phase 5: Waiting for rollouts..."
sleep 10
log "Checking lux-mainnet pods:"
$K get pods -n lux-mainnet -l app=lux-exchange --no-headers 2>/dev/null | head -5
$K get pods -n lux-mainnet -l app=exchange-api --no-headers 2>/dev/null | head -5
$K get pods -n lux-mainnet -l app=explorer-backend --no-headers 2>/dev/null | head -5
log "Checking lux-testnet pods:"
$K get pods -n lux-testnet -l app=lux-frontend --no-headers 2>/dev/null | head -5
log "Checking lux-devnet pods:"
$K get pods -n lux-devnet -l app=lux-frontend --no-headers 2>/dev/null | head -5
fi
###############################################################################
# Phase 6: Scale down old namespace (manual step)
###############################################################################
log ""
log "Migration complete. Next steps:"
log " 1. Verify all services are healthy in new namespaces"
log " 2. Check IngressRoutes are routing correctly"
log " 3. Scale down old resources:"
log " kubectl --context $CTX scale --replicas=0 -n lux-explorer deployment --all"
log " 4. After verification period, delete old namespace:"
log " kubectl --context $CTX delete namespace lux-explorer"
log ""
log "NOTE: graph-node PVCs in lux-explorer cannot be moved."
log " New graph-node in lux-mainnet will need subgraph redeployment."
log " Keep lux-explorer alive until graph-node is reindexed."