-
Notifications
You must be signed in to change notification settings - Fork 849
Expand file tree
/
Copy pathentrypoint.sh
More file actions
executable file
·187 lines (165 loc) · 8.84 KB
/
entrypoint.sh
File metadata and controls
executable file
·187 lines (165 loc) · 8.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env bash
# Fixup the passwd file, in case we're on OpenShift
if ! whoami &>/dev/null && [[ $(id -u) != 5050 && -w /etc/passwd ]]; then
echo "${USER_NAME:-pgadminr}:x:$(id -u):0:${USER_NAME:-pgadminr} user:${HOME}:/sbin/nologin" >> /etc/passwd
fi
# usage: file_env VAR [DEFAULT] ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, for Docker's secrets feature)
function file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [[ -n ${!var:-} && -n ${!fileVar:-} ]]; then
printf >&2 'error: both %s and %s are set (but are exclusive)\n' "$var" "$fileVar"
exit 1
fi
local val="$def"
if [[ -n ${!var:-} ]]; then
val="${!var}"
elif [[ -n ${!fileVar:-} ]]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
# Set values for config variables that can be passed using secrets
if [[ -n $PGADMIN_CONFIG_CONFIG_DATABASE_URI_FILE ]]; then
file_env PGADMIN_CONFIG_CONFIG_DATABASE_URI
fi
file_env PGADMIN_DEFAULT_PASSWORD
# TO enable custom path for config_distro, pass config distro path via environment variable.
export CONFIG_DISTRO_FILE_PATH="${PGADMIN_CUSTOM_CONFIG_DISTRO_FILE:-/pgadmin4/config_distro.py}"
# Populate config_distro.py. This has some default config, as well as anything
# provided by the user through the PGADMIN_CONFIG_* environment variables.
# Only update the file on first launch. The empty file is created only in default path during the
# container build so it can have the required ownership.
if [[ ! -e $CONFIG_DISTRO_FILE_PATH || $(wc -m "${CONFIG_DISTRO_FILE_PATH}" 2>/dev/null | awk '{ print $1 }') == 0 ]]; then
cat << EOF > "${CONFIG_DISTRO_FILE_PATH}"
CA_FILE = '/etc/ssl/certs/ca-certificates.crt'
LOG_FILE = '/dev/null'
HELP_PATH = '../../docs'
DEFAULT_BINARY_PATHS = {
'pg': '/usr/local/pgsql-18',
'pg-18': '/usr/local/pgsql-18',
'pg-17': '/usr/local/pgsql-17',
'pg-16': '/usr/local/pgsql-16',
'pg-15': '/usr/local/pgsql-15',
'pg-14': '/usr/local/pgsql-14',
'pg-13': '/usr/local/pgsql-13'
}
EOF
# This is a bit kludgy, but necessary as the container uses BusyBox/ash as
# it's shell and not bash which would allow a much cleaner implementation
for var in $(env | grep "^PGADMIN_CONFIG_" | cut -d "=" -f 1); do
# shellcheck disable=SC2086
# shellcheck disable=SC2046
echo ${var#PGADMIN_CONFIG_} = $(eval "echo \$$var") >> "${CONFIG_DISTRO_FILE_PATH}"
done
fi
# Check whether the external configuration database exists if it is being used.
external_config_db_exists="False"
if [[ -n $PGADMIN_CONFIG_CONFIG_DATABASE_URI ]]; then
external_config_db_exists=$(cd /pgadmin4/pgadmin/utils && /venv/bin/python3 -c "from check_external_config_db import check_external_config_db; val = check_external_config_db("${PGADMIN_CONFIG_CONFIG_DATABASE_URI}"); print(val)")
fi
# DRY of the code to load the PGADMIN_SERVER_JSON_FILE
function load_server_json_file() {
export PGADMIN_SERVER_JSON_FILE="${PGADMIN_SERVER_JSON_FILE:-/pgadmin4/servers.json}"
EXTRA_ARGS=""
if [[ $PGADMIN_REPLACE_SERVERS_ON_STARTUP == 'True' ]]; then
EXTRA_ARGS="--replace"
fi
if [[ -f $PGADMIN_SERVER_JSON_FILE ]]; then
# When running in Desktop mode, no user is created
# so we have to import servers anonymously
if [[ $PGADMIN_CONFIG_SERVER_MODE == 'False' ]]; then
/venv/bin/python3 /pgadmin4/setup.py load-servers "${PGADMIN_SERVER_JSON_FILE}" ${EXTRA_ARGS}
else
/venv/bin/python3 /pgadmin4/setup.py load-servers "${PGADMIN_SERVER_JSON_FILE}" --user "${PGADMIN_DEFAULT_EMAIL}" ${EXTRA_ARGS}
fi
fi
}
if [[ ! -f /var/lib/pgadmin/pgadmin4.db && $external_config_db_exists == 'False' ]]; then
if [[ -z $PGADMIN_DEFAULT_EMAIL || (-z $PGADMIN_DEFAULT_PASSWORD && -z $PGADMIN_DEFAULT_PASSWORD_FILE) ]]; then
echo 'You need to define the PGADMIN_DEFAULT_EMAIL and PGADMIN_DEFAULT_PASSWORD or PGADMIN_DEFAULT_PASSWORD_FILE environment variables.'
exit 1
fi
# Validate PGADMIN_DEFAULT_EMAIL
CHECK_EMAIL_DELIVERABILITY="False"
if [[ -n $PGADMIN_CONFIG_CHECK_EMAIL_DELIVERABILITY ]]; then
CHECK_EMAIL_DELIVERABILITY=${PGADMIN_CONFIG_CHECK_EMAIL_DELIVERABILITY}
fi
ALLOW_SPECIAL_EMAIL_DOMAINS="[]"
if [[ -n $PGADMIN_CONFIG_ALLOW_SPECIAL_EMAIL_DOMAINS ]]; then
ALLOW_SPECIAL_EMAIL_DOMAINS=${PGADMIN_CONFIG_ALLOW_SPECIAL_EMAIL_DOMAINS}
fi
GLOBALLY_DELIVERABLE="True"
if [[ -n $PGADMIN_CONFIG_GLOBALLY_DELIVERABLE ]]; then
GLOBALLY_DELIVERABLE=${PGADMIN_CONFIG_GLOBALLY_DELIVERABLE}
fi
email_config="{'CHECK_EMAIL_DELIVERABILITY': ${CHECK_EMAIL_DELIVERABILITY}, 'ALLOW_SPECIAL_EMAIL_DOMAINS': ${ALLOW_SPECIAL_EMAIL_DOMAINS}, 'GLOBALLY_DELIVERABLE': ${GLOBALLY_DELIVERABLE}}"
echo "email config is ${email_config}"
is_valid_email=$(cd /pgadmin4/pgadmin/utils && /venv/bin/python3 -c "from validation_utils import validate_email; val = validate_email('${PGADMIN_DEFAULT_EMAIL}', ${email_config}); print(val)")
if echo "${is_valid_email}" | grep "False" &>/dev/null; then
echo "'${PGADMIN_DEFAULT_EMAIL}' does not appear to be a valid email address. Please reset the PGADMIN_DEFAULT_EMAIL environment variable and try again."
echo "Validation output: ${is_valid_email}"
exit 1
fi
# Switch back to root directory for further process
cd /pgadmin4
# Set the default username and password in a
# backwards compatible way
export PGADMIN_SETUP_EMAIL="${PGADMIN_DEFAULT_EMAIL}"
export PGADMIN_SETUP_PASSWORD="${PGADMIN_DEFAULT_PASSWORD}"
# Initialize DB before starting Gunicorn
# Importing pgadmin4 (from this script) is enough
/venv/bin/python3 run_pgadmin.py
export PGADMIN_PREFERENCES_JSON_FILE="${PGADMIN_PREFERENCES_JSON_FILE:-/pgadmin4/preferences.json}"
# Pre-load any required servers
load_server_json_file
# Pre-load any required preferences
if [[ -f $PGADMIN_PREFERENCES_JSON_FILE ]]; then
if [[ $PGADMIN_CONFIG_SERVER_MODE == 'False' ]]; then
DESKTOP_USER=$(cd /pgadmin4 && /venv/bin/python3 -c 'import config; print(config.DESKTOP_USER)')
/venv/bin/python3 /pgadmin4/setup.py set-prefs "${DESKTOP_USER}" --input-file "${PGADMIN_PREFERENCES_JSON_FILE}"
else
/venv/bin/python3 /pgadmin4/setup.py set-prefs "${PGADMIN_DEFAULT_EMAIL}" --input-file "${PGADMIN_PREFERENCES_JSON_FILE}"
fi
fi
# Copy the pgpass file passed using secrets
if [[ -f $PGPASS_FILE ]]; then
if [[ $PGADMIN_CONFIG_SERVER_MODE == 'False' ]]; then
cp ${PGPASS_FILE} /var/lib/pgadmin/.pgpass
chmod 600 /var/lib/pgadmin/.pgpass
else
PGADMIN_USER_CONFIG_DIR=$(echo "${PGADMIN_DEFAULT_EMAIL}" | sed 's/@/_/g')
mkdir -p /var/lib/pgadmin/storage/${PGADMIN_USER_CONFIG_DIR}
cp ${PGPASS_FILE} /var/lib/pgadmin/storage/${PGADMIN_USER_CONFIG_DIR}/.pgpass
chmod 600 /var/lib/pgadmin/storage/${PGADMIN_USER_CONFIG_DIR}/.pgpass
fi
fi
# If already initialised and PGADMIN_REPLACE_SERVERS_ON_STARTUP is set to true, then load the server json file.
elif [[ $PGADMIN_REPLACE_SERVERS_ON_STARTUP == 'True' ]]; then
load_server_json_file
fi
# Start Postfix to handle password resets etc.
if [[ -z $PGADMIN_DISABLE_POSTFIX ]]; then
sudo /usr/sbin/postfix start
fi
# Get the session timeout from the pgAdmin config. We'll use this (in seconds)
# to define the Gunicorn worker timeout
TIMEOUT=$(cd /pgadmin4 && /venv/bin/python3 -c 'import config; print(config.SESSION_EXPIRATION_TIME * 60 * 60 * 24)')
# NOTE: currently pgadmin can run only with 1 worker due to sessions implementation
# Using --threads to have multi-threaded single-process worker
if [[ -n $PGADMIN_ENABLE_SOCK ]]; then
BIND_ADDRESS="unix:/run/pgadmin/pgadmin.sock"
elif [[ -n $PGADMIN_ENABLE_TLS ]]; then
BIND_ADDRESS="${PGADMIN_LISTEN_ADDRESS:-[::]}:${PGADMIN_LISTEN_PORT:-443}"
else
BIND_ADDRESS="${PGADMIN_LISTEN_ADDRESS:-[::]}:${PGADMIN_LISTEN_PORT:-80}"
fi
if [[ -n $PGADMIN_ENABLE_TLS ]]; then
exec /venv/bin/gunicorn --limit-request-line "${GUNICORN_LIMIT_REQUEST_LINE:-8190}" --timeout "${TIMEOUT}" --bind "${BIND_ADDRESS}" -w 1 --threads "${GUNICORN_THREADS:-25}" --access-logfile "${GUNICORN_ACCESS_LOGFILE:--}" --keyfile /certs/server.key --certfile /certs/server.cert -c gunicorn_config.py run_pgadmin:app
else
exec /venv/bin/gunicorn --limit-request-line "${GUNICORN_LIMIT_REQUEST_LINE:-8190}" --limit-request-fields "${GUNICORN_LIMIT_REQUEST_FIELDS:-100}" --limit-request-field_size "${GUNICORN_LIMIT_REQUEST_FIELD_SIZE:-8190}" --timeout "${TIMEOUT}" --bind "${BIND_ADDRESS}" -w 1 --threads "${GUNICORN_THREADS:-25}" --access-logfile "${GUNICORN_ACCESS_LOGFILE:--}" -c gunicorn_config.py run_pgadmin:app
fi