#!/usr/bin/env bash # ============================================================================= # AI Software Factory — OpenSearch bootstrap (one-shot) # # Runs in the `opensearch-init` compose service (opensearch image, so curl and # the network are available; the JVM is never started — we only use its tools). # Waits for the cluster, then: # 1. Puts the index template from init-indices.json # 2. Creates the factory-docs index (template supplies settings + mapping) # Idempotent: template overwrite + index-if-absent. Exits 0 on success. # ============================================================================= set -euo pipefail OPENSEARCH_URL="${OPENSEARCH_URL:-http://localhost:9200}" TEMPLATE_NAME="factory-docs-template" INDEX_NAME="factory-docs" TEMPLATE_FILE="/usr/local/share/opensearch/init-indices.json" MAX_WAIT_SECONDS="${MAX_WAIT_SECONDS:-120}" TEMPLATE_PAYLOAD="$(tr -d '\n' < "$TEMPLATE_FILE")" log() { echo "[opensearch-init] $*" >&2; } log "waiting for ${OPENSEARCH_URL} (up to ${MAX_WAIT_SECONDS}s)..." elapsed=0 until curl -sf "${OPENSEARCH_URL}/_cluster/health" >/dev/null 2>&1; do if [ "$elapsed" -ge "$MAX_WAIT_SECONDS" ]; then log "ERROR: opensearch did not become ready within ${MAX_WAIT_SECONDS}s" exit 1 fi sleep 3 elapsed=$((elapsed + 3)) log " still waiting... (${elapsed}s)" done # Make sure the cluster is actually accepting writes (green/yellow ok). STATUS="$(curl -sf "${OPENSEARCH_URL}/_cluster/health" | sed -n 's/.*"status":"\([a-z]*\)".*/\1/p')" if [ "$STATUS" != "green" ] && [ "$STATUS" != "yellow" ]; then log "ERROR: unexpected cluster status: ${STATUS:-unknown}" exit 1 fi log "cluster healthy (status=${STATUS})" # 1) Index template. log "PUT _index_template/${TEMPLATE_NAME}" HTTP_CODE="$(curl -s -o /tmp/os-template-resp.json -w '%{http_code}' -X PUT \ "${OPENSEARCH_URL}/_index_template/${TEMPLATE_NAME}" \ -H 'Content-Type: application/json' \ -d "${TEMPLATE_PAYLOAD}")" if [ "$HTTP_CODE" != "200" ] && [ "$HTTP_CODE" != "201" ]; then log "ERROR: template PUT returned HTTP ${HTTP_CODE}:" cat /tmp/os-template-resp.json >&2 || true exit 1 fi log "template applied" # 2) Index (idempotent — only create when missing). if curl -sf "${OPENSEARCH_URL}/${INDEX_NAME}" >/dev/null 2>&1; then log "index ${INDEX_NAME} already exists — skipping creation" else log "PUT ${INDEX_NAME}" HTTP_CODE="$(curl -s -o /tmp/os-index-resp.json -w '%{http_code}' -X PUT \ "${OPENSEARCH_URL}/${INDEX_NAME}" -H 'Content-Type: application/json' -d '{}')" if [ "$HTTP_CODE" != "200" ] && [ "$HTTP_CODE" != "201" ]; then log "ERROR: index PUT returned HTTP ${HTTP_CODE}:" cat /tmp/os-index-resp.json >&2 || true exit 1 fi log "index created" fi # Refresh so the index is queryable immediately. curl -sf -X POST "${OPENSEARCH_URL}/${INDEX_NAME}/_refresh" >/dev/null log "done: template=${TEMPLATE_NAME} index=${INDEX_NAME}"