Skip to content

Commit 022dbc2

Browse files
Merge pull request #647 from aerospike/stage
Nodejs-Release-6.0.0
2 parents 5d43d80 + c8c6512 commit 022dbc2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+3631
-699
lines changed
Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,108 @@
11
name: 'Run EE Server'
2-
description: 'Run EE server'
2+
description: 'Run EE server. Returns once server is ready. Only tested on Linux and macOS'
3+
# NOTE: do not share this server container with others
4+
# since it's using the default admin / admin credentials
35
inputs:
46
# All inputs in composite actions are strings
57
use-server-rc:
68
required: true
7-
default: false
9+
description: Deploy server release candidate?
10+
default: 'false'
811
server-tag:
912
required: true
13+
description: Specify Docker tag
14+
1015
default: 'latest'
1116
# Github Composite Actions can't access secrets
1217
# so we need to pass them in as inputs
1318
docker-hub-username:
19+
description: Required for using release candidates
1420
required: false
1521
docker-hub-password:
22+
description: Required for using release candidates
1623
required: false
1724

1825
runs:
1926
using: "composite"
2027
steps:
21-
- name: Create config folder to store configs in
22-
run: mkdir configs
28+
- name: Install crudini to manipulate config.conf
29+
# This will only work on the Github hosted runners.
30+
run: pipx install crudini --pip-args "-c ${{ github.workspace }}/.github/workflows/requirements.txt"
31+
working-directory: .github/workflows
2332
shell: bash
2433

25-
- name: Use release server
26-
if: ${{ inputs.use-server-rc == 'false' }}
27-
run: echo "SERVER_IMAGE=aerospike/aerospike-server-enterprise" >> $GITHUB_ENV
34+
- name: Create config.conf
35+
run: cp config.conf.template config.conf
36+
working-directory: .github/workflows
2837
shell: bash
2938

30-
- name: Use release candidate server
31-
if: ${{ inputs.use-server-rc == 'true' }}
32-
run: echo "SERVER_IMAGE=aerospike/aerospike-server-enterprise-rc" >> $GITHUB_ENV
39+
- name: Use enterprise edition instead of community edition in config.conf
40+
run: |
41+
crudini --existing=param --set config.conf enterprise-edition hosts ''
42+
crudini --existing=param --set config.conf enterprise-edition hosts 127.0.0.1:3000
43+
working-directory: .github/workflows
44+
shell: bash
45+
46+
- run: echo SUPERUSER_NAME_AND_PASSWORD="superuser" >> $GITHUB_ENV
47+
shell: bash
48+
49+
- name: Set credentials in config file
50+
run: |
51+
crudini --existing=param --set config.conf enterprise-edition user ${{ env.SUPERUSER_NAME_AND_PASSWORD }}
52+
crudini --existing=param --set config.conf enterprise-edition password ${{ env.SUPERUSER_NAME_AND_PASSWORD }}
53+
working-directory: .github/workflows
3354
shell: bash
3455

3556
- name: Log into Docker Hub to get server RC
3657
if: ${{ inputs.use-server-rc == 'true' }}
3758
run: docker login --username ${{ inputs.docker-hub-username }} --password ${{ inputs.docker-hub-password }}
3859
shell: bash
3960

