#!/usr/bin/env bash # ============================================================================= # eBdesk SiCABE — Seed StarRocks: External Catalog (Nessie) + Native Shared Tables # ============================================================================= # Idempoten: # 1. Pastikan external catalog 'iceberg_catalog' → Nessie (query Iceberg). # 2. Buat database native 'sicabe' di default_catalog. # 3. Buat tabel native shared-data 'sicabe.orders' + 'sicabe.products' # (otomatis CLOUD_NATIVE via default storage volume 's3_volume' → MinIO). # 4. Seed data contoh (hanya bila kosong). # 5. GRANT object privileges ke role (RBAC internal — tanpa ini user OIDC # bisa login tapi tabel tidak terlihat). # # Pemakaian: # cd deploy # set -a; source config/environment.defaults.sh; source .env; set +a # ./scripts/seed-starrocks.sh # # Env (opsional): # STARROCKS_FE_CONTAINER (sicabe-starrocks-fe), STARROCKS_ROOT_PASSWORD, # SEED_DB (sicabe) # ============================================================================= set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "${SCRIPT_DIR}" source "${SCRIPT_DIR}/lib/common.sh" source "${SCRIPT_DIR}/config/environment.defaults.sh" sicabe_load_env "${SCRIPT_DIR}" "$@" SR_CONTAINER="${STARROCKS_FE_CONTAINER:-sicabe-starrocks-fe}" SR_PASSWORD="${STARROCKS_ROOT_PASSWORD:?set STARROCKS_ROOT_PASSWORD}" SEED_DB="${SEED_DB:-sicabe}" # Multi-host: StarRocks FE ada di host `compute`; `docker exec` bersifat lokal. sicabe_require_local_container "${SR_CONTAINER}" "StarRocks FE" "compute" || exit $? # Jalankan SQL via mysql client di dalam container FE (selalu tersedia di image). sr_sql() { docker exec "${SR_CONTAINER}" mysql -h 127.0.0.1 -P 9030 -u root -p"${SR_PASSWORD}" -N -e "$1" 2>/dev/null } # ─── 1. External catalog Nessie (idempoten) ───────────────────────────────── ensure_external_catalog() { echo -e "${INFO} [1/5] Pastikan external catalog 'iceberg_catalog' → Nessie..." if sr_sql "SHOW CATALOGS;" | grep -q "iceberg_catalog"; then echo -e "${OK} Catalog 'iceberg_catalog' sudah ada." return 0 fi sr_sql "CREATE EXTERNAL CATALOG iceberg_catalog PROPERTIES ( 'type' = 'iceberg', 'iceberg.catalog.type' = 'rest', 'iceberg.catalog.uri' = '${NESSIE_URL:-http://nessie:19120}/iceberg/', 'iceberg.catalog.warehouse' = '${ICEBERG_WAREHOUSE:-warehouse}', 'iceberg.catalog.rest.nested-namespace-enabled' = 'true', 'aws.s3.endpoint' = '${S3_ENDPOINT:-http://minio:9000}', 'aws.s3.access_key' = '${S3_ACCESS_KEY:-${MINIO_ROOT_USER:-minioadmin}}', 'aws.s3.secret_key' = '${S3_SECRET_KEY:-${MINIO_ROOT_PASSWORD}}', 'aws.s3.enable_path_style_access' = 'true', 'aws.s3.region' = '${S3_REGION:-us-east-1}' );" && echo -e "${OK} Catalog 'iceberg_catalog' dibuat." } # ─── 2. Database native ───────────────────────────────────────────────────── ensure_native_db() { echo -e "${INFO} [2/5] Database native '${SEED_DB}'..." sr_sql "CREATE DATABASE IF NOT EXISTS ${SEED_DB};" \ && echo -e "${OK} Database '${SEED_DB}' siap." } # ─── 3. Tabel native shared-data (→ MinIO via default storage volume) ─────── ensure_native_tables() { echo -e "${INFO} [3/5] Tabel native shared-data (→ MinIO via 's3_volume')..." sr_sql "CREATE TABLE IF NOT EXISTS ${SEED_DB}.orders ( id INT NOT NULL, item VARCHAR(50), customer VARCHAR(50), qty INT, price DECIMAL(10,2), ts DATETIME ) DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 3 PROPERTIES (\"replication_num\" = \"1\");" \ && echo -e "${OK} Tabel '${SEED_DB}.orders' siap." sr_sql "CREATE TABLE IF NOT EXISTS ${SEED_DB}.products ( id INT NOT NULL, name VARCHAR(50), category VARCHAR(50), price DECIMAL(10,2) ) DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 3 PROPERTIES (\"replication_num\" = \"1\");" \ && echo -e "${OK} Tabel '${SEED_DB}.products' siap." } # ─── 4. Seed data (hanya bila kosong) ─────────────────────────────────────── seed_rows() { echo -e "${INFO} [4/5] Seed data contoh (bila kosong)..." local cnt cnt=$(sr_sql "SELECT count(*) FROM ${SEED_DB}.orders;" || true); cnt="${cnt:-0}" if [[ "${cnt}" -gt 0 ]]; then echo -e "${OK} '${SEED_DB}.orders' sudah berisi ${cnt} baris (skip)." else sr_sql "INSERT INTO ${SEED_DB}.orders VALUES (1,'laptop','alice',2,1500.00,'2026-09-01 09:00:00'), (2,'monitor','budi',1,300.50,'2026-09-02 10:30:00'), (3,'keyboard','citra',3,75.25,'2026-09-03 11:00:00');" \ && echo -e "${OK} 3 baris → '${SEED_DB}.orders'." fi local pcnt pcnt=$(sr_sql "SELECT count(*) FROM ${SEED_DB}.products;" || true); pcnt="${pcnt:-0}" if [[ "${pcnt}" -gt 0 ]]; then echo -e "${OK} '${SEED_DB}.products' sudah berisi ${pcnt} baris (skip)." else sr_sql "INSERT INTO ${SEED_DB}.products VALUES (1,'laptop','elektronik',1500.00), (2,'monitor','elektronik',300.50), (3,'keyboard','aksesoris',75.25), (4,'kursi','furnitur',450.00);" \ && echo -e "${OK} 4 baris → '${SEED_DB}.products'." fi } # ─── 5. GRANT object privileges ke role (RBAC internal) ───────────────────── # Role di-map dari grup eksternal (bootstrap Step 5: GRANT role TO EXTERNAL # GROUP). Tanpa object privilege, user OIDC bisa login tapi tidak melihat tabel. grant_roles() { echo -e "${INFO} [5/5] GRANT object privileges ke role (RBAC internal)..." local role for role in sr_admin sr_engineer sr_analyst sr_viewer; do sr_sql "CREATE ROLE ${role};" >/dev/null 2>&1 || true done sr_sql "GRANT SELECT ON ALL TABLES IN DATABASE ${SEED_DB} TO ROLE sr_analyst;" >/dev/null 2>&1 \ && echo -e "${OK} sr_analyst: SELECT ${SEED_DB}.*" sr_sql "GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN DATABASE ${SEED_DB} TO ROLE sr_engineer;" >/dev/null 2>&1 \ && echo -e "${OK} sr_engineer: RW ${SEED_DB}.*" sr_sql "GRANT SELECT,INSERT,UPDATE,DELETE,ALTER,DROP ON ALL TABLES IN ALL DATABASES TO ROLE sr_admin;" >/dev/null 2>&1 \ && echo -e "${OK} sr_admin: ALL (semua database)" echo -e "${INFO} sr_viewer: tanpa grant (fail-closed)" } # ─── Verifikasi ───────────────────────────────────────────────────────────── verify() { echo -e "${INFO} Verifikasi:" echo " Catalogs:" sr_sql "SHOW CATALOGS;" | sed 's/^/ /' echo " Native tables (default_catalog.${SEED_DB}):" sr_sql "SHOW TABLES FROM ${SEED_DB};" | sed 's/^/ /' echo " ${SEED_DB}.orders:" sr_sql "SELECT id,item,customer,qty,price FROM ${SEED_DB}.orders ORDER BY id;" | sed 's/^/ /' echo " External (Nessie) iceberg_catalog.bronze.orders:" sr_sql "SELECT id,komoditas,harga_per_kg FROM iceberg_catalog.bronze.orders ORDER BY id;" | sed 's/^/ /' } # ─── MAIN ─────────────────────────────────────────────────────────────────── main() { echo -e "${BOLD}${BLUE}═══ Seed StarRocks — catalog Nessie + tabel native shared (${SEED_DB}) ═══${NC}" if ! docker ps --format '{{.Names}}' | grep -q "^${SR_CONTAINER}$"; then echo -e "${ERR} Container '${SR_CONTAINER}' tidak running." exit 1 fi ensure_external_catalog ensure_native_db ensure_native_tables seed_rows grant_roles verify echo -e "${OK} ${GREEN}Seed StarRocks selesai.${NC}" } main "$@"