#!/bin/bash

# Place this file in /home/satsense/installers/ and make it executable
# Then run 
#           ./ext-api.bash $SERVICE $PORT1 $INSTALL_PATH $DOMAIN
# e.g.      ./ext-api.bash staging-ext-api 5020 /var/www/staging/ext-api staging.satsense.com


# NOTE: $PORT2 will be automatically generated by adding 1 to the value provided for $PORT1

SERVICE=$1
PORT1=$2
PORT2=$(($PORT1+1))
INSTALL_PATH=$3
DOMAIN=$4
TIMESTAMP=$(/bin/date +"%Y%m%d_%H%M%S")


if [ ! -z "$4" ]; then
  echo "Service names:   $SERVICE-blue, $SERVICE-green"
  echo "Port numbers:    $PORT1, $PORT2"
  echo "Install paths:   $INSTALL_PATH-blue, $INSTALL_PATH-green"
  echo "Domain:          $DOMAIN"
  echo "Download:        /home/flask/ext-api/$TIMESTAMP"
else
  echo "Must provide 3 params:    Service name    |     Port number   |    Path   |       Domain"
  echo "e.g.  ./ext-api.bash       staging-ext-api         5020     /var/www/staging/ext-api    staging.api.satsense.com"
  exit
fi

printf "\n\nTo revert everything this script is about to do, run the following commands:\n\n"

echo "sudo rm /etc/systemd/system/$SERVICE-blue.service"
echo "sudo rm /etc/systemd/system/$SERVICE-green.service"
echo "sudo rm /etc/systemd/system/$SERVICE-blue-celery.service"
echo "sudo rm /etc/systemd/system/$SERVICE-green-celery.service"
echo "sudo rm /etc/apache2/sites-available/$SERVICE.conf"
echo "sudo rm /etc/apache2/sites-enabled/$SERVICE.conf"
echo "sudo rm -rf $INSTALL_PATH-*"
echo "sudo systemctl daemon-reload"
echo "sudo service apache2 reload"
echo ""

read -r -p "Type Y to continue, or anything else to exit: " input
if [ $input != 'Y' ]; then
  echo "Exiting"
  exit
fi

# Download artifacts
sudo -i -u flask /home/flask/releases/ext-api/download_artifacts.bash master $TIMESTAMP


INDEX=0
for colour in blue green
do
  install_path="${INSTALL_PATH}-${colour}"
  download_path="/home/flask/releases/ext-api/${TIMESTAMP}/dist"
  pip="${install_path}/virtual_environments/venv/bin/pip"
  port=$(($PORT1+$INDEX))

  # Create directories
  printf "\n\nInstalling to $install_path\n\n"
  sudo mkdir -p $install_path
  cd $install_path

  sudo mkdir log/
  sudo chown flask:www-data log/

  sudo mkdir log/flask
  sudo chown flask:flask log/flask/

  sudo mkdir log/gunicorn
  sudo chown flask:flask log/gunicorn/

  sudo mkdir app_home/
  sudo chown flask:flask app_home/

  sudo mkdir virtual_environments/
  sudo chown flask:flask virtual_environments/

  sudo mkdir celery/
  sudo chown flask:flask celery/

  # Create virtual environment
  printf "\n\nWill create and use pip instance in $pip\n\n"
  sudo -i -u flask /usr/bin/python3.7 -m venv $install_path/virtual_environments/venv

  # Install
  printf "\n\nInstalling using download $download_path\n\n"
  sudo -i -u flask cp $download_path/satapi/app.py $install_path/app_home
  sudo -i -u flask cp $download_path/satapi/celery_app.py $install_path/app_home

  # Create config.ini if blue, symlink to the blue one if green
  if [ "$colour" = "green"  ]; then
    sudo -i -u flask ln -s $INSTALL_PATH-blue/app_home/config.ini $INSTALL_PATH-green/app_home/
    printf "\n\nsymlinked config.ini green to config.ini blue.\n\n"
  else
    sudo -i -u flask cp $download_path/satapi/config.ini $install_path/app_home
    printf "\n\nNow edit $install_path/app_home/config.ini with the necessary config.\n\n"
  fi

  sudo -i -u flask $pip install "$(sudo -i -u flask cat $download_path/satapi/requirements/production.txt | grep numpy)"
  sudo -i -u flask $pip install GDAL==$(gdal-config --version | awk -F'[.]' '{print $1"."$2}') --global-option=build_ext --global-option="-I/usr/include/gdal"
  sudo -i -u flask $pip install -r $download_path/satapi/requirements/production.txt

  printf "\n\nInstalling SatSense Domain packages\n\n"
  sudo mkdir $install_path/tmp
  sudo cp -r $download_path/satdom $install_path/tmp/
  sudo -i -u flask $pip install $install_path/tmp/satdom/satdom*.whl

  printf "\n\nInstalling API packages\n\n"
  sudo cp -r $download_path/satapi $install_path/tmp/
  sudo -i -u flask $pip install $install_path/tmp/satapi/satapi*.whl

  sudo rm -rf $install_path/tmp

  sudo -i -u flask $pip install gunicorn



  # Services
  SERVICE_NAME="${SERVICE}-${colour}"
  printf "\n\nCreating $SERVICE_NAME service\n\n"
  sudo touch /etc/systemd/system/$SERVICE_NAME.service
  sudo chmod 664 /etc/systemd/system/$SERVICE_NAME.service

  sudo tee -a /etc/systemd/system/$SERVICE_NAME.service > /dev/null <<EOT
