fix: move single-tenant DB record creation from bootstrap to installer
The bootstrap script runs before the SaaS app starts, but the tenants table only exists after Flyway migrations run in the SaaS app. This circular dependency caused Phase 12b's psql commands to fail under set -e, crashing the Logto container on first install in single-tenant mode. Now the bootstrap only handles Logto-side setup (org, user roles, OIDC redirect URIs), and the installer creates the tenant DB record after verify_health confirms the SaaS app is up. Also makes docker_compose_up tolerant of transient startup errors since verify_health is the real health gate. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -730,20 +730,8 @@ elif [ -n "$TENANT_ORG_NAME" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Insert tenant record into cameleer_saas database
|
# NOTE: Tenant DB record is created by the installer after Flyway migrations
|
||||||
pgpass
|
# have run (the tenants table doesn't exist yet at bootstrap time).
|
||||||
EXISTING_TENANT=$(psql -h "$PG_HOST" -U "$PG_USER" -d "$PG_DB_SAAS" -t -A -c \
|
|
||||||
"SELECT id FROM tenants WHERE slug = '$TENANT_SLUG';" 2>/dev/null)
|
|
||||||
if [ -z "$EXISTING_TENANT" ]; then
|
|
||||||
TENANT_UUID=$(cat /proc/sys/kernel/random/uuid 2>/dev/null || python3 -c "import uuid; print(uuid.uuid4())" 2>/dev/null)
|
|
||||||
psql -h "$PG_HOST" -U "$PG_USER" -d "$PG_DB_SAAS" -c \
|
|
||||||
"INSERT INTO tenants (id, name, slug, tier, status, logto_org_id, created_at, updated_at)
|
|
||||||
VALUES ('$TENANT_UUID', '$TENANT_ORG_NAME', '$TENANT_SLUG', 'STANDARD', 'PROVISIONING', '$TENANT_ORG_ID', NOW(), NOW());" >/dev/null 2>&1
|
|
||||||
log "Created tenant record: $TENANT_SLUG (status: PROVISIONING)"
|
|
||||||
log " The SaaS app will provision the tenant's server on next restart or via the UI."
|
|
||||||
else
|
|
||||||
log "Tenant record already exists for slug: $TENANT_SLUG"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Single-tenant setup complete."
|
log "Single-tenant setup complete."
|
||||||
|
|||||||
@@ -930,8 +930,8 @@ docker_compose_pull() {
|
|||||||
|
|
||||||
docker_compose_up() {
|
docker_compose_up() {
|
||||||
log_info "Starting Cameleer SaaS platform..."
|
log_info "Starting Cameleer SaaS platform..."
|
||||||
(cd "$INSTALL_DIR" && docker compose -p "$COMPOSE_PROJECT" up -d)
|
(cd "$INSTALL_DIR" && docker compose -p "$COMPOSE_PROJECT" up -d) || true
|
||||||
log_info "Containers started."
|
log_info "Containers started — verifying health next."
|
||||||
}
|
}
|
||||||
|
|
||||||
docker_compose_down() {
|
docker_compose_down() {
|
||||||
@@ -1018,6 +1018,58 @@ verify_health() {
|
|||||||
log_success "All services healthy."
|
log_success "All services healthy."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# --- Single-tenant DB record ---
|
||||||
|
|
||||||
|
setup_single_tenant_record() {
|
||||||
|
[ -z "$TENANT_ORG_NAME" ] && return 0
|
||||||
|
|
||||||
|
local slug
|
||||||
|
slug=$(echo "$TENANT_ORG_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g; s/--*/-/g; s/^-//; s/-$//')
|
||||||
|
|
||||||
|
log_info "Creating single-tenant record for '$TENANT_ORG_NAME' (slug: $slug)..."
|
||||||
|
|
||||||
|
# Check if tenant already exists
|
||||||
|
local existing
|
||||||
|
existing=$(cd "$INSTALL_DIR" && docker compose -p "$COMPOSE_PROJECT" exec -T postgres \
|
||||||
|
psql -U "${POSTGRES_USER}" -d cameleer_saas -t -A -c \
|
||||||
|
"SELECT id FROM tenants WHERE slug = '$slug';" 2>/dev/null) || true
|
||||||
|
|
||||||
|
if [ -n "$existing" ]; then
|
||||||
|
printf " ${GREEN}[ok]${NC} Tenant record already exists: %s\n" "$slug"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get Logto org ID from the logto database
|
||||||
|
local org_id
|
||||||
|
org_id=$(cd "$INSTALL_DIR" && docker compose -p "$COMPOSE_PROJECT" exec -T postgres \
|
||||||
|
psql -U "${POSTGRES_USER}" -d logto -t -A -c \
|
||||||
|
"SELECT id FROM organizations WHERE name = '$TENANT_ORG_NAME' AND tenant_id = 'default';" 2>/dev/null) || true
|
||||||
|
|
||||||
|
if [ -z "$org_id" ]; then
|
||||||
|
log_warn "Could not find Logto organization for '$TENANT_ORG_NAME' — tenant record not created."
|
||||||
|
log_warn "Create the tenant manually via the vendor console."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate UUID and insert
|
||||||
|
local uuid
|
||||||
|
uuid=$(cat /proc/sys/kernel/random/uuid 2>/dev/null || python3 -c "import uuid; print(uuid.uuid4())" 2>/dev/null || true)
|
||||||
|
if [ -z "$uuid" ]; then
|
||||||
|
log_warn "Could not generate UUID — tenant record not created."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if cd "$INSTALL_DIR" && docker compose -p "$COMPOSE_PROJECT" exec -T postgres \
|
||||||
|
psql -U "${POSTGRES_USER}" -d cameleer_saas -c \
|
||||||
|
"INSERT INTO tenants (id, name, slug, tier, status, logto_org_id, created_at, updated_at)
|
||||||
|
VALUES ('$uuid', '$TENANT_ORG_NAME', '$slug', 'STANDARD', 'PROVISIONING', '$org_id', NOW(), NOW());" >/dev/null 2>&1; then
|
||||||
|
printf " ${GREEN}[ok]${NC} Tenant record created: %s (status: PROVISIONING)\n" "$slug"
|
||||||
|
log_info "The SaaS app will provision the tenant's server automatically."
|
||||||
|
else
|
||||||
|
log_warn "Failed to create tenant record — create it manually via the vendor console."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# --- Output file generation ---
|
# --- Output file generation ---
|
||||||
|
|
||||||
write_config_file() {
|
write_config_file() {
|
||||||
@@ -1330,6 +1382,7 @@ handle_rerun() {
|
|||||||
docker_compose_down
|
docker_compose_down
|
||||||
docker_compose_up
|
docker_compose_up
|
||||||
verify_health
|
verify_health
|
||||||
|
setup_single_tenant_record
|
||||||
generate_install_doc
|
generate_install_doc
|
||||||
print_summary
|
print_summary
|
||||||
exit 0
|
exit 0
|
||||||
@@ -1423,6 +1476,9 @@ main() {
|
|||||||
# Verify health
|
# Verify health
|
||||||
verify_health
|
verify_health
|
||||||
|
|
||||||
|
# Create single-tenant record (after Flyway migrations have run)
|
||||||
|
setup_single_tenant_record
|
||||||
|
|
||||||
# Generate output files
|
# Generate output files
|
||||||
generate_credentials_file
|
generate_credentials_file
|
||||||
generate_install_doc
|
generate_install_doc
|
||||||
|
|||||||
Reference in New Issue
Block a user