diff --git a/.github/actions/run-ee-server/action.yml b/.github/actions/run-ee-server/action.yml index 79f76a2e2..14417df97 100644 --- a/.github/actions/run-ee-server/action.yml +++ b/.github/actions/run-ee-server/action.yml @@ -1,5 +1,7 @@ name: 'Run EE Server' description: 'Run EE server. Returns once server is ready. Only tested on Linux and macOS' +# NOTE: do not share this server container with others +# since it's using the default admin / admin credentials inputs: # All inputs in composite actions are strings use-server-rc: @@ -43,61 +45,35 @@ runs: run: mkdir configs shell: bash - - name: Use release server - if: ${{ inputs.use-server-rc == 'false' }} - run: echo "SERVER_IMAGE=aerospike/aerospike-server-enterprise" >> $GITHUB_ENV - shell: bash - - - name: Use release candidate server - if: ${{ inputs.use-server-rc == 'true' }} - run: echo "SERVER_IMAGE=aerospike/aerospike-server-enterprise-rc" >> $GITHUB_ENV - shell: bash - - name: Log into Docker Hub to get server RC if: ${{ inputs.use-server-rc == 'true' }} run: docker login --username ${{ inputs.docker-hub-username }} --password ${{ inputs.docker-hub-password }} shell: bash - - run: docker run -d --name aerospike -p 3000:3000 $SERVER_IMAGE:${{ inputs.server-tag }} + - run: echo IMAGE_NAME=aerospike/aerospike-server-enterprise${{ inputs.use-server-rc == 'true' && '-rc' || '' }}:${{ inputs.server-tag }} >> $GITHUB_ENV shell: bash - - uses: ./.github/actions/wait-for-as-server-to-start - id: wait-for-server1 - with: - container-name: aerospike - is-security-enabled: false - - - name: Get default aerospike.conf from Docker server EE container - run: | - docker cp aerospike:/etc/aerospike/aerospike.conf ./configs/aerospike.conf - docker container stop aerospike - docker container rm aerospike + - run: echo SECURITY_IMAGE_NAME=${{ env.IMAGE_NAME }}-security >> $GITHUB_ENV shell: bash - - name: Enable security features using aerospike.conf - # Security stanza - run: echo -e "security {\n\tenable-quotas true\n}\n" >> ./aerospike.conf - working-directory: ./configs + # macOS Github runners don't have Docker by default + - if: ${{ runner.os == 'macOS' }} + run: brew install docker-buildx shell: bash - - name: Run enterprise edition server - run: docker run -tid -v $(pwd)/configs:/opt/aerospike/etc -p 3000:3000 --name aerospike $SERVER_IMAGE:${{ inputs.server-tag }} asd --config-file /opt/aerospike/etc/aerospike.conf + - name: Build and push + uses: docker/build-push-action@v6 + with: + # Don't want to use default Git context or else it will clone the whole Python client repo again + context: .github/workflows + build-args: | + image=${{ env.IMAGE_NAME }} + tags: ${{ env.SECURITY_IMAGE_NAME }} + + - run: docker run -d --name aerospike -p 3000:3000 ${{ env.SECURITY_IMAGE_NAME }} shell: bash - uses: ./.github/actions/wait-for-as-server-to-start - id: wait-for-server2 with: container-name: aerospike is-security-enabled: true - - # Enabling debug logging for workflow runs doesn't show container logs - # So we need this step for now - - if: ${{ !cancelled() && (steps.wait-for-server1.outcome == 'failure' || steps.wait-for-server2.outcome == 'failure') }} - name: Print logs to help debug why the server failed to start up - run: docker container logs aerospike - shell: bash - - - name: Create user in database for tests - # Use default admin user to create another user for testing - run: docker exec aerospike asadm --user admin --password admin --enable -e "manage acl create user superuser password superuser roles read-write-udf sys-admin user-admin data-admin" - shell: bash diff --git a/.github/actions/wait-for-as-server-to-start/action.yml b/.github/actions/wait-for-as-server-to-start/action.yml index 119fbcc3a..26841102b 100644 --- a/.github/actions/wait-for-as-server-to-start/action.yml +++ b/.github/actions/wait-for-as-server-to-start/action.yml @@ -21,5 +21,5 @@ runs: # Also, we don't want to fail if we timeout in case the server *did* finish starting up but the script couldn't detect it due to a bug # Effectively, this composite action is like calling "sleep" that is optimized to exit early when it detects an ok from the server - name: Wait for EE server to start - run: timeout 5 bash ./.github/workflows/wait-for-as-server-to-start.bash ${{ inputs.container-name }} ${{ inputs.is-security-enabled }} || true + run: timeout 30 bash ./.github/workflows/wait-for-as-server-to-start.bash ${{ inputs.container-name }} ${{ inputs.is-security-enabled }} || true shell: bash diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile new file mode 100644 index 000000000..e15848240 --- /dev/null +++ b/.github/workflows/Dockerfile @@ -0,0 +1,10 @@ +ARG image +FROM $image +RUN echo -e "security {\n\tenable-quotas true\n}\n" >> /etc/aerospike/aerospike.template.conf +# security.smd was generated manually by +# 1. Starting a new Aerospike EE server using Docker +# 2. Creating the superuser user +# 3. Copying /opt/aerospike/smd/security.smd from the container and committing it to this repo +# This file should always work +# TODO: generate this automatically, somehow +COPY security.smd /opt/aerospike/smd/ diff --git a/.github/workflows/security.smd b/.github/workflows/security.smd new file mode 100644 index 000000000..9c530d514 --- /dev/null +++ b/.github/workflows/security.smd @@ -0,0 +1,48 @@ +[ + [ + 162276881999406, + 14 + ], + { + "key": "admin|P", + "value": "$2a$10$7EqJtq98hPqEX7fNZaFWoO1mVO/4MLpGzsqojz6E9Gef6iXDjXdDa", + "generation": 1, + "timestamp": 0 + }, + { + "key": "admin|R|user-admin", + "value": "", + "generation": 1, + "timestamp": 0 + }, + { + "key": "superuser|P", + "value": "$2a$10$7EqJtq98hPqEX7fNZaFWoOZX0o4mZCBUwvzt/iecIcG4JaDOC41zK", + "generation": 3, + "timestamp": 458774922440 + }, + { + "key": "superuser|R|read-write-udf", + "value": "", + "generation": 3, + "timestamp": 458774922441 + }, + { + "key": "superuser|R|sys-admin", + "value": "", + "generation": 3, + "timestamp": 458774922442 + }, + { + "key": "superuser|R|user-admin", + "value": "", + "generation": 3, + "timestamp": 458774922442 + }, + { + "key": "superuser|R|data-admin", + "value": null, + "generation": 2, + "timestamp": 458774718056 + } +] diff --git a/.github/workflows/wait-for-as-server-to-start.bash b/.github/workflows/wait-for-as-server-to-start.bash index 4f20ba4f7..c43e17da5 100755 --- a/.github/workflows/wait-for-as-server-to-start.bash +++ b/.github/workflows/wait-for-as-server-to-start.bash @@ -7,13 +7,13 @@ set -o pipefail container_name=$1 is_security_enabled=$2 -while true; do - if [[ $is_security_enabled == true ]]; then - # We need to pass credentials to asinfo if server requires it - # TODO: passing in hardcoded credentials since I can't figure out how to use --instance with global astools.conf - user_credentials="--user=admin --password=admin" - fi +if [[ $is_security_enabled == true ]]; then + # We need to pass credentials to asinfo if server requires it + # TODO: passing in credentials via command line flags since I can't figure out how to use --instance with global astools.conf + user_credentials="--user=admin --password=admin" +fi +while true; do # An unset variable will have a default empty value # Intermediate step is to print docker exec command's output in case it fails # Sometimes, errors only appear in stdout and not stderr, like if asinfo throws an error because of no credentials @@ -22,8 +22,26 @@ while true; do # grep doesn't have a way to print all lines passed as input. # ack does have an option but it doesn't come installed by default # shellcheck disable=SC2086 # The flags in user credentials should be separate anyways. Not one string + echo "Checking if we can reach the server via the service port..." if docker exec "$container_name" asinfo $user_credentials -v status | tee >(cat) | grep -qE "^ok"; then # Server is ready when asinfo returns ok + echo "Can reach server now." + # docker container inspect "$container_name" + break + fi + + echo "Server didn't return ok via the service port. Polling again..." +done + +# Although the server may be reachable via the service port, the cluster may not be fully initialized yet. +# If we try to connect too soon (e.g right after "status" returns ok), the client may throw error code -1 +while true; do + echo "Waiting for server to stabilize (i.e return a cluster key)..." + # We assume that when an ERROR is returned, the cluster is not stable yet (i.e not fully initialized) + if docker exec "$container_name" asinfo $user_credentials -v cluster-stable 2>&1 | (! grep -qE "^ERROR"); then + echo "Server is in a stable state." break fi + + echo "Server did not return a cluster key. Polling again..." done