[Unit]
Description = $SERVICE_NAME
After = network.target

[Service]
User=flask
WorkingDirectory=$install_path/app_home
ExecStart=/bin/sh -c '$install_path/virtual_environments/venv/bin/gunicorn -c $install_path/app_home/gunicorn_config.py app:app'
Restart=always

[Install]
WantedBy = multi-user.target
EOT

  CELERYD_NODES="$SERVICE_NAME-w$port"
  CELERY_BIN="$install_path/virtual_environments/venv/bin/celery"
  CELERY_APP="celery_app"
  CELERYD_OPTS="--time-limit=300 --concurrency=1"
  CELERYD_PID_FILE="$install_path/celery/%n.pid"
  CELERYD_LOG_FILE="$install_path/celery/%n%I.log"
  CELERYD_LOG_LEVEL="INFO"

  sudo touch /etc/systemd/system/$SERVICE_NAME-celery.service
  sudo chmod 664 /etc/systemd/system/$SERVICE_NAME-celery.service
  sudo tee -a /etc/systemd/system/$SERVICE_NAME-celery.service > /dev/null <<EOT
[Unit]
Description=$SERVICE_NAME-celery
After=network.target

[Service]
Type=forking
User=flask
Group=flask
WorkingDirectory=$install_path/app_home
ExecStart=/bin/sh -c '${CELERY_BIN} -A $CELERY_APP multi start $CELERYD_NODES  --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel="${CELERYD_LOG_LEVEL}" $CELERYD_OPTS'
ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait $CELERYD_NODES --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel="${CELERYD_LOG_LEVEL}"'
ExecReload=/bin/sh -c '${CELERY_BIN} -A $CELERY_APP multi restart $CELERYD_NODES --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel="${CELERYD_LOG_LEVEL}" $CELERYD_OPTS'
Restart=always

[Install]
WantedBy=multi-user.target
EOT

  sudo tee -a $install_path/app_home/gunicorn_config.py > /dev/null <<EOT
bind = "localhost:$(($PORT1+$INDEX))"

workers = 4

accesslog = "$install_path/log/gunicorn/accesslog"
errorlog = "$install_path/log/gunicorn/errorlog"
loglevel = "info"
EOT

  sudo systemctl daemon-reload

  sudo systemctl start $SERVICE_NAME-celery
  sudo systemctl stop $SERVICE_NAME-celery
  sudo systemctl enable $SERVICE_NAME-celery

  sudo systemctl start $SERVICE_NAME
  sudo systemctl stop $SERVICE_NAME
  sudo systemctl enable $SERVICE_NAME

  sudo systemctl start $SERVICE_NAME

  INDEX=$(expr $INDEX + 1)
done


# Apache
printf "\n\nCreating Apache VirtualHost at /etc/apache2/sites-available/$SERVICE.conf\n"
echo "Application error logs will be in their respective blue/green /log directory"
echo "Apache error logs will be combined into $INSTALL_PATH-blue/log"
sudo tee -a /etc/apache2/sites-available/$SERVICE.conf > /dev/null <<EOT
<VirtualHost *:80>

ServerName $DOMAIN
ServerAlias $DOMAIN
DocumentRoot $INSTALL_PATH-blue/public

# rewrite to https
RewriteEngine on
RewriteCond %{SERVER_NAME} =$DOMAIN
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

</VirtualHost>

<VirtualHost *:443>
ServerName $DOMAIN
ServerAlias $DOMAIN
DocumentRoot $INSTALL_PATH-blue/public

<Proxy balancer://ext-api>
    BalancerMember http://localhost:$PORT1
    BalancerMember http://localhost:$PORT2
</Proxy>

# flask proxy
ProxyPreserveHost On
ProxyPass / balancer://ext-api/
ProxyPassReverse / balancer://ext-api/

# logs
ErrorLog $INSTALL_PATH-blue/log/error.log
CustomLog $INSTALL_PATH-blue/log/requests.log combined

# headers:
Header always set Strict-Transport-Security "max-age=300; includeSubdomains"
Header always set X-Frame-Options "deny"
Header always set X-Xss-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "no-referrer"
Header always edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=Strict

# Error Documents
ErrorDocument 503 /error/503.html
</VirtualHost>
EOT

sudo ln -s /etc/apache2/sites-available/$SERVICE.conf /etc/apache2/sites-enabled/$SERVICE.conf

sudo service apache2 reload


# Certbot
sudo certbot --apache

echo "Done."