diff --git a/clientdocs/sweep-receipt.txt b/clientdocs/sweep-receipt.txt index 28dfe5e..84acbe5 100644 --- a/clientdocs/sweep-receipt.txt +++ b/clientdocs/sweep-receipt.txt @@ -35,7 +35,7 @@ 30919b61b2b79b33a853a29bc814558d7e0e940a3040b2f7710ea9a14333b71a runbooks/appendix-C-identity-rbac.md 8510402e5375a6d42cc47f28eec9698a23d88e04b22ef70ef6e129e1179f3d32 runbooks/appendix-D-magnum-trust-model.md 927aa7261aa2d9fabe2cb7342499e6c0d0840a93ffbb323ee7003ac8eefe14a7 runbooks/tenant-onboarding-v2-DRAFT.md -80269942634809f903c4a7349fe97a9609cc84280b09af9813d7a068936f66cd scripts/tenant-acceptance.sh +861c5274afd3290791aec15e8200ae39e07aa16f5ef28306bbc75358e4caffa9 scripts/tenant-acceptance.sh ad00be489480069d52df1b978be0360d7fb04dbf954a8cf487162872f2da0593 scripts/tenant-assert.sh -7d203df79e920ac35adedfde634cb1c6ccd5d79f560b7c1b72e1a9aa20ea5654 scripts/tenant-offboard.sh -d221f6ed0aabaf7faab12e16ccbc655a324d3ea873c8ed183cbcd9353e24973a scripts/tenant-onboard.sh +619ba5a352ec423a1d0bf5ba919ae896d9ca09b7ce469485145a4c2df00b631f scripts/tenant-offboard.sh +fa2307d2fe3c55951fe402d736202692e02a6ad3ba4140dd6f15f55f64c981fe scripts/tenant-onboard.sh diff --git a/docs/session-ledger.md b/docs/session-ledger.md index 457be9e..eab653f 100644 --- a/docs/session-ledger.md +++ b/docs/session-ledger.md @@ -481,10 +481,10 @@ source. - **S-CLASS BATCH STATUS (operator ruled 2026-07-08):** DONE = S7, S4, S8a (DOCFIX-132/133/134). **S8b APPROVED -- DO IT (next actionable):** centralize - KEYSTONE_VIP into lib-net.sh (verified source-safe: constants + read-only helpers, - no set/side-effects); wire the 6 literal sites (phase-03-admin-openrc, phase-06- - kubeconfig-gate, phase-06-k8s-bootstrap, tenant-onboard, tenant-offboard, - tenant-acceptance). **S8c RULED WON'T-DO** (operator: marginal value for as-built + KEYSTONE_VIP into lib-net.sh. **DONE (DOCFIX-138):** KEYSTONE_VIP_DEFAULT in + lib-net.sh; all 6 sites reference it (3 forms: KEYSTONE_VIP, KEYSTONE_HOSTPORT, + acceptance inline); lib-net source added where absent. Gauntlet 39/39, lint 0 fail. + **S8 FULLY DONE (S8a+S8b).** **S8c RULED WON'T-DO** (operator: marginal value for as-built constants vs bash<->python emit/parse machinery). S1/S2/S3/S5 (lib-validate) STILL HELD -- operator keeps DOCFIX-126/127 live-verify open for an upcoming opportunity (devteam actively using resources; not now). S6 no-action. diff --git a/docs/v1-redeploy-changelog.md b/docs/v1-redeploy-changelog.md index 73a3fd0..f18eb96 100644 --- a/docs/v1-redeploy-changelog.md +++ b/docs/v1-redeploy-changelog.md @@ -3411,4 +3411,31 @@ - Numbers consumed: DOCFIX-137. REVERT: git checkout HEAD~ -- scripts/repo_lint.py scripts/repo-lint.sh tests/repo-lint/run-tests.sh clientdocs/guide-skill-coupling.txt docs/v1-redeploy-changelog.md docs/session-ledger.md. -Next-free after this push (per scan, keep this line unwrapped): D-076, DOCFIX-138, BUNDLEFIX-012. +### 2026-07-08 (addendum 54, jumphost stream) -- DOCFIX-138: S8b KEYSTONE_VIP default centralized into lib-net.sh + +Operator-approved S-class item S8b. The keystone PUBLIC endpoint literal (10.12.4.50) +was the default in 6 scripts across 3 forms; now all reference one lib-net.sh constant +(hard-rule #3; Roosevelt = 1 edit not 6). lib-net verified source-safe before wiring +(constants + read-only helpers, no set/side-effects, source-safe guard). +- lib-net.sh: new KEYSTONE_VIP_DEFAULT="10.12.4.50" (D-020/D-052-tagged, under the + existing SC2034 carve-out). +- Wired (each stays env-overridable; a lib-net source added where absent): + - phase-03-admin-openrc.sh: `KEYSTONE_VIP="${KEYSTONE_VIP:-$KEYSTONE_VIP_DEFAULT}"` + (had SCRIPT_DIR; added source). + - tenant-onboard.sh: top-level SDIR + source (was function-local only); line 23 ref. + - tenant-offboard.sh + tenant-acceptance.sh: source added after their existing SDIR + (DOCFIX-133); offboard KEYSTONE_VIP ref; acceptance foil_env inline AUTH_URL now + `https://${KEYSTONE_VIP_DEFAULT}:5000/v3`. + - phase-06-kubeconfig-gate.sh + phase-06-k8s-bootstrap.sh (KEYSTONE_HOSTPORT form): + local SCRIPT_DIR + source before the block; `${KEYSTONE_VIP_DEFAULT}:5000`. +- Resolve-checked: KEYSTONE_VIP -> 10.12.4.50, KEYSTONE_HOSTPORT -> 10.12.4.50:5000. + Two header-comment mentions of the literal RETAINED as as-run provenance (doc only, + not an executable second source). +- Gauntlet 39/39 (onboard/offboard/acceptance/phase-06 all green under the new + sourcing); repo-lint 0 fail (L7 receipt re-recorded for the 3 tenant scripts -- + internal change, no clientdocs staleness). +- S8 now FULLY done (S8a DOCFIX-134 + S8b here); S8c ruled won't-do. +- Numbers consumed: DOCFIX-138. +REVERT: git checkout HEAD~ -- scripts/lib-net.sh scripts/phase-03-admin-openrc.sh scripts/phase-06-kubeconfig-gate.sh scripts/phase-06-k8s-bootstrap.sh scripts/tenant-onboard.sh scripts/tenant-offboard.sh scripts/tenant-acceptance.sh clientdocs/sweep-receipt.txt docs/v1-redeploy-changelog.md docs/session-ledger.md; then bash scripts/repo-lint.sh --record-clientdocs-sweep. + +Next-free after this push (per scan, keep this line unwrapped): D-076, DOCFIX-139, BUNDLEFIX-012. diff --git a/scripts/lib-net.sh b/scripts/lib-net.sh index 6213fa7..ac61ad7 100644 --- a/scripts/lib-net.sh +++ b/scripts/lib-net.sh @@ -65,6 +65,12 @@ FIP_POOL_START="10.12.5.0" FIP_POOL_END="10.12.7.254" +# Keystone PUBLIC endpoint host (provider VIP, D-020/D-052 -- a .50-.60 provider VIP). +# Single source of truth for the KEYSTONE_VIP / KEYSTONE_HOSTPORT defaults across the +# tenant-* family + phase-03/phase-06 scripts (each stays env-overridable). Roosevelt: +# change here once, not in 6 scripts. +KEYSTONE_VIP_DEFAULT="10.12.4.50" + # --- tiny read-only helpers --- # need_jq: jq is required (present on the jumphost). Returns non-zero if absent. diff --git a/scripts/phase-03-admin-openrc.sh b/scripts/phase-03-admin-openrc.sh index dc1c5cb..2d4d82d 100644 --- a/scripts/phase-03-admin-openrc.sh +++ b/scripts/phase-03-admin-openrc.sh @@ -23,8 +23,9 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EXTRACT="$SCRIPT_DIR/extract_admin_password.py" +. "$SCRIPT_DIR/lib-net.sh" # KEYSTONE_VIP_DEFAULT (single source of truth) -KEYSTONE_VIP="${KEYSTONE_VIP:-10.12.4.50}" # keystone PUBLIC endpoint (provider VIP; verify vs bundle on rebuild) +KEYSTONE_VIP="${KEYSTONE_VIP:-$KEYSTONE_VIP_DEFAULT}" # keystone PUBLIC endpoint (provider VIP) ADMIN_DOMAIN="${ADMIN_DOMAIN:-admin_domain}" PROJECT_CANDIDATES="${PROJECT_CANDIDATES:-admin admin_domain}" # tried in order; first that SCOPES wins (DOCFIX-022) CA="${CA:-$HOME/vault-init/vault-ca-root.pem}" diff --git a/scripts/phase-06-k8s-bootstrap.sh b/scripts/phase-06-k8s-bootstrap.sh index 2c0af71..22e1794 100644 --- a/scripts/phase-06-k8s-bootstrap.sh +++ b/scripts/phase-06-k8s-bootstrap.sh @@ -52,9 +52,10 @@ SSH_OPTS=(-i "$SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=no \ -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10) -# --- Keystone public host:port -- the as-run literal (6.3 tagged ENV(keystone-vip)); -# env-overridable per site. NOT discovered -- this is the value that ran verbatim. --- -KEYSTONE_HOSTPORT="${KEYSTONE_HOSTPORT:-10.12.4.50:5000}" +# --- Keystone public host:port -- default from lib-net.sh (single source of truth); +# env-overridable per site. NOT discovered. --- +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"; . "$SCRIPT_DIR/lib-net.sh" +KEYSTONE_HOSTPORT="${KEYSTONE_HOSTPORT:-${KEYSTONE_VIP_DEFAULT}:5000}" echo "[OK] Keystone public endpoint: $KEYSTONE_HOSTPORT" KHOST="${KEYSTONE_HOSTPORT%%:*}"; KPORT="${KEYSTONE_HOSTPORT##*:}" IHOST="${INET_PROBE%%:*}"; IPORT="${INET_PROBE##*:}" diff --git a/scripts/phase-06-kubeconfig-gate.sh b/scripts/phase-06-kubeconfig-gate.sh index 64ac72d..62bb2f1 100644 --- a/scripts/phase-06-kubeconfig-gate.sh +++ b/scripts/phase-06-kubeconfig-gate.sh @@ -50,9 +50,10 @@ SSH_OPTS=(-i "$SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=no \ -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10) -# --- Keystone public host:port -- the as-run literal (6.5 tagged it verbatim); +# --- Keystone public host:port -- default from lib-net.sh (single source of truth); # env-overridable per site. NOT discovered. --- -KEYSTONE_HOSTPORT="${KEYSTONE_HOSTPORT:-10.12.4.50:5000}" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"; . "$SCRIPT_DIR/lib-net.sh" +KEYSTONE_HOSTPORT="${KEYSTONE_HOSTPORT:-${KEYSTONE_VIP_DEFAULT}:5000}" echo "[OK] Keystone public endpoint: $KEYSTONE_HOSTPORT" # --- 1. pull the RAW admin kubeconfig (no server= arg; we rewrite locally) --- diff --git a/scripts/tenant-acceptance.sh b/scripts/tenant-acceptance.sh index ec9106f..57676a7 100644 --- a/scripts/tenant-acceptance.sh +++ b/scripts/tenant-acceptance.sh @@ -15,6 +15,7 @@ # Harness: tests/tenant-acceptance/run-tests.sh (offline; covers the DOCFIX-094 stdout-only trust capture). set -uo pipefail SDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # for helper .py (trust_filter.py) +. "$SDIR/lib-net.sh" # KEYSTONE_VIP_DEFAULT (single source of truth) CLIENT="${1:-}" [ -n "$CLIENT" ] || { echo "usage: tenant-acceptance.sh [foil-appcred-file]"; exit 14; } CF="$HOME/tenant-${CLIENT}/${CLIENT}-cluster-cred.txt" @@ -31,7 +32,7 @@ export OS_PROJECT_ID="$(awk -F= '/^project_id=/{print $2}' "$CF")" OS_PASSWORD="$(awk -F= '/^password=/{print $2}' "$CF")"; } admin_env() { for v in $(env|awk -F= '/^OS_/{print $1}'); do unset "$v"; done; source "$HOME/admin-openrc"; } foil_env() { for v in $(env|awk -F= '/^OS_/{print $1}'); do unset "$v"; done - export OS_AUTH_TYPE=v3applicationcredential OS_AUTH_URL="https://10.12.4.50:5000/v3" OS_IDENTITY_API_VERSION=3 + export OS_AUTH_TYPE=v3applicationcredential OS_AUTH_URL="https://${KEYSTONE_VIP_DEFAULT}:5000/v3" OS_IDENTITY_API_VERSION=3 export OS_CACERT="${OS_CACERT:-$HOME/vault-init/vault-ca-root.pem}" export OS_APPLICATION_CREDENTIAL_ID="$(awk -F'"' '/^id=/{print $2}' "$FOIL_ACF")" export OS_APPLICATION_CREDENTIAL_SECRET="$(awk -F'"' '/^secret=/{print $2}' "$FOIL_ACF")"; } diff --git a/scripts/tenant-offboard.sh b/scripts/tenant-offboard.sh index 5a558b8..ad45230 100644 --- a/scripts/tenant-offboard.sh +++ b/scripts/tenant-offboard.sh @@ -20,6 +20,7 @@ # script exits nonzero at the end (22 sweep / 23 identity) rather than stranding silently. set -uo pipefail SDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # for helper .py (trust_filter.py) +. "$SDIR/lib-net.sh" # KEYSTONE_VIP_DEFAULT (single source of truth) SWEEP_FAIL=0; ID_FAIL=0 run(){ # run : capture-then-test; count failures loudly local _c="$1"; shift; local out @@ -169,7 +170,7 @@ # DOCFIX-113: auth URL comes from the cred file's auth_url= line (same rule as # tenant-acceptance.sh tenant_env); the literal is only a KEYSTONE_VIP-overridable # fallback, consistent with tenant-onboard.sh. -KEYSTONE_VIP="${KEYSTONE_VIP:-10.12.4.50}" +KEYSTONE_VIP="${KEYSTONE_VIP:-$KEYSTONE_VIP_DEFAULT}" tenant_env(){ for v in $(env|awk -F= '/^OS_/{print $1}'); do unset "$v"; done local AU; AU="$(awk -F= '/^auth_url=/{print $2}' "$TCF")" export OS_AUTH_URL="${AU:-https://${KEYSTONE_VIP}:5000/v3}" OS_IDENTITY_API_VERSION=3 diff --git a/scripts/tenant-onboard.sh b/scripts/tenant-onboard.sh index 10a7ad3..b69a108 100644 --- a/scripts/tenant-onboard.sh +++ b/scripts/tenant-onboard.sh @@ -16,11 +16,12 @@ # whitelist-write secrets to 0600 files, never echo; dynamic ID resolution; CA threaded; verify # before mutate. This is an EXECUTED script (bash tenant-onboard.sh ...), so exit-on-error is correct. set -uo pipefail +SDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"; . "$SDIR/lib-net.sh" # KEYSTONE_VIP_DEFAULT (single source of truth) # ---- inputs ---- CLIENT="${1:-}"; STAGE="${2:-all}" TENANT_CIDR="${TENANT_CIDR:-}" # required for stage 4 (e.g. 10.20.24.0/24); must not collide -KEYSTONE_VIP="${KEYSTONE_VIP:-10.12.4.50}" +KEYSTONE_VIP="${KEYSTONE_VIP:-$KEYSTONE_VIP_DEFAULT}" CA="${OS_CACERT:-$HOME/vault-init/vault-ca-root.pem}" OUT="$HOME/tenant-${CLIENT}" # 0600 credential handover dir AUTH_URL="https://${KEYSTONE_VIP}:5000/v3"