kampodine 0.3.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.
@@ -8,7 +8,7 @@
8
8
  # API call, rollback is the same call reversed.
9
9
  #
10
10
  # Colors are instance display names: <app>-blue / <app>-green (defaults:
11
- # esellar-blue / esellar-green).
11
+ # kampodine-blue / kampodine-green).
12
12
  # The reserved IP is derived from live OCI state — no local state file.
13
13
  #
14
14
  # Usage:
@@ -20,7 +20,7 @@
20
20
  #
21
21
  # FLIP = ACME-FIRST:
22
22
  # 1. health gate on the target's own IP
23
- # 2. anchor.conf written on the TARGET guest over ssh — the esellar-anchor
23
+ # 2. anchor.conf written on the TARGET guest over ssh — the kampodine-anchor
24
24
  # watcher service (shipped by vm-prepare) configures the anchor private
25
25
  # address within one interval; flip waits for `ip addr` to show it
26
26
  # 3. OCI assigns the reserved IP to the target's anchor (secondary private
@@ -49,7 +49,7 @@
49
49
  # instead — it runs the same ACME-first sequence there.
50
50
  #
51
51
  # provision has TWO routes:
52
- # 1. NATIVE — a UEFI_64 esellar-alpine* custom image exists in the
52
+ # 1. NATIVE — a UEFI_64 kampodine-alpine* custom image exists in the
53
53
  # compartment: launch it directly (the golden image boots as-is).
54
54
  # 2. INJECT (provision-via-migrate) — OCI pins imported custom images to
55
55
  # firmware=BIOS and A1/Ampere is UEFI-only, but the template instance
@@ -63,7 +63,7 @@
63
63
  # 'gunzip | sudo dd', reboot, verify /etc/alpine-release). The instance
64
64
  # record keeps the platform image metadata — exactly like the template.
65
65
  #
66
- # Env: OCI_PROFILE (default esellar-api), OCI_COMPARTMENT (default esellar).
66
+ # Env: OCI_PROFILE (default: "default"), OCI_COMPARTMENT (required).
67
67
  # Injection extras: ALPINE_QCOW2 (golden disk path), OPS_SSH_PUBKEY (ops
68
68
  # public key for the platform-image launch), PLATFORM_SSH_USER (default
69
69
  # ubuntu), INJECT_PROBE_SLEEP / INJECT_PROBE_TRIES (ssh wait tuning).
@@ -71,9 +71,29 @@
71
71
  # loopback; the reserved IP is checked over :80 with the prod Host header).
72
72
  set -euo pipefail
73
73
 
74
- PROFILE="${OCI_PROFILE:-esellar-api}"
75
- COMPARTMENT_NAME="${OCI_COMPARTMENT:-esellar}"
76
- APP_HOST_HEADER="${APP_HOST_HEADER:-app.example.com}"
74
+ HERE="${BASH_SOURCE[0]%/*}"
75
+ # shellcheck source=common.sh
76
+ source "$HERE/common.sh"
77
+
78
+ # --profile pre-scan (kampodine INSTANCE profile): every sub-step accepts it
79
+ # before its own flags; flip/provision have their own flag loops, so the flag
80
+ # is lifted here once, validated, and its proxyHost feeds the status health
81
+ # header (APP_HOST_HEADER) when the env did not pin one. The flip's own
82
+ # ACME hostname stays derived from the reserved IP by design.
83
+ PROFILE_FLAG=""
84
+ args=()
85
+ while [[ $# -gt 0 ]]; do
86
+ case "$1" in
87
+ --profile) PROFILE_FLAG="$2"; shift 2 ;;
88
+ *) args+=("$1"); shift ;;
89
+ esac
90
+ done
91
+ set -- ${args[@]+"${args[@]}"}
92
+ profile_resolve "$PROFILE_FLAG" "" ""
93
+
94
+ PROFILE="${OCI_PROFILE:-default}"
95
+ COMPARTMENT_NAME="${OCI_COMPARTMENT:-kampodine}"
96
+ APP_HOST_HEADER="${PROFILE_PROXY_HOST:-${APP_HOST_HEADER:-app.example.com}}"
77
97
  REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)}"
