Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions deploy/docker/base.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ RUN set -o xtrace \
&& echo "deb http://apt.postgresql.org/pub/repos/apt $(grep CODENAME /etc/lsb-release | cut -d= -f2)-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list \
&& curl --silent --show-error --location https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& apt update \
&& apt-get install --no-install-recommends --yes mongodb-org redis postgresql-13 \
&& apt-get install --no-install-recommends --yes mongodb-org redis postgresql-13 postgresql-14 \
Comment thread
sharat87 marked this conversation as resolved.
# Create a symlink to the current version of PostgreSQL
&& ln -s /usr/lib/postgresql/13 /usr/lib/postgresql/current \
&& apt-get clean

ENV PATH="/usr/lib/postgresql/13/bin:${PATH}"
ENV PATH="/usr/lib/postgresql/14/bin:${PATH}"
Comment thread
srix marked this conversation as resolved.

# Install Java
RUN set -o xtrace \
Expand Down
7 changes: 3 additions & 4 deletions deploy/docker/fs/opt/appsmith/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ set -e

tlog "Running as: $(id)"

# Temporary, remove after this change goes into `base.dockerfile`.
export PATH="/usr/lib/postgresql/13/bin:${PATH}"

stacks_path=/appsmith-stacks

export SUPERVISORD_CONF_TARGET="$TMP/supervisor-conf.d/" # export for use in supervisord.conf
Expand Down Expand Up @@ -428,7 +425,9 @@ init_postgres() {
# Postgres does not allow it's server to be run with super user access, we use user postgres and the file system owner also needs to be the same user postgres
chown -R postgres:postgres "$POSTGRES_DB_PATH" "$TMP/pg-runtime"

if [[ ! -e "$POSTGRES_DB_PATH/PG_VERSION" ]]; then
if [[ -e "$POSTGRES_DB_PATH/PG_VERSION" ]]; then
/opt/appsmith/pg-upgrade.sh
Comment thread
srix marked this conversation as resolved.
Comment thread
srix marked this conversation as resolved.
else
tlog "Initializing local Postgres data folder"
su postgres -c "env PATH='$PATH' initdb -D $POSTGRES_DB_PATH"
fi
Expand Down
91 changes: 91 additions & 0 deletions deploy/docker/fs/opt/appsmith/pg-upgrade.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/bin/bash

set -o errexit
set -o nounset

Comment thread
srix marked this conversation as resolved.
# This script will upgrade Postgres to the "current" version of Postgres, if needed.

# Assumptions:
# 1. Postgres is currently not running. The caller of this script ensures that _no_ version of Postgres server is currently running.
# 2. The newest version of Postgres we want to use, is already installed.
# 3. Postgres is installed via apt package manager only.

# Contract:
# 1. Don't install old version of Postgres, if it's already installed.
# 2. Use absolute paths to all Postgres executables, don't rely on any of them to be coming from "\$PATH".
# 3. Be idempotent across versions.
# 4. When we can't proceed due to any exceptional scenarios, communicate clearly.
# 5. Mark old/stale/deprecated data with a date, so it can be deleted with confidence later.

# TODO: Verify that no Postgres server is running.
Comment thread
sharat87 marked this conversation as resolved.
Outdated

postgres_path=/usr/lib/postgresql

pg_data_dir=/appsmith-stacks/data/postgres/main

old_version=""
if [[ -f "$pg_data_dir/PG_VERSION" ]]; then
old_version="$(cat "$pg_data_dir/PG_VERSION")"
fi

if [[ -z "$old_version" ]]; then
tlog "No existing Postgres data found, not upgrading anything." >&2
exit
fi

if [[ -f "$pg_data_dir/postmaster.pid" ]]; then
tlog "Previous Postgres was not shutdown cleanly. Please start and stop Postgres $old_version properly with 'supervisorctl' only." >&2
exit 1
fi

top_available_version="$(postgres --version | grep -o '[[:digit:]]\+' | head -1)"

declare -a to_uninstall
to_uninstall=()

# 13 to 14
if [[ "$old_version" == 13 && "$top_available_version" > "$old_version" ]]; then
if [[ ! -e "$postgres_path/$old_version" ]]; then
apt-get update
apt-get install --yes "postgresql-$old_version"
to_uninstall+=("postgresql-$old_version")
fi

new_version="$((old_version + 1))"
new_data_dir="$pg_data_dir-$new_version"

# `pg_upgrade` writes log to current folder. So change to a temp folder first.
rm -rf "$TMP/pg_upgrade" "$new_data_dir"
mkdir -p "$TMP/pg_upgrade" "$new_data_dir"
chown -R postgres "$TMP/pg_upgrade" "$new_data_dir"
cd "$TMP/pg_upgrade"

# Required by the temporary Postgres server started by `pg_upgrade`.
chown postgres /etc/ssl/private/ssl-cert-snakeoil.key
chmod 0600 /etc/ssl/private/ssl-cert-snakeoil.key

su postgres --command "
set -o errexit
set -o xtrace
'$postgres_path/$new_version/bin/initdb' --pgdata='$new_data_dir'
'$postgres_path/$new_version/bin/pg_upgrade' \
--old-datadir='$pg_data_dir' \
--new-datadir='$new_data_dir' \
--old-bindir='$postgres_path/$old_version/bin' \
--new-bindir='$postgres_path/$new_version/bin'
"

date -u '+%FT%T.%3NZ' > "$pg_data_dir/deprecated-on.txt"
mv -v "$pg_data_dir" "$pg_data_dir-$old_version"
mv -v "$new_data_dir" "$pg_data_dir"

# Dangerous generated script that deletes the now updated data folder.
rm -fv "$TMP/pg_upgrade/delete_old_cluster.sh"
fi

if [[ -n "${#to_uninstall[@]}" ]]; then
apt-get purge "${to_uninstall[@]}"
apt-get clean
fi

echo "== Fin =="
93 changes: 93 additions & 0 deletions deploy/docker/tests/pg-upgrade/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/bin/bash

# A script to test Postgres upgrades. WIP.

set -o errexit
set -o nounset
set -o xtrace

from_tag=appsmith/appsmith-ce:v1.28
Comment thread
srix marked this conversation as resolved.
to_tag=appsmith/appsmith-ce:latest

container_name=appsmith-pg-upgrade-test
port=20080

docker rm -f "$container_name"
docker volume rm --force "$container_name"
Comment thread
sharat87 marked this conversation as resolved.

# TODO: Add `--pull always` for images that have a manifest?

docker volume create "$container_name"
docker run \
--name "$container_name" \
--detach \
--publish "$port":80 \
--volume "$container_name":/appsmith-stacks \
"$from_tag"

wait-for-supervisor() {
while ! docker exec "$container_name" test -e /tmp/appsmith/supervisor.sock; do
sleep 1
done
sleep 2
}

wait-for-supervisor

docker exec "$container_name" bash -exc '
supervisorctl status \
| awk '\''$1 != "postgres" && $1 != "stdout" {print $1}'\'' \
| xargs supervisorctl stop

# Insert some sample data
su postgres -c "psql -h 127.0.0.1 -c \"
create table t (id serial, name text);
insert into t values (1, '\''one'\'');
insert into t values (2, '\''two'\'');
insert into t values (3, '\''three'\'');
\""

supervisorctl stop postgres

cat /appsmith-stacks/data/postgres/main/PG_VERSION
Comment thread
sharat87 marked this conversation as resolved.
'

docker rm -f "$container_name"

docker run \
--name "$container_name" \
--detach \
--publish "$port":80 \
--volume "$container_name":/appsmith-stacks \
"$to_tag"

wait-for-supervisor

status=0

if [[ 14 != "$(docker exec "$container_name" cat /appsmith-stacks/data/postgres/main/PG_VERSION)" ]]; then
echo "Version isn't 14"
status=1
else
sample_table_contents="$(su postgres -c 'psql -h 127.0.0.1 -c "select * from t"')"
expected_contents=' id | name
----+-------
1 | one
2 | two
3 | three
(3 rows)'
if ! diff <(echo "$expected_contents") <(su postgres -c 'psql -h 127.0.0.1 -c "select * from t"'); then
status=1
echo "Table contents mismatch. Found this:"
su postgres -c 'psql -h 127.0.0.1 -c "select * from t"'
echo "Instead of this:"
echo "$expected_contents"
fi
fi
Comment thread
sharat87 marked this conversation as resolved.
Comment thread
sharat87 marked this conversation as resolved.

docker exec -it "$container_name" bash

docker rm --force "$container_name"
docker volume rm --force "$container_name"

exit "$status"