default:
  image: python:3.9-slim
variables:
  OS_AUTH_TYPE: v3applicationcredential
  OS_AUTH_URL: https://hdf-cloud.fz-juelich.de:5000
  OS_IDENTITY_API_VERSION: 3
  OS_REGION_NAME: "HDFCloud"
  OS_INTERFACE: public
  TESTING_IP: 134.94.199.220
  OLD_TEST_NAME: old-airflow-test
  TESTING_NAME: airflow-testing
  TESTING_URL: http://134.94.199.220:7001/home
  AIRFLOW_TESTUSER: "airflow"

# before script copied from gitlab docs
.before_script_template: &ssh_setup
  before_script:
    - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client gcc libxslt-dev libffi-dev libssl-dev build-essential python3-dev -y )'
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh

stages:
  - test
  - deploy
  - test-deployment
  - cleanup

test:
  stage: test
  image: 
    name: apache/airflow:2.1.3
    entrypoint: [""]
  before_script:
    - airflow db init
    - pip install -r requirements.txt
    - pip install nose==1.3.7
    - airflow connections add --conn-uri https://b2share-testing.fz-juelich.de/ default_b2share
  script: 
   - ls 
   - pwd
   - cp dags/* /opt/airflow/dags/
   - airflow dags list 
   - airflow connections list
   - airflow dags test testdag 2021-08-18
   - nosetests

full-deploy-testing:
  stage: deploy
  environment: Testing
  only:
    - web
  script:
    - echo "Starting the full testing deployment of airflows example."
    - pip install python-openstackclient
    - OLD_ID=`openstack server show $TESTING_NAME -f value -c id`
    - openstack server set --name $OLD_TEST_NAME $OLD_ID
    - INSTANCE_ID=`openstack server create -f value -c id --prefix IMAGE_ --flavor m4 --image 149a65b5-aeb8-499f-aaa6-ec966bd28dd6 --user-data scripts/cloudinit.yml --security-group ssh --security-group airflows --security-group www --security-group https $TESTING_NAME`
    - while [ "`openstack server show $INSTANCE_ID -c addresses -f value`" = "{}" ]; do sleep 5; done # wait until an address is available to attach the floating ip
    - openstack server add floating ip $INSTANCE_ID $TESTING_IP
    - echo "Done"

# TODO test light deployment
light-deploy-testing:
  stage: deploy
  # only run when master is updated, unless the pipeline was triggered via the web UI
  only:
    - master
    - mptest
  except:
    - tags
    - web
  <<: *ssh_setup
  environment: Testing
  script:
    - ssh -oStrictHostKeyChecking=accept-new airflow@$TESTING_IP "cd /home/airflow/data-logistics-service && sudo git stash && sudo git pull --all && sudo git checkout -f $CI_COMMIT_TAG && sudo git stash clear"
    - ssh -oStrictHostKeyChecking=accept-new airflow@$TESTING_IP "sudo /home/airflow/data-logistics-service/scripts/deployment.sh /home/airflow /home/airflow/data-logistics-service"

test-testing_dags:
  cache: {}
  stage: test-deployment 
  only:
    - web # and master
  except:
    - tags
  script:
    - apt update && apt -y install curl
    - echo "This is a simple check if the deployment was successful and dags get executed"
    # ensure that the docker containers are up and running before testing the airflow deployment; timeout in 16 to 17 minutes
    - SECONDS=0
    - 'while [ $SECONDS -le 1000 ] ; do if output=$(curl --insecure --max-time 10 -I -H "Accept: application/json" $TESTING_URL) ; then break; else sleep 30; fi ; done'
    - 'curl --insecure -I -H "Accept: application/json" $TESTING_URL'
    - 'curl -X GET -u $AIRFLOW_TESTUSER:$AIRFLOW_TESTUSER_PASS -H "Content-Type: application/json" $TESTING_IP:7001/api/v1/dags'
    - 'curl -X GET -u $AIRFLOW_TESTUSER:$AIRFLOW_TESTUSER_PASS -H "Content-Type: application/json" $TESTING_IP:7001/api/v1/connections'
    - 'curl -X POST -u $AIRFLOW_TESTUSER:$AIRFLOW_TESTUSER_PASS -H "Content-Type: application/json" --data {} $TESTING_IP:7001/api/v1/dags/testdag/dagRuns'

cleanup-successful-full-deployment:
  # check if there is an old prod or test instance, and delete it if present
  stage: cleanup
  when: on_success
  only:
    - web
  script:
    - echo "This is the cleanup for the full-redeployment of the testing or production servers"
    - echo "if this job is reached, all earlier jobs were successful, and any lingering old instances need to be removed"
    - pip install python-openstackclient
    - openstack server delete $OLD_TEST_NAME && echo "Deleted old testing server." || echo "No old testing server found."

cleanup-failed-full-deployment:
  # check if there is an old prod or test instance, assign respective ip to it, re-attach volume, delete new instance, rename old instance
  # if there is none, this is a failed light-deployment, which is handled by another job
  # this does not guarantee a successful rollback, but unless the old instance was faulty, this should work
  stage: cleanup
  when: on_failure
  only:
    - web
  <<: *ssh_setup
  script:
    - echo "This is the cleanup for the full-redeployment of the testing or production servers"
    - echo "if this job is reached, some earlier job had to have failed, this will return to the previous instance (if available)"
    - echo "A successfull cleanup can not be guaranteed, depending on the failure reason"
    - pip install python-openstackclient
    # check which old instance is present. (either old test or old production); store instance id in a var
    - OLD_TEST_ID=`openstack server show $OLD_TEST_NAME -f value -c id` && rollback_test=true || echo "No old testing server found."
    # if applicable: rollback test server
    - if [ "$rollback_test" = true ] ; then 
      REMOVE_ID=`openstack server show $TESTING_NAME -f value -c id`;
      openstack server set --name $TESTING_NAME $OLD_TEST_ID;
      openstack server add floating ip $OLD_TEST_ID $TESTING_IP;
      openstack server delete $REMOVE_ID && echo "Deleted faulty testing server.";
      fi
    # gitlab should automatically alert the devs about this failure