78
98
  SSH_OPTS=(-o ConnectTimeout=6 -o BatchMode=yes -o StrictHostKeyChecking=accept-new)
79
99
 
@@ -86,7 +106,7 @@ usage() {
86
106
  cat <<'EOF'
87
107
 
88
108
  Each sub-step has its own --help: status | init | provision | flip | rollback.
89
- Env: OCI_PROFILE (default esellar-api), OCI_COMPARTMENT (default esellar).
109
+ Env: OCI_PROFILE (default: "default"), OCI_COMPARTMENT (required).
90
110
 
91
111
  Examples:
92
112
  kampodine bluegreen status
@@ -181,7 +201,7 @@ compartment_ocid() {
181
201
  instance_by_color() {
182
202
  local comp="$1" color="$2" row
183
203
  row="$(oci compute instance list -c "$comp" --profile "$PROFILE" \
184
- --display-name "esellar-$color" --lifecycle-state RUNNING \
204
+ --display-name "kampodine-$color" --lifecycle-state RUNNING \
185
205
  --query 'sort_by(data, &"time-created")[-1] | ["id", "availability-domain"] | join('\'' '\'', @)' \
186
206
  --raw-output 2>/dev/null || true)"
187
207
  [[ -n "$row" ]] || return 0
@@ -240,7 +260,7 @@ reserved_anchor_ip() {
240
260
  return 0
241
261
  fi
242
262
  oci network private-ip create --profile "$PROFILE" --vnic-id "$vnic" \
243
- --display-name "esellar-reserved-anchor" \
263
+ --display-name "kampodine-reserved-anchor" \
244
264
  --query 'data.id' --raw-output 2>/dev/null
245
265
  }
246
266
 
@@ -249,9 +269,9 @@ FLIP_POLL_SLEEP="${FLIP_POLL_SLEEP:-5}"
249
269
  FLIP_ADDR_TRIES="${FLIP_ADDR_TRIES:-12}" # guest watcher pickup: 12 x 5s = 60s
250
270
  FLIP_ACME_TRIES="${FLIP_ACME_TRIES:-24}" # LE HTTP-01: 24 x 5s = 120s
251
271
 
252
- # Guest anchor protocol (the esellar-anchor watcher half lives in
253
- # infra/alpine-host/ansible/roles/container-service/files/esellar-anchor.sh —
254
- # both halves of the conf path must stay in sync: /etc/esellar/anchor.conf).
272
+ # Guest anchor protocol (the kampodine-anchor watcher half lives in
273
+ # infra/alpine-host/ansible/roles/container-service/files/kampodine-anchor.sh —
274
+ # both halves of the conf path must stay in sync: /etc/kampodine/anchor.conf).
255
275
  # Remote commands are composed client-side BY DESIGN (vm-prepare convention);
256
276
  # the interpolated values are OCI-API derived and regex-gated at the call
257
277
  # sites, never user input.
@@ -260,7 +280,7 @@ FLIP_ACME_TRIES="${FLIP_ACME_TRIES:-24}" # LE HTTP-01: 24 x 5s = 120s
260
280
  write_anchor_conf() {
261
281
  local ip="$1" addr="$2"
262
282
  ssh "${SSH_OPTS[@]}" "root@$ip" \
263
- "umask 077; mkdir -p /etc/esellar; printf 'ANCHOR_ADDR=%s\nANCHOR_IFACE=\n' '$addr' > /etc/esellar/anchor.conf && echo ANCHOR_CONF_WRITTEN"
283
+ "umask 077; mkdir -p /etc/kampodine; printf 'ANCHOR_ADDR=%s\nANCHOR_IFACE=\n' '$addr' > /etc/kampodine/anchor.conf && echo ANCHOR_CONF_WRITTEN"
264
284
  }
265
285
 
266
286
  # shellcheck disable=SC2029
@@ -274,7 +294,7 @@ anchor_addr_ready() {
274
294
  read_anchor_conf_addr() {
275
295
  local ip="$1" line addr
276
296
  line="$(ssh "${SSH_OPTS[@]}" "root@$ip" \
277
- 'grep -h "^ANCHOR_ADDR=" /etc/esellar/anchor.conf 2>/dev/null | head -n 1' 2>/dev/null || true)"
297
+ 'grep -h "^ANCHOR_ADDR=" /etc/kampodine/anchor.conf 2>/dev/null | head -n 1' 2>/dev/null || true)"
278
298
  addr="${line#ANCHOR_ADDR=}"
279
299
  addr="${addr//\"/}"
280
300
  addr="${addr//\'/}"
@@ -297,7 +317,7 @@ delete_guest_addr() {
297
317
  # re-added the address once; retry the delete across one watcher interval.
298
318
  cleanup_target_anchor() {
299
319
  local ip="$1" addr="$2" i
300
- ssh "${SSH_OPTS[@]}" "root@$ip" "rm -f /etc/esellar/anchor.conf" >/dev/null 2>&1 || true
320
+ ssh "${SSH_OPTS[@]}" "root@$ip" "rm -f /etc/kampodine/anchor.conf" >/dev/null 2>&1 || true
301
321
  for ((i = 1; i <= 3; i++)); do
302
322
  delete_guest_addr "$ip" "$addr"
303
323
  anchor_addr_ready "$ip" "$addr" >/dev/null 2>&1 || return 0
@@ -323,7 +343,7 @@ flip_failure_rollback() {
323
343
  if [[ "$bpip" == ocid1.privateip* ]]; then
324
344
  if oci network public-ip update --public-ip-id "$rocid" --profile "$PROFILE" \
325
345
  --private-ip-id "$bpip" --force >/dev/null 2>&1; then
326
- say "rolled back to esellar-$ob (existing anchor $bpip)" >&2
346
+ say "rolled back to kampodine-$ob (existing anchor $bpip)" >&2
327
347
  recovered=1
328
348
  fi
329
349
  fi
@@ -331,14 +351,14 @@ flip_failure_rollback() {
331
351
  if (( ! recovered )); then
332
352
  if oci network public-ip update --public-ip-id "$rocid" --profile "$PROFILE" \
333
353
  --private-ip-id "" --force --wait-for-state AVAILABLE >/dev/null 2>&1; then
334
- say "reserved ip UNASSIGNED (dormant) — no existing anchor on esellar-$ob" >&2
354
+ say "reserved ip UNASSIGNED (dormant) — no existing anchor on kampodine-$ob" >&2
335
355
  else
336
356
  cleanup_target_anchor "$tpub" "$taddr"
337
357
  die "AUTO-ROLLBACK FAILED — reserved ip state unknown; flip manually via console: $rocid"
338
358
  fi
339
359
  fi
340
360
  cleanup_target_anchor "$tpub" "$taddr"
341
- say "esellar-$to cleaned (anchor.conf removed, anchor address deleted) — investigate before retrying" >&2
361
+ say "kampodine-$to cleaned (anchor.conf removed, anchor address deleted) — investigate before retrying" >&2
342
362
  }
343
363
 
344
364
  # instance_healthy <ephemeral_ip> -> ssh + loopback app check.
@@ -349,7 +369,7 @@ instance_healthy() {
349
369
  local ip="$1"
350
370
  [[ -n "$ip" ]] || return 1
351
371
  ssh "${SSH_OPTS[@]}" "root@$ip" \
352
- "rc-service esellar-api status >/dev/null 2>&1 && busybox wget -q -O /dev/null http://127.0.0.1:8080/up" 2>/dev/null
372
+ "rc-service kampodine-api status >/dev/null 2>&1 && busybox wget -q -O /dev/null http://127.0.0.1:8080/up" 2>/dev/null
353
373
  }
354
374
 
355
375
  # instance_wait_running <iid> — poll lifecycle-state to RUNNING. The OCI CLI's
@@ -365,7 +385,7 @@ instance_wait_running() {
365
385
  --query 'data."lifecycle-state"' --raw-output 2>/dev/null || true)"
366
386
  case "$state" in
367
387
  RUNNING) return 0 ;;
368
- FAILED | TERMINATED | TERMINATING) die "esellar instance reached $state — nothing to inject, check the console" ;;
388
+ FAILED | TERMINATED | TERMINATING) die "kampodine instance reached $state — nothing to inject, check the console" ;;
369
389
  esac
370
390
  sleep "$sleep_s"
371
391
  done
@@ -390,7 +410,7 @@ inject_alpine() {
390
410
  # the Alpine verify forever. The scrub below
391
411
  # clears the phase file between the two boots; the user's file is never
392
412
  # touched.
393
- kh="$(mktemp "${TMPDIR:-/tmp}/esellar-inject-kh.XXXXXX")"
413
+ kh="$(mktemp "${TMPDIR:-/tmp}/kampodine-inject-kh.XXXXXX")"
394
414
  iss() { ssh -o UserKnownHostsFile="$kh" "${SSH_OPTS[@]}" "$@"; }
395
415
  say "inject: waiting for ssh (${ruser}@${ip}, platform-image first boot)…"
396
416
  ssh_wait_probe() { iss "${ruser}@${ip}" true; }
@@ -400,7 +420,7 @@ inject_alpine() {
400
420
  [[ "$i" == "$probe_tries" ]] && die "ssh never came up on ${ip} (${ruser}) — check the instance console connection"
401
421
  sleep "$probe_sleep"
402
422
  done
403
- raw="$(mktemp "${TMPDIR:-/tmp}/esellar-inject-raw.XXXXXX")"
423
+ raw="$(mktemp "${TMPDIR:-/tmp}/kampodine-inject-raw.XXXXXX")"
404
424
  say "inject: converting ${qcow2} -> raw…"
405
425
  qemu-img convert -O raw "$qcow2" "$raw"
406
426
  say "inject: streaming golden disk -> ${ip} boot volume (gunzip | dd, conv=fsync)…"
@@ -440,7 +460,7 @@ inject_alpine() {
440
460
  done
441
461
  rm -f "$kh"
442
462
  [[ -n "$rel" ]] || die "injection streamed but no ALPINE 3.x ssh on ${ip} after reboot (got: '${rel:-nothing}') — check the serial console; terminate, do NOT flip to ${color}"
443
- say "INJECTED esellar-$color: Alpine ${rel} boots on ${ip} (instance image metadata stays the platform image — like green)"
463
+ say "INJECTED kampodine-$color: Alpine ${rel} boots on ${ip} (instance image metadata stays the platform image — like green)"
444
464
  say "next: kampodine vm-prepare --host root@${ip} -> kampodine deploy --host root@${ip}"
445
465
  say "then 'bluegreen.sh flip --to ${color}' (health-gated) once its app checks green."
446
466
  }
@@ -458,11 +478,12 @@ for help_arg in "$@"; do
458
478
  ;;
459
479
  esac
460
480
  done
481
+ [[ -n "${OCI_COMPARTMENT:-}" ]] || die "set OCI_COMPARTMENT=<compartment name or ocid> — no default: compartments are account-specific"
461
482
  case "$cmd" in
462
483
  status)
463
484
  comp="$(compartment_ocid)"
464
485
  rp="$(reserved_ip "$comp")"
465
- say "== esellar blue/green pair (compartment $COMPARTMENT_NAME) =="
486
+ say "== kampodine blue/green pair (compartment $COMPARTMENT_NAME) =="
466
487
  if [[ -n "$rp" ]]; then
467
488
  read -r rocid raddr rholder <<<"$rp"
468
489
  say "reserved IP : $raddr ($rocid)"
@@ -475,9 +496,9 @@ case "$cmd" in
475
496
  if [[ -n "$row" ]]; then
476
497
  read -r iid pub ad <<<"$row"
477
498
  if instance_healthy "$pub"; then verdict=HEALTHY; else verdict=UNHEALTHY/unreachable; fi
478
- say "esellar-$color : $iid ip=${pub:-none} ad=${ad:-?} app=$verdict"
499
+ say "kampodine-$color : $iid ip=${pub:-none} ad=${ad:-?} app=$verdict"
479
500
  else
480
- say "esellar-$color : not provisioned"
501
+ say "kampodine-$color : not provisioned"
481
502
  fi
482
503
  done
483
504
  ;;
@@ -491,7 +512,7 @@ case "$cmd" in
491
512
  exit 0
492
513
  fi
493
514
  addr="$(oci network public-ip create -c "$comp" --profile "$PROFILE" \
494
- --lifetime RESERVED --display-name esellar-active \
515
+ --lifetime RESERVED --display-name kampodine-active \
495
516
  --query 'data."ip-address"' --raw-output)"
496
517
  say "created DORMANT reserved IP: $addr (unassigned — no instance attached)"
497
518
  say "Point DNS/SSLIP at this address when the pair goes active."
@@ -502,25 +523,25 @@ case "$cmd" in
502
523
  color="${1:-}"
503
524
  [[ "$color" == blue || "$color" == green ]] || die "usage: kampodine bluegreen provision <blue|green>"
504
525
  comp="$(compartment_ocid)"
505
- instance_by_color "$comp" "$color" | grep -q . && die "esellar-$color already RUNNING"
526
+ instance_by_color "$comp" "$color" | grep -q . && die "kampodine-$color already RUNNING"
506
527
  # base: the OTHER color's AD + subnet (same fault domain layout), golden image
507
528
  other=green; [[ "$color" == green ]] && other=blue
508
529
  orow="$(instance_by_color "$comp" "$other")"
509
- [[ -n "$orow" ]] || die "esellar-$other not RUNNING — need its AD/subnet as the pair template"
530
+ [[ -n "$orow" ]] || die "kampodine-$other not RUNNING — need its AD/subnet as the pair template"
510
531
  # instance_by_color rows are "<ocid> <ephemeral_public_ip> <ad>" — field 2
511
532
  # is the IP, the AD is field 3 (launching with the IP as AD fails).
512
533
  read -r oiid _ oad <<<"$orow"
513
534
  subnet="$(oci compute vnic-attachment list -c "$comp" --profile "$PROFILE" \
514
535
  --instance-id "$oiid" --query 'data[0]."subnet-id"' --raw-output)"