40-
- name: Get default aerospike.conf from Docker server EE container
41-
run: |
42-
docker run -d --name aerospike -p 3000-3002:3000-3002 $SERVER_IMAGE:${{ inputs.server-tag }}
43-
sleep 5
44-
docker cp aerospike:/etc/aerospike/aerospike.conf ./configs/aerospike.conf
45-
docker container stop aerospike
46-
docker container rm aerospike
61+
- run: echo IMAGE_NAME=aerospike/aerospike-server-enterprise${{ inputs.use-server-rc == 'true' && '-rc' || '' }}:${{ inputs.server-tag }} >> $GITHUB_ENV
62+
shell: bash
63+
64+
- run: echo NEW_IMAGE_NAME=${{ env.IMAGE_NAME }}-security-and-sc >> $GITHUB_ENV
65+
shell: bash
66+
67+
# macOS Github runners and Windows self-hosted runners don't have buildx installed by default
68+
- if: ${{ runner.os == 'Windows' || runner.os == 'macOS' }}
69+
uses: docker/setup-buildx-action@v3
70+
71+
- name: Build and push
72+
uses: docker/build-push-action@v6
73+
with:
74+
# Don't want to use default Git context or else it will clone the whole Python client repo again
75+
context: .github/workflows/docker-build-context
76+
build-args: |
77+
server_image=${{ env.IMAGE_NAME }}
78+
tags: ${{ env.NEW_IMAGE_NAME }}
79+
# setup-buildx-action configures Docker to use the docker-container build driver
80+
# This driver doesn't publish an image locally by default
81+
# so we have to manually enable it
82+
load: true
83+
84+
- run: echo SERVER_CONTAINER_NAME="aerospike" >> $GITHUB_ENV
85+
shell: bash
86+
87+
- run: docker run -d --name ${{ env.SERVER_CONTAINER_NAME }} -e DEFAULT_TTL=2592000 -p 3000:3000 ${{ env.NEW_IMAGE_NAME }}
88+
shell: bash
89+
90+
- uses: ./.github/actions/wait-for-as-server-to-start
91+
with:
92+
container-name: ${{ env.SERVER_CONTAINER_NAME }}
93+
is-strong-consistency-enabled: true
94+
95+
- run: echo ASADM_AUTH_FLAGS="--user=${{ env.SUPERUSER_NAME_AND_PASSWORD }} --password=${{ env.SUPERUSER_NAME_AND_PASSWORD }}" >> $GITHUB_ENV
4796
shell: bash
4897

49-
- name: Enable security features using aerospike.conf
50-
# Security stanza
51-
run: echo -e "security {\n\tenable-quotas true\n}\n" >> ./aerospike.conf
52-
working-directory: ./configs
98+
# All the partitions are assumed to be dead when reusing a roster file
99+
- run: docker exec ${{ env.SERVER_CONTAINER_NAME }} asadm $ASADM_AUTH_FLAGS --enable --execute "manage revive ns test"
53100
shell: bash
54101

55-
- name: Run enterprise edition server
56-
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
102+
# Apply changes
103+
- run: docker exec ${{ env.SERVER_CONTAINER_NAME }} asadm $ASADM_AUTH_FLAGS --enable --execute "manage recluster"
57104
shell: bash
58105

