mirror of
https://github.com/FerretDB/documentdb.git
synced 2026-11-06 19:12:50 -05:00
### Does this PR have any customer impact? yes ### Type (Feature, Refactoring, Bugfix, DevOps, Testing, Perf, etc) bugfix ### Does it involve schema level changes? (Table, Column, Index, UDF, etc level changes) no ### Are you introducing any new config? If yes, do you have tests with and without them being set? no ### ChangeLog (Refer [Template](../oss/CHANGELOG.md)) ### Description - enable building both locally & in docker - fix the hardcoded paths ---- #### AI description (iteration 1) #### PR Classification Enhancement: Updates to build scripts and Docker configuration to enable building the gateway both locally and in Docker. #### PR Summary This pull request revises several scripts and configuration files to integrate local and containerized build processes for the gateway. - **`/oss/scripts/emulator_entrypoint.sh`**: Refactors the configuration file handling by defining a variable and updating file permissions and copy paths. - **`/oss/scripts/build_and_start_gateway.sh`**: Introduces a local build process using Cargo (clean, build, and binary copy) and adjusts the binary execution path. - **`/oss/.github/containers/Build-Ubuntu/Dockerfile_gateway`**: Updates copy paths to place the gateway binary and configuration into the new subfolder. - **`/oss/rust-toolchain.toml` & `/oss/pg_documentdb_gw/.gitignore`**: Adds the Cargo component to the toolchain and ensures the built binary is ignored. <!-- GitOpsUserAgent=GitOps.Apps.Server.pullrequestcopilot --> Signed-off-by: Shuai Tian <shuaitian@microsoft.com>
425 lines
15 KiB
Bash
Executable File
425 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Cleanup function to handle container shutdown gracefully
|
|
cleanup() {
|
|
echo "Shutting down DocumentDB components..."
|
|
|
|
# Kill log streaming processes if they exist
|
|
for pid_var in PG_LOG_TAIL_PID SYSTEM_PG_LOG_TAIL_PID OSS_LOG_TAIL_PID GATEWAY_LOG_TAIL_PID; do
|
|
pid_value=$(eval echo \$${pid_var})
|
|
if [ -n "$pid_value" ]; then
|
|
echo "Stopping log streaming process $pid_var (PID: $pid_value)"
|
|
kill $pid_value 2>/dev/null || true
|
|
fi
|
|
done
|
|
|
|
# Kill gateway process if it exists
|
|
if [ -n "${gateway_pid:-}" ]; then
|
|
echo "Stopping gateway process (PID: $gateway_pid)"
|
|
kill $gateway_pid 2>/dev/null || true
|
|
fi
|
|
|
|
echo "Cleanup completed"
|
|
exit 0
|
|
}
|
|
|
|
# Set up signal handlers for graceful shutdown
|
|
trap cleanup SIGTERM SIGINT
|
|
|
|
# Function to start log streaming
|
|
start_log_streaming() {
|
|
local log_file="$1"
|
|
local log_prefix="$2"
|
|
local pid_var="$3"
|
|
|
|
if [ -f "$log_file" ]; then
|
|
echo "Starting log streaming from $log_file with prefix [$log_prefix]..."
|
|
tail -F "$log_file" 2>/dev/null | while IFS= read -r line; do
|
|
echo "[$log_prefix] $line"
|
|
done &
|
|
local tail_pid=$!
|
|
eval "$pid_var=$tail_pid"
|
|
echo "Log streaming started with PID: $tail_pid"
|
|
return 0
|
|
else
|
|
echo "Log file $log_file not found, skipping streaming"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Print help message
|
|
usage() {
|
|
cat << EOF
|
|
Launches DocumentDB
|
|
|
|
Optional arguments:
|
|
-h, --help Display information on available configuration
|
|
--cert-path [PATH] Specify a path to a certificate for securing traffic. You need to mount this file into the
|
|
container (e.g. if CERT_PATH=/mycert.pfx, you'd add an option like the following to your
|
|
docker run: --mount type=bind,source=./mycert.pfx,target=/mycert.pfx)
|
|
Can set CERT_SECRET to the password for the certificate.
|
|
Overrides CERT_PATH environment variable.
|
|
--key-file [PATH] Override default key with key in key file. You need to mount this file into the
|
|
container (e.g. if KEY_FILE=/mykey.key, you'd add an option like the following to your
|
|
docker run: --mount type=bind,source=./mykey.key,target=/mykey.key)
|
|
Overrides KEY_FILE environment variable.
|
|
--data-path [PATH] Specify a directory for data. Frequently used with docker run --mount option
|
|
(e.g. if DATA_PATH=/usr/documentdb/data, you'd add an option like the following to your
|
|
docker run: --mount type=bind,source=./.local/data,target=/usr/documentdb/data)
|
|
Defaults to /data
|
|
Overrides DATA_PATH environment variable.
|
|
--documentdb-port The port of the DocumentDB endpoint on the container.
|
|
You still need to publish this port (e.g. -p 10260:10260).
|
|
Defaults to 10260
|
|
Overrides PORT environment variable.
|
|
--enable-telemetry Enable telemetry data sent to the usage colletor (Azure Application Insights).
|
|
Overrides ENABLE_TELEMETRY environment variable.
|
|
--log-level The verbosity of logs that will be emitted.
|
|
Overrides LOG_LEVEL environment variable.
|
|
quiet, error, warn, info (default), debug, trace
|
|
--username Specify the username for the DocumentDB.
|
|
Defaults to default_user
|
|
Overrides USERNAME environment variable.
|
|
--password Specify the password for the DocumentDB.
|
|
REQUIRED.
|
|
Overrides PASSWORD environment variable.
|
|
--create-user Specify whether to create a user.
|
|
Defaults to true.
|
|
--start-pg Specify whether to start the PostgreSQL server.
|
|
Defaults to true.
|
|
--pg-port Specify the port for the PostgreSQL server.
|
|
Defaults to 9712.
|
|
Overrides PG_PORT environment variable.
|
|
--owner Specify the owner of the DocumentDB.
|
|
Overrides OWNER environment variable.
|
|
defaults to documentdb.
|
|
--allow-external-connections
|
|
Allow external connections to PostgreSQL.
|
|
Defaults to false.
|
|
Overrides ALLOW_EXTERNAL_CONNECTIONS environment variable.
|
|
|
|
EOF
|
|
}
|
|
|
|
if [[ -f "/version.txt" ]]; then
|
|
DocumentDB_RELEASE_VERSION=$(cat /version.txt)
|
|
echo "Release Version: $DocumentDB_RELEASE_VERSION"
|
|
fi
|
|
|
|
echo "[ENTRYPOINT] DocumentDB container starting..."
|
|
echo "[ENTRYPOINT] Log streaming will be enabled for PostgreSQL logs"
|
|
|
|
# Handle arguments
|
|
|
|
while [[ $# -gt 0 ]];
|
|
do
|
|
case $1 in
|
|
-h|--help)
|
|
usage;
|
|
exit 0;;
|
|
|
|
--cert-path)
|
|
shift
|
|
export CERT_PATH=$1
|
|
shift;;
|
|
|
|
--key-file)
|
|
shift
|
|
export KEY_FILE=$1
|
|
shift;;
|
|
|
|
--data-path)
|
|
shift
|
|
export DATA_PATH=$1
|
|
shift;;
|
|
|
|
--documentdb-port)
|
|
shift
|
|
export DOCUMENTDB_PORT=$1
|
|
shift;;
|
|
|
|
--enable-telemetry)
|
|
shift
|
|
export ENABLE_TELEMETRY=$1
|
|
shift;;
|
|
|
|
--log-level)
|
|
shift
|
|
export LOG_LEVEL=$1
|
|
shift;;
|
|
|
|
--username)
|
|
shift
|
|
export USERNAME=$1
|
|
shift;;
|
|
|
|
--password)
|
|
shift
|
|
export PASSWORD=$1
|
|
shift;;
|
|
|
|
--create-user)
|
|
shift
|
|
export CREATE_USER=$1
|
|
shift;;
|
|
|
|
--start-pg)
|
|
shift
|
|
export START_POSTGRESQL=$1
|
|
shift;;
|
|
|
|
--pg-port)
|
|
shift
|
|
export POSTGRESQL_PORT=$1
|
|
shift;;
|
|
|
|
--owner)
|
|
shift
|
|
export OWNER=$1
|
|
shift;;
|
|
|
|
--allow-external-connections)
|
|
shift
|
|
export ALLOW_EXTERNAL_CONNECTIONS=$1
|
|
shift;;
|
|
|
|
-*)
|
|
echo "Unknown option $1"
|
|
exit 1;;
|
|
esac
|
|
done
|
|
|
|
# Set default values if not provided
|
|
export OWNER=${OWNER:-$(whoami)}
|
|
export DATA_PATH=${DATA_PATH:-/data}
|
|
export DOCUMENTDB_PORT=${DOCUMENTDB_PORT:-10260}
|
|
export POSTGRESQL_PORT=${POSTGRESQL_PORT:-9712}
|
|
export USERNAME=${USERNAME:-default_user}
|
|
export PASSWORD=${PASSWORD:-Admin100}
|
|
export CREATE_USER=${CREATE_USER:-true}
|
|
export START_POSTGRESQL=${START_POSTGRESQL:-true}
|
|
|
|
# Setup centralized log directory structure
|
|
echo "Setting up centralized log directory at /var/log/documentdb..."
|
|
sudo mkdir -p /var/log/documentdb/postgres
|
|
sudo chown -R documentdb:documentdb /var/log/documentdb
|
|
sudo chmod -R 755 /var/log/documentdb
|
|
|
|
# Define centralized log file paths
|
|
export ENTRYPOINT_LOG="/var/log/documentdb/gateway_entrypoint.log"
|
|
export GATEWAY_LOG="/var/log/documentdb/gateway.log"
|
|
export OSS_SERVER_LOG="/var/log/documentdb/oss_server.log"
|
|
# Note: PostgreSQL log will be symlinked after PostgreSQL starts
|
|
export PG_LOG_FILE="/var/log/documentdb/postgres/pglog.log"
|
|
|
|
echo "Centralized log directory created with the following structure:"
|
|
echo " /var/log/documentdb/gateway_entrypoint.log"
|
|
echo " /var/log/documentdb/gateway.log"
|
|
echo " /var/log/documentdb/oss_server.log"
|
|
echo " /var/log/documentdb/postgres/pglog.log (will be symlinked)"
|
|
|
|
# Validate required parameters
|
|
if [ -z "${PASSWORD:-}" ]; then
|
|
echo "Error: PASSWORD is required. Please provide a password using --password argument or PASSWORD environment variable."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Using username: $USERNAME"
|
|
echo "Using owner: $OWNER"
|
|
echo "Using data path: $DATA_PATH"
|
|
|
|
if { [ -n "${CERT_PATH:-}" ] && [ -z "${KEY_FILE:-}" ]; } || \
|
|
{ [ -z "${CERT_PATH:-}" ] && [ -n "${KEY_FILE:-}" ]; }; then
|
|
echo "Error: Both CERT_PATH and KEY_FILE must be set together, or neither should be set."
|
|
exit 1
|
|
fi
|
|
|
|
num='^[0-9]+$'
|
|
if ! [[ "$DOCUMENTDB_PORT" =~ $num ]]; then
|
|
echo "Invalid port value $DOCUMENTDB_PORT, must be a number"
|
|
exit 1
|
|
fi
|
|
|
|
if ! [[ "$POSTGRESQL_PORT" =~ $num ]]; then
|
|
echo "Invalid PostgreSQL port value $POSTGRESQL_PORT, must be a number"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "$ENABLE_TELEMETRY" ] && \
|
|
[ "$ENABLE_TELEMETRY" != "true" ] && \
|
|
[ "$ENABLE_TELEMETRY" != "false" ]; then
|
|
echo "Invalid enable-telemetry value $ENABLE_TELEMETRY, must be true or false"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "$LOG_LEVEL" ] && \
|
|
[ "$LOG_LEVEL" != "quiet" ] && \
|
|
[ "$LOG_LEVEL" != "error" ] && \
|
|
[ "$LOG_LEVEL" != "warn" ] && \
|
|
[ "$LOG_LEVEL" != "info" ] && \
|
|
[ "$LOG_LEVEL" != "debug" ] && \
|
|
[ "$LOG_LEVEL" != "trace" ]; then
|
|
echo "Invalid log level value $LOG_LEVEL, must be one of: quiet, error, warn, info, debug, trace"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$START_POSTGRESQL" = "true" ]; then
|
|
echo "Starting PostgreSQL server on port $POSTGRESQL_PORT..."
|
|
exec > >(tee -a "$ENTRYPOINT_LOG") 2> >(tee -a "$ENTRYPOINT_LOG" >&2)
|
|
|
|
# Fix permissions on data directory to prevent "Permission denied" errors
|
|
echo "Ensuring proper permissions on data directory: $DATA_PATH"
|
|
if [ ! -d "$DATA_PATH" ]; then
|
|
echo "Creating data directory: $DATA_PATH"
|
|
sudo mkdir -p "$DATA_PATH"
|
|
fi
|
|
|
|
# Change ownership to documentdb user to ensure we can write/delete files
|
|
echo "Setting ownership of $DATA_PATH to documentdb user"
|
|
sudo chown -R documentdb:documentdb "$DATA_PATH"
|
|
|
|
# Ensure we have full permissions on the directory
|
|
echo "Setting permissions on $DATA_PATH"
|
|
sudo chmod -R 750 "$DATA_PATH"
|
|
|
|
if ALLOW_EXTERNAL_CONNECTIONS="true"; then
|
|
echo "Allowing external connections to PostgreSQL..."
|
|
export PGOPTIONS="-e"
|
|
fi
|
|
echo "Starting OSS server..."
|
|
/home/documentdb/gateway/scripts/start_oss_server.sh $PGOPTIONS -d $DATA_PATH -p $POSTGRESQL_PORT | tee -a "$OSS_SERVER_LOG"
|
|
|
|
echo "OSS server started."
|
|
echo "[ENTRYPOINT] Setting up PostgreSQL log streaming..."
|
|
|
|
# Start streaming PostgreSQL logs to docker logs
|
|
# Note: We exclude ENTRYPOINT_LOG_TAIL_PID to prevent recursion
|
|
PG_LOG_TAIL_PID=""
|
|
SYSTEM_PG_LOG_TAIL_PID=""
|
|
OSS_LOG_TAIL_PID=""
|
|
GATEWAY_LOG_TAIL_PID=""
|
|
|
|
echo "Setting up PostgreSQL log streaming from $PG_LOG_FILE..."
|
|
|
|
# Wait for PostgreSQL log file to be created in the data directory
|
|
ACTUAL_PG_LOG="$DATA_PATH/pglog.log"
|
|
i=0
|
|
while [ ! -f "$ACTUAL_PG_LOG" ] && [ $i -lt 30 ]; do
|
|
sleep 1
|
|
i=$((i + 1))
|
|
done
|
|
|
|
# Create symlink from centralized location to actual PostgreSQL log
|
|
if [ -f "$ACTUAL_PG_LOG" ]; then
|
|
echo "Creating symlink: $PG_LOG_FILE -> $ACTUAL_PG_LOG"
|
|
ln -sf "$ACTUAL_PG_LOG" "$PG_LOG_FILE"
|
|
else
|
|
echo "Warning: PostgreSQL log file not found at $ACTUAL_PG_LOG"
|
|
fi
|
|
|
|
# Start streaming main PostgreSQL log
|
|
start_log_streaming "$PG_LOG_FILE" "POSTGRES" "PG_LOG_TAIL_PID"
|
|
|
|
# Also stream system PostgreSQL logs if they exist
|
|
SYSTEM_PG_LOG="/var/log/postgresql/postgresql-17-main.log"
|
|
start_log_streaming "$SYSTEM_PG_LOG" "POSTGRES-SYSTEM" "SYSTEM_PG_LOG_TAIL_PID"
|
|
|
|
# Stream OSS server logs
|
|
start_log_streaming "$OSS_SERVER_LOG" "OSS-SERVER" "OSS_LOG_TAIL_PID"
|
|
|
|
# NOTE: We do NOT stream entrypoint logs to prevent infinite recursion!
|
|
# The entrypoint messages are already going to stdout/stderr and appear in docker logs
|
|
# ENTRYPOINT_LOG="/home/documentdb/gateway_entrypoint.log"
|
|
# start_log_streaming "$ENTRYPOINT_LOG" "ENTRYPOINT" "ENTRYPOINT_LOG_TAIL_PID"
|
|
|
|
echo "Checking if PostgreSQL is running..."
|
|
i=0
|
|
while [ ! -f "$DATA_PATH/postmaster.pid" ]; do
|
|
sleep 1
|
|
if [ $i -ge 60 ]; then
|
|
echo "PostgreSQL failed to start within 60 seconds."
|
|
cat "$OSS_SERVER_LOG"
|
|
exit 1
|
|
fi
|
|
i=$((i + 1))
|
|
done
|
|
echo "PostgreSQL is running."
|
|
else
|
|
echo "Skipping PostgreSQL server start."
|
|
fi
|
|
|
|
# Setting up the configuration file
|
|
mkdir -p /home/documentdb/gateway/pg_documentdb_gw/target
|
|
configFile="/home/documentdb/gateway/pg_documentdb_gw/target/SetupConfiguration_temp.json"
|
|
cp /home/documentdb/gateway/pg_documentdb_gw/SetupConfiguration.json $configFile
|
|
sudo chmod 755 $configFile
|
|
|
|
if [ -n "${DOCUMENTDB_PORT:-}" ]; then
|
|
echo "Updating GatewayListenPort in the configuration file..."
|
|
jq ".GatewayListenPort = $DOCUMENTDB_PORT" $configFile > $configFile.tmp && \
|
|
mv $configFile.tmp $configFile
|
|
fi
|
|
|
|
if [ -n "${POSTGRESQL_PORT:-}" ]; then
|
|
echo "Updating PostgresPort in the configuration file..."
|
|
jq ".PostgresPort = $POSTGRESQL_PORT" $configFile > $configFile.tmp && \
|
|
mv $configFile.tmp $configFile
|
|
fi
|
|
|
|
if [ -n "${CERT_PATH:-}" ] && [ -n "${KEY_FILE:-}" ]; then
|
|
echo "Adding CertificateOptions to the configuration file..."
|
|
jq --arg certPath "$CERT_PATH" --arg keyFilePath "$KEY_FILE" \
|
|
'.CertificateOptions = { "CertType": "PemFile", "FilePath": $certPath, "KeyFilePath": $keyFilePath }' \
|
|
$configFile > $configFile.tmp && \
|
|
mv $configFile.tmp $configFile
|
|
fi
|
|
|
|
echo "Starting gateway in the background..."
|
|
if [ "$CREATE_USER" = "false" ]; then
|
|
echo "Skipping user creation and starting the gateway..."
|
|
/home/documentdb/gateway/scripts/build_and_start_gateway.sh -s -d $configFile -P $POSTGRESQL_PORT -o $OWNER | tee -a "$GATEWAY_LOG" &
|
|
else
|
|
/home/documentdb/gateway/scripts/build_and_start_gateway.sh -u $USERNAME -p $PASSWORD -d $configFile -P $POSTGRESQL_PORT -o $OWNER | tee -a "$GATEWAY_LOG" &
|
|
fi
|
|
|
|
gateway_pid=$! # Capture the PID of the gateway process
|
|
|
|
# Also stream existing gateway logs (for historical logs that might already exist)
|
|
if [ -f "$GATEWAY_LOG" ]; then
|
|
echo "Starting gateway log streaming for existing logs..."
|
|
tail -F "$GATEWAY_LOG" 2>/dev/null | while IFS= read -r line; do
|
|
echo "[GATEWAY-FILE] $line"
|
|
done &
|
|
GATEWAY_LOG_TAIL_PID=$!
|
|
echo "Gateway log file streaming started with PID: $GATEWAY_LOG_TAIL_PID"
|
|
fi
|
|
|
|
echo "Gateway started with PID: $gateway_pid"
|
|
echo ""
|
|
echo "=== DocumentDB is ready ==="
|
|
echo "All logs are being streamed to docker logs with prefixes:"
|
|
echo " [POSTGRES] - PostgreSQL database logs ($PG_LOG_FILE)"
|
|
echo " [POSTGRES-SYSTEM] - System PostgreSQL logs (/var/log/postgresql/postgresql-17-main.log)"
|
|
echo " [OSS-SERVER] - OSS server logs ($OSS_SERVER_LOG)"
|
|
echo " [ENTRYPOINT] - Entrypoint script logs ($ENTRYPOINT_LOG)"
|
|
echo " [GATEWAY] - Gateway application logs (live output via tee)"
|
|
echo " [GATEWAY-FILE] - Gateway log file content ($GATEWAY_LOG)"
|
|
echo ""
|
|
echo "Centralized log directory structure:"
|
|
echo " /var/log/documentdb/"
|
|
echo " ├── gateway_entrypoint.log"
|
|
echo " ├── gateway.log"
|
|
echo " ├── oss_server.log"
|
|
echo " └── postgres/"
|
|
echo " └── pglog.log -> $DATA_PATH/pglog.log"
|
|
echo ""
|
|
echo "View all logs with: docker logs <container_name>"
|
|
echo "View live logs with: docker logs -f <container_name>"
|
|
echo "Filter specific logs: docker logs <container_name> | grep '[PREFIX]'"
|
|
echo "Example: docker logs <container_name> | grep '[POSTGRES]'"
|
|
echo "=========================="
|
|
echo ""
|
|
|
|
# Wait for the gateway process to keep the container alive
|
|
# The wait will be interrupted by signals, allowing cleanup to run
|
|
wait $gateway_pid |