515
536
 
516
- # Route selection. NATIVE only with a UEFI_64 esellar-alpine* custom image:
537
+ # Route selection. NATIVE only with a UEFI_64 kampodine-alpine* custom image:
517
538
  # OCI pins IMPORTED images to firmware=BIOS and A1 is UEFI-only, so a BIOS
518
539
  # verdict means the import would die at launch (Shape ... is not valid for
519
540
  # image) — skip it. Otherwise take the template's LIVE image-id from its
520
541
  # instance record and inject the golden disk (provision-via-migrate).
521
542
  mode="" image=""
522
543
  custom="$(oci compute image list -c "$comp" --profile "$PROFILE" --all --sort-by TIMECREATED \
523
- --query "data[?\"display-name\" != null && starts_with(\"display-name\", 'esellar-alpine')] | [0].id" \
544
+ --query "data[?\"display-name\" != null && starts_with(\"display-name\", 'kampodine-alpine')] | [0].id" \
524
545
  --raw-output 2>/dev/null || true)"
525
546
  if [[ "$custom" == ocid1.image* ]]; then
526
547
  fw="$(oci compute image get --image-id "$custom" --profile "$PROFILE" \
@@ -528,7 +549,7 @@ case "$cmd" in
528
549
  if [[ "$fw" == "UEFI_64" ]]; then
