name: CI

on: [push, pull_request]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', 'pypy3.10']

    env:
      REALM: test
      USER: oauth_user
      PASSWORD: password
      CLIENT_ID: vertica
      CLIENT_SECRET: P9f8350QQIUhFfK1GF5sMhq4Dm3P6Sbs

    steps:
      - name: Check out repository
        uses: actions/checkout@v4
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - name: Set up a Keycloak docker container
        timeout-minutes: 5
        run: |
          docker network create -d bridge my-network
          docker run -d -p 8080:8080 \
            --name keycloak --network my-network \
            -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \
            quay.io/keycloak/keycloak:23.0.4 start-dev
          docker container ls

      - name: Set up a Vertica server docker container
        timeout-minutes: 15
        run: |
          docker run -d -p 5433:5433 -p 5444:5444 \
            --name vertica_docker --network my-network \
            opentext/vertica-ce:24.2.0-1
          echo "Vertica startup ..."
          until docker exec vertica_docker test -f /data/vertica/VMart/agent_start.out; do \
            echo "..."; \
            sleep 3; \
          done;
          echo "Vertica is up"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "\l"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "select version()"

      - name: Configure Keycloak
        run: |
          echo "Wait for keycloak ready ..."
          bash -c 'while true; do curl -s localhost:8080 &>/dev/null; ret=$?; [[ $ret -eq 0 ]] && break; echo "..."; sleep 3; done'

          docker exec -i keycloak /bin/bash <<EOF
            /opt/keycloak/bin/kcadm.sh config credentials --server http://localhost:8080 --realm master --user admin --password admin
            /opt/keycloak/bin/kcadm.sh create realms -s realm=${REALM} -s enabled=true
            /opt/keycloak/bin/kcadm.sh update realms/${REALM} -s accessTokenLifespan=3600
            /opt/keycloak/bin/kcadm.sh get realms/${REALM}
            /opt/keycloak/bin/kcadm.sh create users -r ${REALM} -s username=${USER} -s enabled=true
            /opt/keycloak/bin/kcadm.sh set-password -r ${REALM} --username ${USER} --new-password ${PASSWORD}
            /opt/keycloak/bin/kcadm.sh get users -r ${REALM}
            /opt/keycloak/bin/kcadm.sh create clients -r ${REALM} -s clientId=${CLIENT_ID} -s enabled=true \
              -s 'redirectUris=["/*"]' -s 'webOrigins=["/*"]' -s secret=${CLIENT_SECRET} -s directAccessGrantsEnabled=true -o
          EOF

          # Retrieving an Access Token
          curl --location --request POST http://`hostname`:8080/realms/${REALM}/protocol/openid-connect/token \
              --header 'Content-Type: application/x-www-form-urlencoded' \
              --data-urlencode "username=${USER}" \
              --data-urlencode "password=${PASSWORD}" \
              --data-urlencode "client_id=${CLIENT_ID}" \
              --data-urlencode "client_secret=${CLIENT_SECRET}" \
              --data-urlencode 'grant_type=password' -o oauth.json
          cat oauth.json | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["access_token"])' > access_token.txt

          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "CREATE AUTHENTICATION v_oauth METHOD 'oauth' HOST '0.0.0.0/0';"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_oauth SET client_id = '${CLIENT_ID}';"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_oauth SET client_secret = '${CLIENT_SECRET}';"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_oauth SET discovery_url = 'http://`hostname`:8080/realms/${REALM}/.well-known/openid-configuration';"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_oauth SET introspect_url = 'http://`hostname`:8080/realms/${REALM}/protocol/openid-connect/token/introspect';"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "SELECT * FROM client_auth WHERE auth_name='v_oauth';"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "CREATE USER ${USER};"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "GRANT AUTHENTICATION v_oauth TO ${USER};"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "GRANT ALL ON SCHEMA PUBLIC TO ${USER};"
          # A dbadmin-specific authentication record (connect remotely) is needed after setting up an OAuth user
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "CREATE AUTHENTICATION v_dbadmin_hash METHOD 'hash' HOST '0.0.0.0/0';"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_dbadmin_hash PRIORITY 10000;"
          docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "GRANT AUTHENTICATION v_dbadmin_hash TO dbadmin;"

      - name: Install dependencies
        run: pip install tox
      - name: Run tests
        run: |
          export VP_TEST_USER=dbadmin
          export VP_TEST_OAUTH_ACCESS_TOKEN=`cat access_token.txt`
          export VP_TEST_OAUTH_USER=${USER}
          tox -e py
