From cd778c47759aa77e77ac2de6d467eae2564d7c31 Mon Sep 17 00:00:00 2001 From: Agent Date: Sun, 19 Apr 2026 09:35:27 +0000 Subject: [PATCH] fix: [nomad-step-5] edge dispatcher task: Missing vault.read(kv/data/disinto/bots/vault) on fresh init (#1035) --- bin/disinto | 2 + nomad/jobs/edge.hcl | 4 +- tools/vault-seed-ops-repo.sh | 149 +++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 2 deletions(-) create mode 100755 tools/vault-seed-ops-repo.sh diff --git a/bin/disinto b/bin/disinto index c18ef0c..7f6379d 100755 --- a/bin/disinto +++ b/bin/disinto @@ -802,6 +802,7 @@ _disinto_init_nomad() { woodpecker-server|woodpecker-agent) seed_name="woodpecker" ;; agents) seed_name="agents" ;; chat) seed_name="chat" ;; + edge) seed_name="ops-repo" ;; esac local seed_script="${FACTORY_ROOT}/tools/vault-seed-${seed_name}.sh" if [ -x "$seed_script" ]; then @@ -983,6 +984,7 @@ _disinto_init_nomad() { woodpecker-server|woodpecker-agent) seed_name="woodpecker" ;; agents) seed_name="agents" ;; chat) seed_name="chat" ;; + edge) seed_name="ops-repo" ;; esac local seed_script="${FACTORY_ROOT}/tools/vault-seed-${seed_name}.sh" if [ -x "$seed_script" ]; then diff --git a/nomad/jobs/edge.hcl b/nomad/jobs/edge.hcl index 4a495d9..739a377 100644 --- a/nomad/jobs/edge.hcl +++ b/nomad/jobs/edge.hcl @@ -221,10 +221,10 @@ EOT change_mode = "restart" error_on_missing_key = false data = <&2; exit 1; } + +# ── Flag parsing ───────────────────────────────────────────────────────────── +DRY_RUN=0 +case "$#:${1-}" in + 0:) + ;; + 1:--dry-run) + DRY_RUN=1 + ;; + 1:-h|1:--help) + printf 'Usage: %s [--dry-run]\n\n' "$(basename "$0")" + printf 'Seed kv/disinto/shared/ops-repo with FORGE_TOKEN.\n\n' + printf 'Copies token from kv/disinto/bots/vault if present;\n' + printf 'otherwise generates a random value. Idempotent:\n' + printf 'existing non-empty values are left untouched.\n\n' + printf ' --dry-run Print planned actions without writing.\n' + exit 0 + ;; + *) + die "invalid arguments: $* (try --help)" + ;; +esac + +# ── Preconditions ──────────────────────────────────────────────────────────── +for bin in curl jq openssl; do + command -v "$bin" >/dev/null 2>&1 \ + || die "required binary not found: ${bin}" +done + +[ -n "${VAULT_ADDR:-}" ] \ + || die "VAULT_ADDR unset — e.g. export VAULT_ADDR=http://127.0.0.1:8200" +hvault_token_lookup >/dev/null \ + || die "Vault auth probe failed — check VAULT_ADDR + VAULT_TOKEN" + +# ── Step 1/2: ensure kv/ mount exists and is KV v2 ─────────────────────────── +log "── Step 1/2: ensure ${KV_MOUNT}/ is KV v2 ──" +export DRY_RUN +hvault_ensure_kv_v2 "$KV_MOUNT" "[vault-seed-ops-repo]" \ + || die "KV mount check failed" + +# ── Step 2/2: seed ops-repo from vault bot ─────────────────────────────────── +log "── Step 2/2: seed ${OPS_REPO_API} ──" + +# Read existing ops-repo value +existing_raw="$(hvault_get_or_empty "${OPS_REPO_API}")" \ + || die "failed to read ${OPS_REPO_API}" + +existing_token="" +if [ -n "$existing_raw" ]; then + existing_token="$(printf '%s' "$existing_raw" | jq -r '.data.data.token // ""')" +fi + +desired_token="$existing_token" +action="" + +if [ -z "$existing_token" ]; then + # Token missing — try to copy from vault bot + bot_raw="$(hvault_get_or_empty "${VAULT_BOT_API}")" || true + if [ -n "$bot_raw" ]; then + bot_token="$(printf '%s' "$bot_raw" | jq -r '.data.data.token // ""')" + if [ -n "$bot_token" ]; then + desired_token="$bot_token" + action="copied" + fi + fi + + # If still no token, generate one + if [ -z "$desired_token" ]; then + if [ "$DRY_RUN" -eq 1 ]; then + action="generated (dry-run)" + else + desired_token="$(openssl rand -hex 32)" + action="generated" + fi + fi +fi + +if [ -z "$action" ]; then + log "all keys present at ${OPS_REPO_API} — no-op" + log "token unchanged" + exit 0 +fi + +if [ "$DRY_RUN" -eq 1 ]; then + log "[dry-run] ${OPS_REPO_PATH}: would ${action} token" + exit 0 +fi + +# Write the token +payload="$(jq -n --arg t "$desired_token" '{data: {token: $t}}')" +_hvault_request POST "${OPS_REPO_API}" "$payload" >/dev/null \ + || die "failed to write ${OPS_REPO_API}" + +log "${OPS_REPO_PATH}: ${action} token" +log "done — ${OPS_REPO_API} seeded"