529
550
  image="$custom" mode="native"
530
551
  else
531
- say "note: newest esellar-alpine* custom image is firmware=${fw:-unknown} — A1 rejects BIOS-pinned imports, skipping to the platform-image + injection route"
552
+ say "note: newest kampodine-alpine* custom image is firmware=${fw:-unknown} — A1 rejects BIOS-pinned imports, skipping to the platform-image + injection route"
532
553
  fi
533
554
  fi
534
555
  if [[ -z "$image" ]]; then
@@ -536,7 +557,7 @@ case "$cmd" in
536
557
  --query 'data."image-id"' --raw-output 2>/dev/null || true)"
537
558
  [[ "$image" == ocid1.image* ]] || die "template instance has no resolvable image-id — cannot launch or inject"
538
559
  mode="inject"
539
- qcow2="${ALPINE_QCOW2:-${REPO_ROOT}/infra/alpine-host/build/esellar-alpine-3.22.6-aarch64.qcow2}"
560
+ qcow2="${ALPINE_QCOW2:-${REPO_ROOT}/infra/alpine-host/build/kampodine-alpine-3.22.6-aarch64.qcow2}"
540
561
  [[ -f "$qcow2" ]] || die "golden qcow2 not found: $qcow2 (build via packer, or set ALPINE_QCOW2)"
