248 lines
6.1 KiB
Bash
Executable File
248 lines
6.1 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e
|
|
|
|
DATABASE=photowall
|
|
DB_PROD=production-cluster.cluster-cfl0zi9wi0ze.eu-west-1.rds.amazonaws.com
|
|
DB_STAGE=staging-new-cluster.cluster-cfl0zi9wi0ze.eu-west-1.rds.amazonaws.com
|
|
DB_LOCAL=localhost
|
|
DUMP_FILE=~/photowall.sql
|
|
JOBS=1
|
|
|
|
throw_err()
|
|
{
|
|
echo && echo " *** Error: $1" && usage 1
|
|
}
|
|
|
|
graceful_exit()
|
|
{
|
|
echo && echo "$1" && exit 0
|
|
}
|
|
|
|
usage()
|
|
{
|
|
echo
|
|
cat <<- EOF
|
|
Usage: $0 [OPTION]... [COMMAND] [SOURCE] <TARGET>
|
|
|
|
Commands:
|
|
dump <source> dump database photowall from SOURCE
|
|
sync <source> <target> sync database photowall from SOURCE database to TARGET database
|
|
|
|
Options:
|
|
-d, --dry-run don't actually run any commands, just print them
|
|
-h, --help display this help message
|
|
-j, --jobs <num> (DEFAULT: 1) number of processes to use when restoring the dump
|
|
-p, --production tells if the restored database is production like (stage or prod).
|
|
If set, additional grants will be handled
|
|
EOF
|
|
exit ${1:-0}
|
|
}
|
|
|
|
db_exec()
|
|
{
|
|
echo "psql -h $TARGET -xU root -d ${2:-postgres} -c \"$1\""
|
|
|
|
if [ -z "$DRY_RUN" ]
|
|
then
|
|
psql -h $TARGET -xU root -d ${2:-postgres} -c "$1"
|
|
fi
|
|
}
|
|
|
|
confirm_sync()
|
|
{
|
|
cat <<- EOF
|
|
$(tput blink)
|
|
!!! WARNING !!!$(tput sgr0)$(tput bold)
|
|
DATABASE ${DATABASE}
|
|
ON ${TARGET}
|
|
WILL BE DROPPED AND REPLACED WITH THE ONE
|
|
FROM ${SOURCE}$(tput sgr0)$(tput blink)
|
|
!!! WARNING !!!$(tput sgr0)
|
|
|
|
EOF
|
|
|
|
read -rep "Are you sure this is what you want? [y/N] " -n 1 -r
|
|
[[ ! $REPLY =~ ^[Yy]$ ]] && graceful_exit "Quitting..." || true
|
|
}
|
|
|
|
create_dump()
|
|
{
|
|
echo "* Dumping database ${DATABASE} on ${SOURCE} to ${DUMP_FILE}"
|
|
echo
|
|
echo "pg_dump -h ${SOURCE} -d ${DATABASE} -U root -Fc > ${DUMP_FILE}"
|
|
if [ -z "$DRY_RUN" ]
|
|
then
|
|
pg_dump -h $SOURCE -d $DATABASE -U root -Fc > ${DUMP_FILE}
|
|
fi
|
|
}
|
|
|
|
dump()
|
|
{
|
|
## Check if dump file already exists
|
|
if [ -f "$DUMP_FILE" ]
|
|
then
|
|
FDATA=$(date -r $DUMP_FILE "+%Y-%m-%d %H:%M:%S")
|
|
echo
|
|
echo "File $DUMP_FILE ($FDATA) already exists."
|
|
read -rep "Use that instead? [y/N/q] " -n 1 -r
|
|
case "$REPLY" in
|
|
[yY])
|
|
echo
|
|
echo "* Using existing dump file ($FDATA)"
|
|
;;
|
|
[nN])
|
|
echo
|
|
create_dump
|
|
;;
|
|
*)
|
|
graceful_exit "Quitting..."
|
|
;;
|
|
esac
|
|
else
|
|
echo '* Dump file not found'
|
|
echo
|
|
create_dump
|
|
fi
|
|
}
|
|
|
|
provision()
|
|
{
|
|
db_exec "
|
|
SELECT pg_terminate_backend(pg_stat_activity.pid)
|
|
FROM pg_stat_activity
|
|
WHERE pg_stat_activity.datname = 'photowall'
|
|
AND pid <> pg_backend_pid();"
|
|
|
|
echo "dropdb -h $TARGET -U root --if-exists photowall"
|
|
echo "createdb -h $TARGET -U root --encoding=UTF8 photowall"
|
|
|
|
if [ -z "$DRY_RUN" ]
|
|
then
|
|
dropdb -h $TARGET -U root --if-exists photowall
|
|
createdb -h $TARGET -U root --encoding=UTF8 photowall
|
|
fi
|
|
|
|
db_exec 'CREATE EXTENSION IF NOT EXISTS unaccent SCHEMA pg_catalog;' photowall
|
|
}
|
|
|
|
restore()
|
|
{
|
|
provision
|
|
echo "pg_restore -h $TARGET -U root --no-owner --no-acl -j $JOBS -d photowall $DUMP_FILE"
|
|
if [ -z "$DRY_RUN" ]
|
|
then
|
|
pg_restore -h $TARGET -U root --no-owner --no-acl -d photowall $DUMP_FILE
|
|
fi
|
|
}
|
|
|
|
set_grants()
|
|
{
|
|
db_exec 'REVOKE TEMPORARY ON DATABASE photowall FROM public';
|
|
SQL=$(cat <<- 'EOF'
|
|
REVOKE ALL ON SCHEMA public FROM public;
|
|
GRANT USAGE ON SCHEMA public TO photowall;
|
|
GRANT SELECT, UPDATE, INSERT, DELETE ON ALL TABLES IN SCHEMA public TO photowall;
|
|
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO photowall;
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
GRANT SELECT, UPDATE, INSERT, DELETE ON TABLES TO photowall;
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
GRANT USAGE, SELECT ON SEQUENCES TO photowall;
|
|
EOF
|
|
)
|
|
db_exec "$SQL" photowall
|
|
|
|
if [ ! -z $PRODUCTION ]
|
|
then
|
|
for x in $(cat <<-EOF
|
|
v_analytics_products
|
|
v_analytics_inquiries
|
|
v_analytics_discounts
|
|
v_analytics_product_categories
|
|
v_analytics_orders_not_delivered
|
|
v_analytics_orders_rows_not_delivered
|
|
v_analytics_order_rows
|
|
v_analytics_orders2
|
|
v_analytics_contract_customer_discounts
|
|
EOF
|
|
)
|
|
do
|
|
db_exec "GRANT SELECT ON ${x} TO datastudio;" photowall
|
|
done
|
|
|
|
for x in $(cat <<-EOF
|
|
v_funnel_discounts
|
|
v_funnel_order_rows
|
|
v_funnel_orders
|
|
v_funnel_pricelist
|
|
EOF
|
|
)
|
|
do
|
|
db_exec "GRANT SELECT ON ${x} TO funnel;" photowall
|
|
done
|
|
fi
|
|
}
|
|
|
|
set_source()
|
|
{
|
|
SOURCE="$1"
|
|
SOURCE_HASH=$(echo "${SOURCE}${DATABASE}" | md5sum | cut -d' ' -f1)
|
|
DUMP_FILE="/tmp/${DATABASE}-${SOURCE_HASH:0:10}.sql"
|
|
}
|
|
|
|
# Handle arguments
|
|
PARAMS=""
|
|
while (( "$#" )); do
|
|
case "$1" in
|
|
-d|--dry-run)
|
|
DRY_RUN=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
;;
|
|
-j|--jobs)
|
|
if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then
|
|
JOBS="$2"
|
|
shift 2
|
|
else
|
|
throw_err "Argument for ${1} is missing"
|
|
fi
|
|
;;
|
|
-p|--production)
|
|
PRODUCTION=1
|
|
shift 1
|
|
;;
|
|
-*|--*=)
|
|
throw_err "Unsupported flag ${1}"
|
|
;;
|
|
*)
|
|
PARAMS="${PARAMS} ${1}"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# reset positional arguments
|
|
eval set -- "${PARAMS}"
|
|
|
|
[ -z "$2" ] && throw_err "Source server URL is missing" || set_source "$2"
|
|
|
|
case "$1" in
|
|
dump)
|
|
dump
|
|
;;
|
|
sync)
|
|
[ -z $3 ] && throw_err "Target server URL is missing"
|
|
TARGET="$3"
|
|
confirm_sync
|
|
dump
|
|
restore
|
|
set_grants
|
|
;;
|
|
*)
|
|
throw_err "${1} is not a valid command"
|
|
;;
|
|
esac
|
|
|
|
[ -z "$1" ] && throw_err "No command given"
|