59-
- name: Create user in database for tests
60-
# Use default admin user to create another user for testing
61-
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"
106+
# For debugging
107+
- run: docker logs aerospike
62108
shell: bash
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: 'Wait for Aerospike server to start'
2+
description: Only tested on Linux and macOS
3+
inputs:
4+
container-name:
5+
required: true
6+
is-security-enabled:
7+
required: false
8+
default: 'false'
9+
is-strong-consistency-enabled:
10+
required: false
11+
default: 'false'
12+
13+
runs:
14+
using: "composite"
15+
steps:
16+
- name: 'macOS: install timeout command'
17+
if: ${{ runner.os == 'macOS' }}
18+
run: brew install coreutils
19+
shell: bash
20+
21+
# Composite actions doesn't support step-level timeout-minutes
22+
# Use timeout command and store polling logic in file to make it easier to read
23+
# Call bash shell explicitly since timeout uses "sh" shell by default, for some reason
24+
# 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
25+
# Effectively, this composite action is like calling "sleep" that is optimized to exit early when it detects an ok from the server
26+
- name: Wait for EE server to start
27+
run: timeout 30 bash ./.github/workflows/wait-for-as-server-to-start.bash ${{ inputs.container-name }} ${{ inputs.is-security-enabled }} ${{ inputs.is-strong-consistency-enabled }} || true
28+
shell: bash
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[community-edition]
2+
hosts: 127.0.0.1:3000
3+
4+
[enterprise-edition]
5+
hosts :
6+
user :
7+
password :
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
ARG server_image=aerospike/aerospike-server-enterprise:8.0.0.0-rc1
2+
ARG ROSTER_FILE_NAME=roster.smd
3+
# Temp file for passing node id from one build stage to another
4+
# Docker doesn't support command substitution for setting values for ARG variables, so we have to do this
5+
ARG NODE_ID_FILE_NAME=node_id
6+
7+
FROM $server_image as configure-server
8+
9+
WORKDIR /opt/aerospike/smd
10+
11+
# Enable authentication
12+
13+
ARG AEROSPIKE_CONF_TEMPLATE_PATH=/etc/aerospike/aerospike.template.conf
14+
15+
# Not using asconfig to edit config because we are working with a template file, which may not have valid values yet
16+
RUN echo -e "security {\n\tenable-quotas true\n}\n" >> $AEROSPIKE_CONF_TEMPLATE_PATH
17+
# security.smd was generated manually by
18+
# 1. Starting a new Aerospike EE server using Docker
19+
# 2. Creating the superuser user
20+
# 3. Copying /opt/aerospike/smd/security.smd from the container and committing it to this repo
21+
# This file should always work
22+
# TODO: generate this automatically, somehow.
23+
COPY security.smd .
24+
25+
# Enable strong consistency
26+
RUN sed -i "s/\(namespace.*{\)/\1\n\tstrong-consistency true/" $AEROSPIKE_CONF_TEMPLATE_PATH
27+
RUN sed -i "s/\(namespace.*{\)/\1\n\tstrong-consistency-allow-expunge true/" $AEROSPIKE_CONF_TEMPLATE_PATH
28+
RUN sed -i "s/\(namespace.*{\)/\1\n\tdefault-ttl 2592000/" $AEROSPIKE_CONF_TEMPLATE_PATH
29+
ARG ROSTER_FILE_NAME
30+
COPY $ROSTER_FILE_NAME .
31+
32+
# Fetch node id from roster.smd
33+
34+
# There's no tag for the latest major version to prevent breaking changes in jq
35+
# This is the next best thing
36+
FROM ghcr.io/jqlang/jq:1.7 as get-jq
37+
# jq docker image doesn't have a shell
38+
# We need a shell to fetch and pass the node id to the next build stage
39+
FROM busybox as get-node-id
40+
COPY --from=get-jq /jq /bin/
41+
ARG ROSTER_FILE_NAME
42+
COPY $ROSTER_FILE_NAME .
43+
ARG NODE_ID_FILE_NAME
44+
RUN jq --raw-output '.[1].value' $ROSTER_FILE_NAME > $NODE_ID_FILE_NAME
45+
46+
FROM configure-server as set-node-id
47+
ARG NODE_ID_FILE_NAME
48+
COPY --from=get-node-id $NODE_ID_FILE_NAME .
49+
RUN sed -i "s/\(^service {\)/\1\n\tnode-id $(cat $NODE_ID_FILE_NAME)/" $AEROSPIKE_CONF_TEMPLATE_PATH
50+
RUN rm $NODE_ID_FILE_NAME
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[
2+
[
3+
97107025374203,
4+
1
5+
],
6+
{
7+
"key": "test",
8+
"value": "a1",
9+
"generation": 1,
10+
"timestamp": 465602976982
11+
}
12+
]
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[
2+
[
3+
162276881999406,
4+
14
5+
],
6+
{
7+
"key": "admin|P",
8+
"value": "$2a$10$7EqJtq98hPqEX7fNZaFWoO1mVO/4MLpGzsqojz6E9Gef6iXDjXdDa",
9+
"generation": 1,
10+
"timestamp": 0
11+
},
12+
{
13+
"key": "admin|R|user-admin",
14+
"value": "",
15+
"generation": 1,
16+
"timestamp": 0
17+
},
18+
{
19+
"key": "superuser|P",
20+
"value": "$2a$10$7EqJtq98hPqEX7fNZaFWoOZX0o4mZCBUwvzt/iecIcG4JaDOC41zK",
21+
"generation": 3,
22+
"timestamp": 458774922440
23+
},
24+
{
25+
"key": "superuser|R|read-write-udf",
26+
"value": "",
27+
"generation": 3,
28+
"timestamp": 458774922441
29+
},
30+
{
31+
"key": "superuser|R|sys-admin",
32+
"value": "",
33+
"generation": 3,
34+
"timestamp": 458774922442
35+
},
36+
{
37+
"key": "superuser|R|user-admin",
38+
"value": "",
39+
"generation": 3,
40+
"timestamp": 458774922442
41+
},
42+
{
43+
"key": "superuser|R|data-admin",
44+
"value": null,
45+
"generation": 2,
46+
"timestamp": 458774718056
47+
}
48+
]

