github.com/mboersma/deis@v1.13.4/database/bin/boot (about)

     1  #!/usr/bin/env 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:-20}"
    17  
    18  export BUCKET_NAME=${BUCKET_NAME:-db_wal}
    19  
    20  # wait for etcd to be available
    21  until etcdctl --no-sync -C "$ETCD" ls >/dev/null 2>&1; do
    22    echo "database: waiting for etcd at $ETCD..."
    23    sleep $((ETCD_TTL/2))  # sleep for half the TTL
    24  done
    25  
    26  # wait until etcd has discarded potentially stale values
    27  sleep $((ETCD_TTL+1))
    28  
    29  function etcd_set_default {
    30    set +e
    31    ERROR="$(etcdctl --no-sync -C "$ETCD" mk "$ETCD_PATH/$1" "$2" 2>&1 >/dev/null)"
    32  
    33    if [[ $? -ne 0 ]] && echo "$ERROR" | grep -iqve "key already exists"; then
    34      echo "etcd_set_default: an etcd error occurred ($ERROR)"
    35      echo "aborting..."
    36      exit 1
    37    fi
    38    set -e
    39  }
    40  
    41  etcd_set_default engine postgresql_psycopg2
    42  etcd_set_default adminUser "${PG_ADMIN_USER:-postgres}"
    43  etcd_set_default adminPass "${PG_ADMIN_PASS:-changeme123}"
    44  etcd_set_default user "${PG_USER_NAME:-deis}"
    45  etcd_set_default password "${PG_USER_PASS:-changeme123}"
    46  etcd_set_default name "${PG_USER_DB:-deis}"
    47  etcd_set_default bucketName "${BUCKET_NAME}"
    48  
    49  # stub out the confd reload script before it gets templated
    50  echo '#!/bin/sh' > /usr/local/bin/reload
    51  chmod 0755 /usr/local/bin/reload
    52  
    53  # wait for confd to run once and install initial templates
    54  until confd -onetime -node "$ETCD" -confdir /app --log-level error; do
    55    echo "database: waiting for confd to write initial templates..."
    56    sleep $((ETCD_TTL/2))  # sleep for half the TTL
    57  done
    58  
    59  PG_DATA_DIR=/var/lib/postgresql/9.3/main
    60  
    61  # initialize database if one doesn't already exist
    62  # for example, in the case of a data container
    63  if [[ ! -d $PG_DATA_DIR ]]; then
    64    chown -R postgres:postgres /var/lib/postgresql
    65    sudo -u postgres /usr/bin/initdb -D $PG_DATA_DIR
    66  fi
    67  
    68  # ensure WAL log bucket exists
    69  envdir /etc/wal-e.d/env /app/bin/create_bucket "${BUCKET_NAME}"
    70  INIT_ID=$(etcdctl -C "$ETCD" get "$ETCD_PATH/initId" 2> /dev/null || echo none)
    71  echo "database: expecting initialization id: $INIT_ID"
    72  
    73  initial_backup=0
    74  if [[ "$(cat $PG_DATA_DIR/initialized 2> /dev/null)" != "$INIT_ID" ]]; then
    75    echo "database: no existing database found or it is outdated."
    76    # check if there are any backups -- if so, let's restore
    77    # we could probably do better than just testing number of lines -- one line is just a heading, meaning no backups
    78    BACKUP_LIST=$(envdir /etc/wal-e.d/env wal-e --terse backup-list) # if this fails, this script will exit
    79    if [[ $(echo "$BACKUP_LIST" | wc -l) -gt "1" ]]; then
    80      echo "database: restoring from backup..."
    81      rm -rf $PG_DATA_DIR
    82      sudo -u postgres envdir /etc/wal-e.d/env wal-e backup-fetch $PG_DATA_DIR LATEST
    83      chown -R postgres:postgres $PG_DATA_DIR
    84      chmod 0700 $PG_DATA_DIR
    85      echo "restore_command = 'envdir /etc/wal-e.d/env wal-e wal-fetch \"%f\" \"%p\"'" | sudo -u postgres tee $PG_DATA_DIR/recovery.conf >/dev/null
    86    else
    87      echo "database: no backups found. Initializing a new database..."
    88      initial_backup=1
    89    fi
    90    # either way, we mark the database as initialized
    91    INIT_ID=$(cat /proc/sys/kernel/random/uuid)
    92    echo "$INIT_ID" > $PG_DATA_DIR/initialized
    93    etcdctl --no-sync -C "$ETCD" set "$ETCD_PATH/initId" "$INIT_ID" >/dev/null
    94  else
    95    echo "database: existing data directory found. Starting postgres..."
    96  fi
    97  
    98  # Explicitly correct permissions on this file.  This compensates for the fact
    99  # it may have been initially written by root above, but more importantly, if
   100  # it's already owned by root, this will correct the permissions during upgrade.
   101  chown postgres:postgres /var/lib/postgresql/9.3/main/initialized
   102  
   103  # run the service in the background
   104  sudo -i -u postgres /usr/bin/postgres \
   105                      -c config-file="${PG_CONFIG:-/etc/postgresql/main/postgresql.conf}" \
   106                      -c listen-addresses="${PG_LISTEN:-*}" &
   107  
   108  SERVICE_PID=$!
   109  
   110  # smart shutdown on SIGINT and SIGTERM
   111  function on_exit() {
   112      kill -TERM $SERVICE_PID
   113      wait $SERVICE_PID 2>/dev/null
   114      exit 0
   115  }
   116  trap on_exit INT TERM
   117  
   118  # spawn confd in the background to update services based on etcd changes
   119  confd -node "$ETCD" -confdir /app --log-level error --interval 5 &
   120  
   121  # wait for the service to become available
   122  until sudo -u postgres psql -l -t >/dev/null 2>&1; do sleep 1; done
   123  
   124  # perform a one-time reload to populate database entries
   125  /usr/local/bin/reload
   126  
   127  if [[ "${initial_backup}" == "1" ]] ; then
   128    echo "database: performing an initial backup..."
   129    # perform an initial backup
   130    sudo -u postgres envdir /etc/wal-e.d/env wal-e backup-push $PG_DATA_DIR
   131  fi
   132  
   133  sudo -Eu postgres /app/bin/backup &
   134  
   135  echo "database: postgres is running..."
   136  
   137  # publish the service to etcd using the injected HOST and EXTERNAL_PORT
   138  if [[ ! -z $EXTERNAL_PORT ]]; then
   139    # configure service discovery
   140    PORT=${PORT:-5432}
   141    PROTO=${PROTO:-tcp}
   142  
   143    set +e
   144  
   145    # wait for the service to become available on PORT
   146    until sudo -u postgres psql -l -t >/dev/null 2>&1; do sleep 1; done
   147  
   148    # while the port is listening, publish to etcd
   149    while [[ ! -z $(netstat -lnt | awk "\$6 == \"LISTEN\" && \$4 ~ \".$PORT\" && \$1 ~ \"$PROTO.?\"") ]] ; do
   150      etcdctl --no-sync -C "$ETCD" set "$ETCD_PATH/host" "$HOST" --ttl "$ETCD_TTL" >/dev/null
   151      etcdctl --no-sync -C "$ETCD" set "$ETCD_PATH/port" "$EXTERNAL_PORT" --ttl "$ETCD_TTL" >/dev/null
   152      sleep $((ETCD_TTL/2)) # sleep for half the TTL
   153    done
   154  
   155    # if the loop quits, something went wrong
   156    exit 1
   157  
   158  fi
   159  
   160  wait