github.com/gust1n/deis@v0.13.1-0.20141009230754-43ff4d95947b/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 etcdctl --no-sync -C $ETCD mk $ETCD_PATH/$1 $2 >/dev/null 2>&1 || true 35 } 36 37 etcd_set_default engine postgresql_psycopg2 38 etcd_set_default adminUser ${PG_ADMIN_USER:-postgres} 39 etcd_set_default adminPass ${PG_ADMIN_PASS:-changeme123} 40 etcd_set_default user ${PG_USER_NAME:-deis} 41 etcd_set_default password ${PG_USER_PASS:-changeme123} 42 etcd_set_default name ${PG_USER_DB:-deis} 43 etcd_set_default bucketName ${BUCKET_NAME} 44 45 # wait for confd to run once and install initial templates 46 until confd -onetime -node $ETCD -config-file /app/confd.toml; do 47 echo "database: waiting for confd to write initial templates..." 48 sleep $(($ETCD_TTL/2)) # sleep for half the TTL 49 done 50 51 # ensure WAL log bucket exists 52 envdir /etc/wal-e.d/env /app/bin/create_bucket ${BUCKET_NAME} 53 54 initial_backup=0 55 if [[ ! -f /var/lib/postgresql/9.3/main/initialized ]]; then 56 echo "database: no existing database found." 57 # check if there are any backups -- if so, let's restore 58 # we could probably do better than just testing number of lines -- one line is just a heading, meaning no backups 59 if [[ `envdir /etc/wal-e.d/env wal-e --terse backup-list | wc -l` -gt "1" ]]; then 60 echo "database: restoring from backup..." 61 rm -rf /var/lib/postgresql/9.3/main 62 sudo -u postgres envdir /etc/wal-e.d/env wal-e backup-fetch /var/lib/postgresql/9.3/main LATEST 63 chown -R postgres:postgres /var/lib/postgresql/9.3/main 64 chmod 0700 /var/lib/postgresql/9.3/main 65 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 66 else 67 echo "database: no backups found. Initializing a new database..." 68 initial_backup=1 69 fi 70 # either way, we mark the database as initialized 71 touch /var/lib/postgresql/9.3/main/initialized 72 else 73 echo "database: existing data directory found. Starting postgres..." 74 fi 75 76 # run the service in the background 77 sudo -i -u postgres /usr/lib/postgresql/9.3/bin/postgres \ 78 -c config-file=${PG_CONFIG:-/etc/postgresql/9.3/main/postgresql.conf} \ 79 -c listen-addresses=${PG_LISTEN:-*} & 80 81 SERVICE_PID=$! 82 83 # smart shutdown on SIGINT and SIGTERM 84 function on_exit() { 85 kill -TERM $SERVICE_PID 86 wait $SERVICE_PID 2>/dev/null 87 exit 0 88 } 89 trap on_exit INT TERM 90 91 # spawn confd in the background to update services based on etcd changes 92 confd -node $ETCD -config-file /app/confd.toml & 93 CONFD_PID=$! 94 95 # wait for the service to become available 96 sleep 1 && while [[ -z $(netstat -lnt | awk "\$6 == \"LISTEN\" && \$4 ~ \".5432\" && \$1 ~ \"tcp.?\"") ]] ; do sleep 1; done 97 98 # perform a one-time reload to populate database entries 99 /usr/local/bin/reload 100 101 if [[ "${initial_backup}" == "1" ]] ; then 102 echo "database: performing an initial backup..." 103 # perform an initial backup 104 sudo -u postgres envdir /etc/wal-e.d/env wal-e backup-push /var/lib/postgresql/9.3/main 105 fi 106 107 echo "database: postgres is running..." 108 109 count=1 110 # publish the service to etcd using the injected HOST and EXTERNAL_PORT 111 if [[ ! -z $EXTERNAL_PORT ]]; then 112 # configure service discovery 113 PORT=${PORT:-5432} 114 PROTO=${PROTO:-tcp} 115 116 set +e 117 118 # wait for the service to become available on PORT 119 sleep 1 && while [[ -z $(netstat -lnt | awk "\$6 == \"LISTEN\" && \$4 ~ \".$PORT\" && \$1 ~ \"$PROTO.?\"") ]] ; do sleep 1; done 120 121 # while the port is listening, publish to etcd 122 while [[ ! -z $(netstat -lnt | awk "\$6 == \"LISTEN\" && \$4 ~ \".$PORT\" && \$1 ~ \"$PROTO.?\"") ]] ; do 123 etcdctl --no-sync -C $ETCD set $ETCD_PATH/host $HOST --ttl $ETCD_TTL >/dev/null 124 etcdctl --no-sync -C $ETCD set $ETCD_PATH/port $EXTERNAL_PORT --ttl $ETCD_TTL >/dev/null 125 126 # perform a backup whenever we hit BACKUP_FREQUENCY 127 # we really need cron :( 128 if [[ "${count}" -ge "${BACKUP_FREQUENCY}" ]] ; then 129 echo "database: performing a backup..." 130 if [[ -f /var/lib/postgresql/9.3/main/recovery.conf ]] ; then 131 echo "database: database is currently recovering from a backup. Will try again next loop..." 132 else 133 # perform a backup 134 sudo -u postgres envdir /etc/wal-e.d/env wal-e backup-push /var/lib/postgresql/9.3/main 135 # only retain the latest BACKUPS_TO_RETAIN backups 136 sudo -u postgres envdir /etc/wal-e.d/env wal-e delete --confirm retain ${BACKUPS_TO_RETAIN} 137 count=0 138 fi 139 fi 140 ((count++)) 141 sleep $(($ETCD_TTL/2)) # sleep for half the TTL 142 done 143 144 # if the loop quits, something went wrong 145 exit 1 146 147 fi 148 149 wait