.github/workflows/requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
parver==0.5
2+
crudini==0.9.4
3+
delocate==0.10.4
4+
mypy==1.10.0

.github/workflows/tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ jobs:
232232
npm install typescript --save-dev;
233233
npx tsc;
234234
cd ..;
235-
npm run test dist/
235+
npm run test
236236
237237
test-lowest-supported-server:
238238
runs-on: ubuntu-latest
@@ -278,7 +278,7 @@ jobs:
278278
npm install typescript --save-dev;
279279
npx tsc;
280280
cd ..;
281-
npm run test dist/ -- --t 20000
281+
npm run test -- --t 20000
282282
283283
test-ee:
284284
runs-on: ubuntu-latest
@@ -335,7 +335,7 @@ jobs:
335335
npm install typescript --save-dev;
336336
npx tsc;
337337
cd ..;
338-
npm run test dist/admin.js -- --h localhost --U admin --P admin --t 40000
338+
npm run test -- --h localhost --U superuser --P superuser --t 40000
339339
340340
test-valgrind:
341341
runs-on: ubuntu-latest
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
3+
set -x
4+
# Makes sure that if the "docker exec" command fails, it is not ignored
5+
set -o pipefail
6+
7+
container_name=$1
8+
is_security_enabled=$2
9+
is_strong_consistency_enabled=$3
10+
11+
if [[ $is_security_enabled == true ]]; then
12+
# We need to pass credentials to asinfo if server requires it
13+
# TODO: passing in credentials via command line flags since I can't figure out how to use --instance with global astools.conf
14+
user_credentials="--user=admin --password=admin"
15+
fi
16+
17+
while true; do
18+
# An unset variable will have a default empty value
19+
# Intermediate step is to print docker exec command's output in case it fails
20+
# Sometimes, errors only appear in stdout and not stderr, like if asinfo throws an error because of no credentials
21+
# (This is a bug in asinfo since all error messages should be sent to stderr)
22+
# But piping and passing stdin to grep will hide the first command's stdout.
23+
# grep doesn't have a way to print all lines passed as input.
24+
# ack does have an option but it doesn't come installed by default
25+
# shellcheck disable=SC2086 # The flags in user credentials should be separate anyways. Not one string
26+
echo "Checking if we can reach the server via the service port..."
27+
if docker exec "$container_name" asinfo $user_credentials -v status | tee >(cat) | grep -qE "^ok"; then
28+
# Server is ready when asinfo returns ok
29+
echo "Can reach server now."
30+
# docker container inspect "$container_name"
31+
break
32+
fi
33+
34+
echo "Server didn't return ok via the service port. Polling again..."
35+
done
36+
37+
# Although the server may be reachable via the service port, the cluster may not be fully initialized yet.
38+
# If we try to connect too soon (e.g right after "status" returns ok), the client may throw error code -1
39+
while true; do
40+
echo "Waiting for server to stabilize (i.e return a cluster key)..."
41+
# We assume that when an ERROR is returned, the cluster is not stable yet (i.e not fully initialized)
42+
cluster_stable_info_cmd="cluster-stable"
43+
if [[ $is_strong_consistency_enabled == true ]]; then
44+
# The Dockerfile uses a roster from a previously running Aerospike server in a Docker container
45+
# When we reuse this roster, the server assumes all of its partitions are dead because it's running on a new
46+
# storage device.
47+
cluster_stable_info_cmd="$cluster_stable_info_cmd:ignore-migrations=true"
48+
fi
49+
if docker exec "$container_name" asinfo $user_credentials -v $cluster_stable_info_cmd 2>&1 | (! grep -qE "^ERROR"); then
50+
echo "Server is in a stable state."
51+
break
52+
fi
53+
54+
echo "Server did not return a cluster key. Polling again..."
55+
done

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,10 @@ To run all the test cases:
340340

341341
npm test
342342

343+
To run a specific tests, use:
344+
345+
npm test --testfile=filename.js
346+
343347
Note: make sure your server has TTL enabled for the `test` namespace ([Namespace Retention Configuration](https://docs.aerospike.com/server/operations/configure/namespace/retention)) to allow all tests to run correctly.
344348

345349
To run the tests and also report on test coverage:

0 commit comments

Comments
 (0)