#!/usr/bin/env bash # # integration-fixtures.sh — throwaway, self-contained fixtures for the v2-integration workflow (#757). # # up start SQL Server, PostgreSQL (seeded), QuestDB and opc-plc as containers named # otopcua-ci-*, wait until each is usable, and print the env exports the # *.IntegrationTests fixtures read (also appended to $GITHUB_ENV when set). # down remove those containers (idempotent; touches nothing else). # # Deliberately NOT the shared 10.100.0.35 host: CI must not depend on that box, and these # containers are created and destroyed inside the job. Host ports are non-default so a # developer's own fixtures are never clobbered when the script is run locally. # # Reaching the containers: on the host (or a host-network job) that is 127.0.0.1; when the job # itself runs inside a container (/.dockerenv) the published ports live on the docker host, # i.e. the container's default gateway. Override with FIXTURE_HOST. set -euo pipefail SQL_PORT="${CI_SQL_PORT:-14340}" PG_PORT="${CI_PG_PORT:-15440}" QDB_PORT="${CI_QDB_PORT:-18812}" QDB_HTTP_PORT="${CI_QDB_HTTP_PORT:-19000}" OPC_PORT="${CI_OPC_PORT:-50100}" # Throwaway-container-only credentials (never used against anything else). SA_PASSWORD="${CI_SA_PASSWORD:-Ci_throwaway_Pw1}" PG_PASSWORD="${CI_PG_PASSWORD:-Ci_throwaway_pg1}" NAMES=(otopcua-ci-mssql otopcua-ci-pg otopcua-ci-questdb otopcua-ci-opcplc) ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" fixture_host() { if [ -n "${FIXTURE_HOST:-}" ]; then echo "$FIXTURE_HOST"; return; fi if [ -f /.dockerenv ] && command -v ip >/dev/null 2>&1; then ip route | awk '/^default/{print $3; exit}'; return fi echo 127.0.0.1 } down() { docker rm -f "${NAMES[@]}" >/dev/null 2>&1 || true; } wait_for() { # local what="$1" t="$2"; shift 2 local end=$((SECONDS + t)) until "$@" >/dev/null 2>&1; do if [ "$SECONDS" -ge "$end" ]; then echo "TIMEOUT waiting for $what" >&2; return 1; fi sleep 3 done echo "ready: $what" } up() { command -v docker >/dev/null || { echo "docker not available" >&2; exit 1; } down docker run -d --name otopcua-ci-mssql -e ACCEPT_EULA=Y -e MSSQL_PID=Developer \ -e "MSSQL_SA_PASSWORD=$SA_PASSWORD" -p "$SQL_PORT:1433" \ mcr.microsoft.com/mssql/server:2022-latest >/dev/null docker run -d --name otopcua-ci-pg -e "POSTGRES_PASSWORD=$PG_PASSWORD" -e POSTGRES_DB=sqlpollfixture \ -p "$PG_PORT:5432" postgres:17-alpine >/dev/null docker run -d --name otopcua-ci-questdb -p "$QDB_PORT:8812" -p "$QDB_HTTP_PORT:9000" \ questdb/questdb:10.0.1 >/dev/null docker run -d --name otopcua-ci-opcplc -p "$OPC_PORT:$OPC_PORT" \ mcr.microsoft.com/iotedge/opc-plc:2.14.10 --pn="$OPC_PORT" --ut --aa --alm >/dev/null wait_for "postgres" 120 docker exec otopcua-ci-pg pg_isready -U postgres -d sqlpollfixture # pg_isready can answer during initdb's temp server; require a real query on the final server. wait_for "postgres query" 60 docker exec -e "PGPASSWORD=$PG_PASSWORD" otopcua-ci-pg \ psql -h 127.0.0.1 -U postgres -d sqlpollfixture -c 'select 1' docker exec -i -e "PGPASSWORD=$PG_PASSWORD" otopcua-ci-pg \ psql -v ON_ERROR_STOP=1 -v "app_password=$PG_PASSWORD" -h 127.0.0.1 -U postgres -d sqlpollfixture \ < "$ROOT/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.IntegrationTests/Docker/postgres/seed-pg.sql" >/dev/null echo "seeded: postgres" local sqlcmd=/opt/mssql-tools18/bin/sqlcmd wait_for "sql server" 300 docker exec otopcua-ci-mssql "$sqlcmd" -C -S localhost -U sa -P "$SA_PASSWORD" -Q 'SELECT 1' wait_for "questdb" 120 curl -fsS "http://$(fixture_host):$QDB_HTTP_PORT/exec?query=select%201" wait_for "opc-plc" 120 bash -c "exec 3<>/dev/tcp/$(fixture_host)/$OPC_PORT" local h; h="$(fixture_host)" local -a exports=( "SQL_TEST_ENDPOINT=$h,$SQL_PORT" "SQL_TEST_USER=sa" "SQL_TEST_PASSWORD=$SA_PASSWORD" "SQL_PG_ENDPOINT=$h:$PG_PORT" "SQL_PG_PASSWORD=$PG_PASSWORD" "HISTORIAN_SQL_TEST_CONNECTION=Server=$h,$SQL_PORT;User Id=sa;Password=$SA_PASSWORD;TrustServerCertificate=True;Encrypt=False" "HISTORIAN_QUESTDB_TEST_CONNECTION=Host=$h;Port=$QDB_PORT;Username=admin;Password=quest;Database=qdb;ServerCompatibilityMode=NoTypeLoading" "OPCUA_SIM_ENDPOINT=opc.tcp://$h:$OPC_PORT" ) for e in "${exports[@]}"; do echo "export \"$e\"" [ -n "${GITHUB_ENV:-}" ] && echo "$e" >> "$GITHUB_ENV" done } case "${1:-}" in up) up ;; down) down ;; *) echo "usage: $0 up|down" >&2; exit 2 ;; esac