541
562
  command -v qemu-img >/dev/null 2>&1 || die "qemu-img not found in PATH (brew install qemu) — required for the qcow2 -> raw conversion"
542
563
  # ops ssh public key for the platform-image first boot. OPS_SSH_PUBKEY
@@ -549,22 +570,22 @@ case "$cmd" in
549
570
  keyfile="$OPS_SSH_PUBKEY"
550
571
  else
551
572
  agent_keys="$(ssh-add -L 2>/dev/null | grep -v '\.pub$' || true)"
552
- [[ -n "$agent_keys" ]] || die "no ssh key available: OPS_SSH_PUBKEY unset and ssh-add lists no keys (ssh-add ~/.ssh/id_ed25519-esellar, or set OPS_SSH_PUBKEY)"
553
- keyfile="$(mktemp "${TMPDIR:-/tmp}/esellar-ops-pubkey.XXXXXX")"
573
+ [[ -n "$agent_keys" ]] || die "no ssh key available: OPS_SSH_PUBKEY unset and ssh-add lists no keys (ssh-add ~/.ssh/id_ed25519-kampodine, or set OPS_SSH_PUBKEY)"
574
+ keyfile="$(mktemp "${TMPDIR:-/tmp}/kampodine-ops-pubkey.XXXXXX")"
554
575
  printf '%s\n' "$agent_keys" > "$keyfile"
