1#!/usr/bin/env bash 2# ============================================================================= 3# AI Software Factory — OpenSearch bootstrap (one-shot) 4# 5# Runs in the `opensearch-init` compose service (opensearch image, so curl and 6# the network are available; the JVM is never started — we only use its tools). 7# Waits for the cluster, then: 8# 1. Puts the index template from init-indices.json 9# 2. Creates the factory-docs index (template supplies settings + mapping) 10# Idempotent: template overwrite + index-if-absent. Exits 0 on success. 11# ============================================================================= 12set -euo pipefail 13 14OPENSEARCH_URL="${OPENSEARCH_URL:-http://localhost:9200}" 15TEMPLATE_NAME="factory-docs-template" 16INDEX_NAME="factory-docs" 17TEMPLATE_FILE="/usr/local/share/opensearch/init-indices.json" 18MAX_WAIT_SECONDS="${MAX_WAIT_SECONDS:-120}" 19TEMPLATE_PAYLOAD="$(tr -d '\n' < "$TEMPLATE_FILE")" 20 21log() { echo "[opensearch-init] $*" >&2; } 22 23log "waiting for ${OPENSEARCH_URL} (up to ${MAX_WAIT_SECONDS}s)..." 24elapsed=0 25until curl -sf "${OPENSEARCH_URL}/_cluster/health" >/dev/null 2>&1; do 26 if [ "$elapsed" -ge "$MAX_WAIT_SECONDS" ]; then 27 log "ERROR: opensearch did not become ready within ${MAX_WAIT_SECONDS}s" 28 exit 1 29 fi 30 sleep 3 31 elapsed=$((elapsed + 3)) 32 log " still waiting... (${elapsed}s)" 33done 34 35# Make sure the cluster is actually accepting writes (green/yellow ok). 36STATUS="$(curl -sf "${OPENSEARCH_URL}/_cluster/health" | sed -n 's/.*"status":"\([a-z]*\)".*/\1/p')" 37if [ "$STATUS" != "green" ] && [ "$STATUS" != "yellow" ]; then 38 log "ERROR: unexpected cluster status: ${STATUS:-unknown}" 39 exit 1 40fi 41log "cluster healthy (status=${STATUS})" 42 43# 1) Index template. 44log "PUT _index_template/${TEMPLATE_NAME}" 45HTTP_CODE="$(curl -s -o /tmp/os-template-resp.json -w '%{http_code}' -X PUT \ 46 "${OPENSEARCH_URL}/_index_template/${TEMPLATE_NAME}" \ 47 -H 'Content-Type: application/json' \ 48 -d "${TEMPLATE_PAYLOAD}")" 49if [ "$HTTP_CODE" != "200" ] && [ "$HTTP_CODE" != "201" ]; then 50 log "ERROR: template PUT returned HTTP ${HTTP_CODE}:" 51 cat /tmp/os-template-resp.json >&2 || true 52 exit 1 53fi 54log "template applied" 55 56# 2) Index (idempotent — only create when missing). 57if curl -sf "${OPENSEARCH_URL}/${INDEX_NAME}" >/dev/null 2>&1; then 58 log "index ${INDEX_NAME} already exists — skipping creation" 59else 60 log "PUT ${INDEX_NAME}" 61 HTTP_CODE="$(curl -s -o /tmp/os-index-resp.json -w '%{http_code}' -X PUT \ 62 "${OPENSEARCH_URL}/${INDEX_NAME}" -H 'Content-Type: application/json' -d '{}')" 63 if [ "$HTTP_CODE" != "200" ] && [ "$HTTP_CODE" != "201" ]; then 64 log "ERROR: index PUT returned HTTP ${HTTP_CODE}:" 65 cat /tmp/os-index-resp.json >&2 || true 66 exit 1 67 fi 68 log "index created" 69fi 70 71# Refresh so the index is queryable immediately. 72curl -sf -X POST "${OPENSEARCH_URL}/${INDEX_NAME}/_refresh" >/dev/null 73log "done: template=${TEMPLATE_NAME} index=${INDEX_NAME}" 74