github.com/misfo/deis@v1.0.1-0.20141111224634-e0eee0392b8a/database/bin/boot (about) 1 #!/bin/bash 2 # 3 # This script is designed to be run inside the container 4 # 5 6 # fail hard and fast even on pipelines 7 set -eo pipefail 8 9 # set debug based on envvar 10 [[ $DEBUG ]] && set -x 11 12 # configure etcd 13 export ETCD_PORT=${ETCD_PORT:-4001} 14 export ETCD="$HOST:$ETCD_PORT" 15 export ETCD_PATH=${ETCD_PATH:-/deis/database} 16 export ETCD_TTL=${ETCD_TTL:-10} 17 18 export BUCKET_NAME=${BUCKET_NAME:-db_wal} 19 export BACKUPS_TO_RETAIN=${BACKUPS_TO_RETAIN:-5} 20 21 # how many TTL/2 sleeps between backups -- 2160 is 3 hours 22 export BACKUP_FREQUENCY=${BACKUP_FREQUENCY:-2160} 23 24 # wait for etcd to be available 25 until etcdctl --no-sync -C $ETCD ls >/dev/null 2>&1; do 26 echo "database: waiting for etcd at $ETCD..." 27 sleep $(($ETCD_TTL/2)) # sleep for half the TTL 28 done 29 30 # wait until etcd has discarded potentially stale values 31 sleep $(($ETCD_TTL+1)) 32 33 function etcd_set_default { 34 set +e 35 etcdctl --no-sync -C $ETCD mk $ETCD_PATH/$1 $2 >/dev/null 2>&1 36 if [[ $? -ne 0 && $? -ne 4 ]]; then 37 echo "etcd_set_default: an etcd error occurred. aborting..." 38 exit 1 39 fi 40 set -e 41 } 42 43 etcd_set_default engine postgresql_psycopg2 44 etcd_set_default adminUser ${PG_ADMIN_USER:-postgres} 45 etcd_set_default adminPass ${PG_ADMIN_PASS:-changeme123} 46 etcd_set_default user ${PG_USER_NAME:-deis} 47 etcd_set_default password ${PG_USER_PASS:-changeme123} 48 etcd_set_default name ${PG_USER_DB:-deis} 49 etcd_set_default bucketName ${BUCKET_NAME} 50 51 # wait for confd to run once and install initial templates 52 until confd -onetime -node $ETCD -config-file /app/confd.toml; do 53 echo "database: waiting for confd to write initial templates..." 54 sleep $(($ETCD_TTL/2)) # sleep for half the TTL 55 done 56 57 # initialize database if one doesn't already exist 58 # for example, in the case of a data container 59 if [[ ! -d /var/lib/postgresql/9.3/main ]]; then 60 chown -R postgres:postgres /var/lib/postgresql 61 sudo -u postgres /usr/lib/postgresql/9.3/bin/initdb -D /var/lib/postgresql/9.3/main 62 fi 63 64 # ensure WAL log bucket exists 65 envdir /etc/wal-e.d/env /app/bin/create_bucket ${BUCKET_NAME} 66 67 initial_backup=0 68 if [[ ! -f /var/lib/postgresql/9.3/main/initialized ]]; then 69 echo "database: no existing database found." 70 # check if there are any backups -- if so, let's restore 71 # we could probably do better than just testing number of lines -- one line is just a heading, meaning no backups 72 if [[ `envdir /etc/wal-e.d/env wal-e --terse backup-list | wc -l` -gt "1" ]]; then 73 echo "database: restoring from backup..." 74 rm -rf /var/lib/postgresql/9.3/main 75 sudo -u postgres envdir /etc/wal-e.d/env wal-e backup-fetch /var/lib/postgresql/9.3/main LATEST 76 chown -R postgres:postgres /var/lib/postgresql/9.3/main 77 chmod 0700 /var/lib/postgresql/9.3/main 78 echo "restore_command = 'envdir /etc/wal-e.d/env wal-e wal-fetch \"%f\" \"%p\"'" | sudo -u postgres tee /var/lib/postgresql/9.3/main/recovery.conf >/dev/null 79 else 80 echo "database: no backups found. Initializing a new database..." 81 initial_backup=1 82 fi 83 # either way, we mark the database as initialized 84 touch /var/lib/postgresql/9.3/main/initialized 85 else 86 echo "database: existing data directory found. Starting postgres..." 87 fi 88 89 # run the service in the background 90 sudo -i -u postgres /usr/lib/postgresql/9.3/bin/postgres \ 91 -c config-file=${PG_CONFIG:-/etc/postgresql/9.3/main/postgresql.conf} \ 92 -c listen-addresses=${PG_LISTEN:-*} & 93 94 SERVICE_PID=$! 95 96 # smart shutdown on SIGINT and SIGTERM 97 function on_exit() { 98 kill -TERM $SERVICE_PID 99 wait $SERVICE_PID 2>/dev/null 100 exit 0 101 } 102 trap on_exit INT TERM 103 104 # spawn confd in the background to update services based on etcd changes 105 confd -node $ETCD -config-file /app/confd.toml & 106 CONFD_PID=$! 107 108 # wait for the service to become available 109 sleep 1 && while [[ -z $(netstat -lnt | awk "\$6 == \"LISTEN\" && \$4 ~ \".5432\" && \$1 ~ \"tcp.?\"") ]] ; do sleep 1; done 110 111 # perform a one-time reload to populate database entries 112 /usr/local/bin/reload 113 114 if [[ "${initial_backup}" == "1" ]] ; then 115 echo "database: performing an initial backup..." 116 # perform an initial backup 117 sudo -u postgres envdir /etc/wal-e.d/env wal-e backup-push /var/lib/postgresql/9.3/main 118 fi 119 120 echo "database: postgres is running..." 121 122 count=1 123 # publish the service to etcd using the injected HOST and EXTERNAL_PORT 124 if [[ ! -z $EXTERNAL_PORT ]]; then 125 # configure service discovery 126 PORT=${PORT:-5432} 127 PROTO=${PROTO:-tcp} 128 129 set +e 130 131 # wait for the service to become available on PORT 132 sleep 1 && while [[ -z $(netstat -lnt | awk "\$6 == \"LISTEN\" && \$4 ~ \".$PORT\" && \$1 ~ \"$PROTO.?\"") ]] ; do sleep 1; done 133 134 # while the port is listening, publish to etcd 135 while [[ ! -z $(netstat -lnt | awk "\$6 == \"LISTEN\" && \$4 ~ \".$PORT\" && \$1 ~ \"$PROTO.?\"") ]] ; do 136 etcdctl --no-sync -C $ETCD set $ETCD_PATH/host $HOST --ttl $ETCD_TTL >/dev/null 137 etcdctl --no-sync -C $ETCD set $ETCD_PATH/port $EXTERNAL_PORT --ttl $ETCD_TTL >/dev/null 138 139 # perform a backup whenever we hit BACKUP_FREQUENCY 140 # we really need cron :( 141 if [[ "${count}" -ge "${BACKUP_FREQUENCY}" ]] ; then 142 echo "database: performing a backup..." 143 if [[ -f /var/lib/postgresql/9.3/main/recovery.conf ]] ; then 144 echo "database: database is currently recovering from a backup. Will try again next loop..." 145 else 146 # perform a backup 147 sudo -u postgres envdir /etc/wal-e.d/env wal-e backup-push /var/lib/postgresql/9.3/main 148 # only retain the latest BACKUPS_TO_RETAIN backups 149 sudo -u postgres envdir /etc/wal-e.d/env wal-e delete --confirm retain ${BACKUPS_TO_RETAIN} 150 count=0 151 fi 152 fi 153 ((count++)) 154 sleep $(($ETCD_TTL/2)) # sleep for half the TTL 155 done 156 157 # if the loop quits, something went wrong 158 exit 1 159 160 fi 161 162 wait