555
576
  chmod 600 "$keyfile"
556
577
  fi
557
578
  fi
558
579
 
559
- say "launching esellar-$color: image=${image:0:60}… ad=$oad subnet=${subnet:0:60}… mode=$mode"
580
+ say "launching kampodine-$color: image=${image:0:60}… ad=$oad subnet=${subnet:0:60}… mode=$mode"
560
581
  # NOTE: --profile stays ON the launch line (script-gates static scan reads
561
582
  # the invocation line, not array contents).
562
583
  launch_args=(-c "$comp" --availability-domain "$oad" --subnet-id "$subnet"
563
584
  --image-id "$image" --shape VM.Standard.A1.Flex --shape-config '{"ocpus":2,"memoryInGBs":12}'
564
- --assign-public-ip true --display-name "esellar-$color")
585
+ --assign-public-ip true --display-name "kampodine-$color")
565
586
  [[ "$mode" == "inject" ]] && launch_args+=(--ssh-authorized-keys-file "$keyfile")
566
587
  iid="$(oci compute instance launch "${launch_args[@]}" --profile "$PROFILE" --query 'data.id' --raw-output)"
567
- say "LAUNCHED esellar-$color: $iid"
588
+ say "LAUNCHED kampodine-$color: $iid"
568
589
  if [[ "$mode" == "native" ]]; then
569
590
  say "next: wait RUNNING -> ssh in -> kampodine vm-prepare -> kampodine deploy --host root@<ephemeral-ip>"
570
591
  say "then 'bluegreen.sh flip --to $color' (health-gated) once its app checks green."
@@ -594,16 +615,16 @@ case "$cmd" in
594
615
  read -r rocid raddr _ <<<"$rp"
595
616
  rhost="${raddr//./-}.sslip.io"
596
617
  trow="$(instance_by_color "$comp" "$to")"
597
- [[ -n "$trow" ]] || die "esellar-$to is not RUNNING — nothing to flip to"
618
+ [[ -n "$trow" ]] || die "kampodine-$to is not RUNNING — nothing to flip to"
598
619
  read -r tiid tpub _ <<<"$trow"
599
620
  tvnic="$(primary_vnic_of "$tiid")"
600
- [[ -n "$tvnic" ]] || die "no primary VNIC on esellar-$to"
621
+ [[ -n "$tvnic" ]] || die "no primary VNIC on kampodine-$to"
601
622
  tpip="$(reserved_anchor_ip "$tvnic")"
602
- [[ "$tpip" == ocid1.privateip* ]] || die "could not resolve/create the reserved-anchor secondary private ip on esellar-$to"
623
+ [[ "$tpip" == ocid1.privateip* ]] || die "could not resolve/create the reserved-anchor secondary private ip on kampodine-$to"
603
624
  if instance_healthy "$tpub"; then
604
- say "target health: esellar-$to app HEALTHY on its own IP"
625
+ say "target health: kampodine-$to app HEALTHY on its own IP"
605
626
  else
606
- (( force )) || die "esellar-$to app UNHEALTHY — refusing flip (override: --force)"
627
+ (( force )) || die "kampodine-$to app UNHEALTHY — refusing flip (override: --force)"
607
628
  say "target health: UNHEALTHY — flipping anyway (--force)"
608
629
  fi
609
630
 
@@ -611,19 +632,19 @@ case "$cmd" in
611
632
  # once the hostname resolves to the reserved ip AND routes to the target,
612
633
  # so the guest anchor address goes FIRST, then the assign, then the cert.
613
634
  ob=green; [[ "$to" == green ]] && ob=blue
614
- say "flip[1/4]: anchor conf -> esellar-$to guest ($tpub), watcher configures the address"
635
+ say "flip[1/4]: anchor conf -> kampodine-$to guest ($tpub), watcher configures the address"
615
636
  tsubnet="$(oci compute vnic-attachment list -c "$comp" --profile "$PROFILE" \
616
637
  --instance-id "$tiid" --query 'data[0]."subnet-id"' --raw-output 2>/dev/null || true)"
617
- [[ "$tsubnet" == ocid1.subnet* ]] || die "could not resolve esellar-$to's subnet id"
638
+ [[ "$tsubnet" == ocid1.subnet* ]] || die "could not resolve kampodine-$to's subnet id"
618
639
  tcidr="$(oci network subnet get --subnet-id "$tsubnet" --profile "$PROFILE" \
619
640
  --query 'data."cidr-block"' --raw-output 2>/dev/null || true)"
620
- [[ "$tcidr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]] || die "could not resolve esellar-$to's subnet cidr (got: ${tcidr:-none})"
641
+ [[ "$tcidr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]] || die "could not resolve kampodine-$to's subnet cidr (got: ${tcidr:-none})"
621
642
  tanchor_addr="$(oci network private-ip get --private-ip-id "$tpip" --profile "$PROFILE" \
622
643
  --query 'data."ip-address"' --raw-output 2>/dev/null || true)"
623
- [[ "$tanchor_addr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || die "could not resolve the anchor private address on esellar-$to"
644
+ [[ "$tanchor_addr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || die "could not resolve the anchor private address on kampodine-$to"
624
645
  taddr_cidr="${tanchor_addr}/${tcidr##*/}"
625
646
  if ! write_anchor_conf "$tpub" "$taddr_cidr" >/dev/null 2>&1; then
626
- die "anchor.conf write failed on esellar-$to ($tpub) — nothing mutated, flip aborted"
647
+ die "anchor.conf write failed on kampodine-$to ($tpub) — nothing mutated, flip aborted"
627
648
  fi
628
649
  addr_ok=0
629
650
  for ((i = 1; i <= FLIP_ADDR_TRIES; i++)); do
@@ -632,15 +653,15 @@ case "$cmd" in
632
653
  done
633
654
  if (( ! addr_ok )); then
634
655
  cleanup_target_anchor "$tpub" "$taddr_cidr"
635
- die "guest watcher never configured $taddr_cidr on esellar-$to — is rc-service esellar-anchor running? (conf removed, NOTHING mutated)"
656
+ die "guest watcher never configured $taddr_cidr on kampodine-$to — is rc-service kampodine-anchor running? (conf removed, NOTHING mutated)"
636
657
  fi
637
- say "flip[2/4]: guest answers on $taddr_cidr — reserved $raddr -> esellar-$to (anchor $tpip)"
658
+ say "flip[2/4]: guest answers on $taddr_cidr — reserved $raddr -> kampodine-$to (anchor $tpip)"
638
659
  oci network public-ip update --public-ip-id "$rocid" --profile "$PROFILE" \
639
660
  --private-ip-id "$tpip" --force --wait-for-state ASSIGNED >/dev/null \
640
661
  || { cleanup_target_anchor "$tpub" "$taddr_cidr"; die "OCI flip call failed — guest conf removed; run 'kampodine bluegreen status'"; }
641
- say "flip[3/4]: reserved IP ASSIGNED — registering $rhost on esellar-$to's kamal-proxy (ACME HTTP-01 through the reserved ip)…"
662
+ say "flip[3/4]: reserved IP ASSIGNED — registering $rhost on kampodine-$to's kamal-proxy (ACME HTTP-01 through the reserved ip)…"
642
663
  if ! ssh "${SSH_OPTS[@]}" "root@$tpub" \
643
- "podman exec kamal-proxy kamal-proxy deploy esellar-api --host=$rhost --target=esellar-api:8080 --tls --health-check-path=/api/auth/ok"; then
664
+ "podman exec kamal-proxy kamal-proxy deploy kampodine-api --host=$rhost --target=kampodine-api:8080 --tls --health-check-path=/api/auth/ok"; then
644
665
  flip_failure_rollback "$to" "$ob" "$comp" "$rocid" "$tpub" "$taddr_cidr"
645
666
  exit 1
646
667
  fi
@@ -656,14 +677,14 @@ case "$cmd" in
656
677
  fi
657
678
  served="$(curl -s -m 8 --resolve "$rhost:443:$raddr" "https://$rhost/api/auth/ok" || true)"
658
679
  say "flip[4/4]: cert for $rhost VALID + serving through $raddr"
659
- say "FLIPPED: https://$raddr/ (https://$rhost/) now serves from esellar-$to"
680
+ say "FLIPPED: https://$raddr/ (https://$rhost/) now serves from kampodine-$to"
660
681
  say "served /api/auth/ok: ${served:-<no body>}"
661
682
  ;;
662
683
 
663
684
  rollback)
664
685
  # DORMANT rollback: holder guest cleanup
665
686
  # (anchor.conf removal + anchor address delete — the flip tool's explicit
666
- # job; the esellar-anchor watcher is add-only) then the OCI unassign
687
+ # job; the kampodine-anchor watcher is add-only) then the OCI unassign
667
688
  # (documented CLI semantics: an empty --private-ip-id unassigns). For a
668
689
  # real pair where traffic must land on the other color, use
669
690
  # 'flip --to <other>' — it runs the full ACME-first sequence there.
@@ -692,10 +713,10 @@ case "$cmd" in
692
713
  if [[ -z "$holder_color" ]]; then
693
714
  say "warning: reserved $raddr held by an anchor of neither RUNNING color (terminated instance?) — unassigning without guest cleanup"
694
715
  else
695
- say "current holder: esellar-$holder_color ($holder_ip) — cleaning the guest anchor, then unassigning"
716
+ say "current holder: kampodine-$holder_color ($holder_ip) — cleaning the guest anchor, then unassigning"
696
717
  conf_addr="$(read_anchor_conf_addr "$holder_ip")"
697
718
  cleanup_target_anchor "$holder_ip" "$conf_addr"
698
- say "esellar-$holder_color guest cleaned (anchor.conf removed${conf_addr:+, address $conf_addr deleted})"
719
+ say "kampodine-$holder_color guest cleaned (anchor.conf removed${conf_addr:+, address $conf_addr deleted})"
699
720
  fi
700
721
  say "unassigning reserved $raddr (-> dormant)…"
701
722
  oci network public-ip update --public-ip-id "$rocid" --profile "$PROFILE" \