Skip to content

Commit 50d8825

Browse files
authored
Merge pull request #536 from aerospike/CLIENT-3852-tests-against-multi-node-cluster
CLIENT-3852 tests against multi node cluster
2 parents ce959a4 + 954c8ba commit 50d8825

File tree

10 files changed

+308
-50
lines changed

10 files changed

+308
-50
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: "Deploy Aerospike Cluster using Aerolab"
2+
description: "Creates an Aerospike cluster using Aerolab on the current runner"
3+
4+
inputs:
5+
aerospike_version:
6+
description: "Aerospike version for cluster creation"
7+
required: false
8+
default: "8.1.0.1c"
9+
nodes:
10+
description: "Number of cluster nodes"
11+
required: false
12+
default: "3"
13+
cluster_name:
14+
description: "Cluster name"
15+
required: false
16+
default: "ce"
17+
aerolab_version:
18+
# https://github.com/aerospike/aerolab/releases/
19+
description: "Aerolab version to run."
20+
required: false
21+
default: "7.9.0"
22+
23+
runs:
24+
using: composite
25+
steps:
26+
- name: Install dependencies
27+
shell: bash
28+
run: |
29+
sudo apt-get update
30+
sudo apt-get install -y curl
31+
32+
- name: Download Aerolab .deb
33+
shell: bash
34+
run: |
35+
echo "Downloading Aerolab ${{ inputs.aerolab_version }} (amd64)"
36+
curl -L -o aerolab.deb https://github.com/aerospike/aerolab/releases/download/${{ inputs.aerolab_version }}/aerolab-linux-amd64-${{ inputs.aerolab_version }}.deb
37+
38+
- name: Install Aerolab
39+
shell: bash
40+
run: |
41+
sudo dpkg -i aerolab.deb
42+
sudo apt-get install -f -y
43+
44+
- name: Prepare Aerolab home
45+
shell: bash
46+
run: |
47+
mkdir -p /tmp/aerolab-home
48+
echo "AEROLAB_HOME=/tmp/aerolab-home" >> $GITHUB_ENV
49+
50+
- name: Configure Aerolab backend
51+
shell: bash
52+
run: |
53+
aerolab config backend -t docker
54+
55+
- name: Create Aerospike cluster
56+
shell: bash
57+
run: |
58+
aerolab cluster create \
59+
-v "${{ inputs.aerospike_version }}" \
60+
-c "${{ inputs.nodes }}" \
61+
-n "${{ inputs.cluster_name }}"
62+
63+
- name: Validate cluster list
64+
shell: bash
65+
run: |
66+
echo "Listing clusters..."
67+
aerolab cluster list | tee cluster-list.txt
68+
69+
- name: Show cluster list output as job summary
70+
shell: bash
71+
run: |
72+
echo "## Aerolab Cluster Created" >> $GITHUB_STEP_SUMMARY
73+
echo "" >> $GITHUB_STEP_SUMMARY
74+
echo '````' >> $GITHUB_STEP_SUMMARY
75+
cat cluster-list.txt >> $GITHUB_STEP_SUMMARY
76+
echo '````' >> $GITHUB_STEP_SUMMARY

.github/actions/make-matrix/action.yaml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,12 @@ runs:
3737
echo "Validating JSON..."
3838
echo "${JSON}" | jq . >/dev/null
3939
40-
MATRIX="$(echo "${JSON}" | jq -c --arg go "${GO_VERSION}" '[to_entries[] | { server: .key, go: $go } + .value]')"
40+
MATRIX="$(echo "${JSON}" | jq -c --arg go "${GO_VERSION}" '[to_entries[] | {server: .key, version: .value.version, "go-version": $go}]')"
41+
42+
echo "matrix<<EOF" >> "$GITHUB_OUTPUT"
43+
echo "${MATRIX}" >> "$GITHUB_OUTPUT"
44+
echo "EOF" >> "$GITHUB_OUTPUT"
4145
42-
{
43-
echo "matrix<<__JSON__"
44-
echo "${MATRIX}"
45-
echo "__JSON__"
46-
} >> "$GITHUB_OUTPUT"
4746
4847
outputs:
4948
matrix:
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: Build and test against multi-node cluster
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
aerospike_version:
7+
description: "Aerolab/Aerospike version"
8+
required: false
9+
default: "8.1.0.1c"
10+
nodes:
11+
description: "Number of cluster nodes"
12+
required: false
13+
default: "3"
14+
cluster_name:
15+
description: "Cluster name"
16+
required: false
17+
default: "ce"
18+
runner_version:
19+
description: "Ubuntu runner version"
20+
required: false
21+
default: "ubuntu-24.04" # https://github.com/actions/runner-images/blob/main/README.md
22+
schedule:
23+
- cron: "0 2 * * *" # Nightly at 02:00 UTC
24+
25+
env:
26+
# defaults to use against workflow triggered through cron
27+
AEROSPIKE_VERSION: 8.1.0.1c
28+
NODES: 3
29+
CLUSTER_NAME: ce
30+
RUNNER_VERSION: ubuntu-24.04
31+
32+
jobs:
33+
make-matrix:
34+
runs-on: ${{ github.event_name == 'workflow_dispatch' && inputs.runner_version || 'ubuntu-24.04' }}
35+
outputs:
36+
input-matrix: ${{ steps.create-server-matrix.outputs.matrix }}
37+
go-version: ${{ steps.get-go-version.outputs.go-version }}
38+
steps:
39+
- uses: actions/checkout@v4
40+
41+
- name: Get Go version
42+
id: get-go-version
43+
run: |
44+
echo "go-version=$(grep '^go [0-9]' go.mod | awk '{print $2}')" >> $GITHUB_OUTPUT
45+
46+
- id: create-server-matrix
47+
uses: ./.github/actions/make-matrix
48+
with:
49+
default_json: |
50+
{
51+
"stable": { "version": "${{ github.event_name == 'workflow_dispatch' && inputs.aerospike_version || env.AEROSPIKE_VERSION }}" }
52+
}
53+
go_version: ${{ steps.get-go-version.outputs.go-version }}
54+
55+
- name: debug - print input variables
56+
run: |
57+
echo "Aerospike version: ${{ github.event_name == 'workflow_dispatch' && inputs.aerospike_version || env.AEROSPIKE_VERSION }}"
58+
echo "Nodes: ${{ github.event_name == 'workflow_dispatch' && inputs.nodes || env.NODES }}"
59+
echo "Cluster name: ${{ github.event_name == 'workflow_dispatch' && inputs.cluster_name || env.CLUSTER_NAME }}"
60+
echo "Go version: ${{ steps.get-go-version.outputs.go-version }}"
61+
echo 'Matrix output:'
62+
echo '${{ steps.create-server-matrix.outputs.matrix }}' | jq .
63+
64+
build:
65+
timeout-minutes: 30
66+
needs: make-matrix
67+
runs-on: ${{ github.event_name == 'workflow_dispatch' && inputs.runner_version || 'ubuntu-24.04' }}
68+
strategy:
69+
matrix:
70+
include: ${{ fromJson(needs.make-matrix.outputs.input-matrix) }}
71+
steps:
72+
- uses: actions/checkout@v4
73+
74+
- name: Deploy Aerolab Cluster
75+
uses: ./.github/actions/deploy-aerolab
76+
with:
77+
aerospike_version: ${{ github.event_name == 'workflow_dispatch' && inputs.aerospike_version || env.AEROSPIKE_VERSION }}
78+
nodes: ${{ github.event_name == 'workflow_dispatch' && inputs.nodes || env.NODES }}
79+
cluster_name: ${{ github.event_name == 'workflow_dispatch' && inputs.cluster_name || env.CLUSTER_NAME }}
80+
81+
- name: "Setup Go ${{ needs.make-matrix.outputs.go-version }}"
82+
uses: actions/setup-go@v4
83+
with:
84+
go-version: "${{ needs.make-matrix.outputs.go-version }}"
85+
cache: true
86+
- name: Fetch dependencies
87+
env:
88+
GODEBUG: fips140=on
89+
run: |
90+
# Install all dependencies
91+
go mod download
92+
93+
# Install ginkgo CLI and gocovmerge for testing
94+
go install github.com/onsi/ginkgo/v2/[email protected]
95+
go mod download github.com/wadey/gocovmerge
96+
97+
# Vendor the dependencies
98+
go mod vendor
99+
100+
- name: Display Go version
101+
run: |
102+
echo "Go version: ${{ needs.make-matrix.outputs.go-version }}"
103+
- name: Run the tests
104+
env: {GOPROXY: off, GOSUMDB: off, GOFLAGS: -mod=vendor}
105+
run: go run -mod=vendor github.com/onsi/ginkgo/v2/ginkgo -output-dir=./ -coverprofile=cover_native.out -covermode=atomic -coverpkg=./... -race -keep-going -succinct -randomize-suites -skip="HyperLogLog" -- -hosts=127.0.0.1:3100,127.0.0.1:3101,127.0.0.1:3102 -use-services-alternate=true
106+
- name: Combine Cover Profiles
107+
env: {GOPROXY: off, GOSUMDB: off, GOFLAGS: -mod=vendor}
108+
run: go run -mod=vendor github.com/wadey/gocovmerge cover_*.out > cover_all.out
109+
- name: Check Code Coverage
110+
uses: vladopajic/go-test-coverage@v2
111+
with:
112+
# Configure action using config file (option 1)
113+
config: ./.testcoverage.yml

.github/workflows/build.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ jobs:
3333

3434
- name: debug - print input variables
3535
run: |
36-
echo ${{ steps.get-go-version.outputs.go-version }}
37-
echo ${{ steps.create-server-matrix.outputs.input-matrix }}
36+
echo "Go version: ${{ steps.get-go-version.outputs.go-version }}"
37+
echo 'Matrix output:'
38+
echo '${{ steps.create-server-matrix.outputs.matrix }}' | jq .
39+
3840
build:
3941
timeout-minutes: 30
4042
needs: make-matrix
@@ -100,7 +102,7 @@ jobs:
100102
run: go run -mod=vendor github.com/onsi/ginkgo/v2/ginkgo build -tags="app_engine" .
101103
- name: Run the tests
102104
env: {GOPROXY: off, GOSUMDB: off, GOFLAGS: -mod=vendor}
103-
run: go run -mod=vendor github.com/onsi/ginkgo/v2/ginkgo -coverprofile=./cover_native.out -covermode=atomic -coverpkg=./... -race -keep-going -succinct -randomize-suites -skip="HyperLogLog"
105+
run: go run -mod=vendor github.com/onsi/ginkgo/v2/ginkgo -output-dir=./ -coverprofile=cover_native.out -covermode=atomic -coverpkg=./... -race -keep-going -succinct -randomize-suites -skip="HyperLogLog"
104106
- name: Combine Cover Profiles
105107
env: {GOPROXY: off, GOSUMDB: off, GOFLAGS: -mod=vendor}
106108
run: go run -mod=vendor github.com/wadey/gocovmerge cover_*.out > cover_all.out

aerospike_suite_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ func initTestVars() {
115115
log.Fatal(err.Error())
116116
}
117117

118+
printConnectedNodes(client)
119+
118120
defaultBatchPolicy := as.NewBatchPolicy()
119121
defaultBatchPolicy.TotalTimeout = 15 * time.Second
120122
defaultBatchPolicy.SocketTimeout = 5 * time.Second
@@ -154,6 +156,13 @@ func initTestVars() {
154156
client.EnableMetrics(nil)
155157
}
156158

159+
func printConnectedNodes(client *as.Client) {
160+
for _, node := range client.GetNodes() {
161+
h := node.GetHost()
162+
fmt.Printf("Node: %s, Host: %s, Port: %d\n", node.GetName(), h.Name, h.Port)
163+
}
164+
}
165+
157166
func TestMain(m *testing.M) {
158167
rand.Seed(time.Now().UnixNano())
159168
flag.Parse()

client_test.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,8 @@ var _ = gg.Describe("Aerospike", func() {
108108

109109
gg.Describe("Client Management", func() {
110110

111-
dbHost := as.NewHost(*host, *port)
112-
dbHost.TLSName = *nodeTLSName
113-
114111
gg.It("must open and close the client without a problem", func() {
115-
client, err := as.NewClientWithPolicyAndHost(clientPolicy, dbHost)
112+
client, err := as.NewClientWithPolicyAndHost(clientPolicy, dbHosts...)
116113
gm.Expect(err).ToNot(gm.HaveOccurred())
117114
gm.Expect(client.IsConnected()).To(gm.BeTrue())
118115

@@ -150,7 +147,7 @@ var _ = gg.Describe("Aerospike", func() {
150147
cpolicy := *clientPolicy
151148
cpolicy.ClusterName = "haha"
152149
cpolicy.Timeout = 10 * time.Second
153-
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHost)
150+
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHosts...)
154151
gm.Expect(err).To(gm.HaveOccurred())
155152
gm.Expect(err.Matches(ast.CLUSTER_NAME_MISMATCH_ERROR)).To(gm.BeTrue())
156153
gm.Expect(nclient).To(gm.BeNil())
@@ -161,7 +158,7 @@ var _ = gg.Describe("Aerospike", func() {
161158
cpolicy.ClusterName = "haha"
162159
cpolicy.Timeout = 10 * time.Second
163160
cpolicy.FailIfNotConnected = false
164-
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHost)
161+
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHosts...)
165162
gm.Expect(err).To(gm.HaveOccurred())
166163
gm.Expect(err.Matches(ast.CLUSTER_NAME_MISMATCH_ERROR)).To(gm.BeTrue())
167164
gm.Expect(nclient).NotTo(gm.BeNil())
@@ -174,7 +171,7 @@ var _ = gg.Describe("Aerospike", func() {
174171
cpolicy := *clientPolicy
175172
cpolicy.ClusterName = actualClusterName
176173
cpolicy.Timeout = 10 * time.Second
177-
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHost)
174+
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHosts...)
178175
gm.Expect(err).NotTo(gm.HaveOccurred())
179176
gm.Expect(len(nclient.GetNodes())).To(gm.Equal(nodeCount))
180177
})
@@ -191,7 +188,7 @@ var _ = gg.Describe("Aerospike", func() {
191188
cpolicy.AuthMode = as.AuthModeExternal
192189
cpolicy.User = "badwan"
193190
cpolicy.Password = "blastoff"
194-
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHost)
191+
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHosts...)
195192
gm.Expect(err).NotTo(gm.HaveOccurred())
196193
gm.Expect(len(nclient.GetNodes())).To(gm.Equal(nodeCount))
197194
})
@@ -202,7 +199,7 @@ var _ = gg.Describe("Aerospike", func() {
202199
cpolicy := *clientPolicy
203200
cpolicy.User = *user
204201
cpolicy.Password = *password
205-
c, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHost)
202+
c, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHosts...)
206203
gm.Expect(err).NotTo(gm.HaveOccurred())
207204

208205
info := info(c, "rack-ids")
@@ -215,7 +212,7 @@ var _ = gg.Describe("Aerospike", func() {
215212
cpolicy.RackAware = true
216213

217214
for rid := 1; rid <= 20; rid++ {
218-
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHost)
215+
nclient, err := as.NewClientWithPolicyAndHost(&cpolicy, dbHosts...)
219216
gm.Expect(err).NotTo(gm.HaveOccurred())
220217

221218
wpolicy := as.NewWritePolicy(0, 0)

connection_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ var _ = gg.Describe("Connection Test", func() {
4242
gm.Expect(conn).ToNot(gm.BeNil())
4343
})
4444

45-
gg.It("Dealines should be calculated correctly", func() {
45+
gg.It("Deadlines should be calculated correctly", func() {
4646
deadline := func(timeout time.Duration) (res time.Time) {
4747
if timeout > 0 {
4848
res = time.Now().Add(timeout)
@@ -67,9 +67,9 @@ var _ = gg.Describe("Connection Test", func() {
6767

6868
gg.By(fmt.Sprintf("expTotalDeadline: %v, expSocketDeadline: %v, expSocketTimeout: %v", matrix.expTotalDeadline, matrix.expSocketDeadline, matrix.expSocketTimeout))
6969

70-
gm.Expect(expTotalDeadline).To(gm.BeTemporally("~", matrix.expTotalDeadline, time.Millisecond))
71-
gm.Expect(expSocketDeadline).To(gm.BeTemporally("~", matrix.expSocketDeadline, time.Millisecond))
72-
gm.Expect(expSocketTimeout).To(gm.BeNumerically("~", matrix.expSocketTimeout, time.Millisecond))
70+
gm.Expect(expTotalDeadline).To(gm.BeTemporally("~", matrix.expTotalDeadline, 2*time.Millisecond))
71+
gm.Expect(expSocketDeadline).To(gm.BeTemporally("~", matrix.expSocketDeadline, 2*time.Millisecond))
72+
gm.Expect(expSocketTimeout).To(gm.BeNumerically("~", matrix.expSocketTimeout, 2*time.Millisecond))
7373
}
7474
})
7575

go.mod

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,28 @@ module github.com/aerospike/aerospike-client-go/v8
33
go 1.23.0
44

55
require (
6-
github.com/onsi/ginkgo/v2 v2.22.2
7-
github.com/onsi/gomega v1.36.2
6+
github.com/onsi/ginkgo/v2 v2.27.2
7+
github.com/onsi/gomega v1.38.2
88
github.com/wadey/gocovmerge v0.0.0-20160331181800-b5bfa59ec0ad
99
github.com/yuin/gopher-lua v1.1.1
10-
golang.org/x/sync v0.12.0
10+
golang.org/x/sync v0.16.0
1111
gopkg.in/yaml.v3 v3.0.1
1212
)
1313

1414
require (
15-
github.com/go-logr/logr v1.4.2 // indirect
15+
github.com/Masterminds/semver/v3 v3.4.0 // indirect
16+
github.com/go-logr/logr v1.4.3 // indirect
1617
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
17-
github.com/google/go-cmp v0.6.0 // indirect
18-
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
18+
github.com/google/go-cmp v0.7.0 // indirect
19+
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
1920
github.com/kr/pretty v0.3.1 // indirect
2021
github.com/stretchr/testify v1.10.0 // indirect
21-
golang.org/x/net v0.37.0 // indirect
22-
golang.org/x/sys v0.31.0 // indirect
23-
golang.org/x/text v0.23.0 // indirect
24-
golang.org/x/tools v0.31.0 // indirect
22+
go.yaml.in/yaml/v3 v3.0.4 // indirect
23+
golang.org/x/mod v0.27.0 // indirect
24+
golang.org/x/net v0.43.0 // indirect
25+
golang.org/x/sys v0.35.0 // indirect
26+
golang.org/x/text v0.28.0 // indirect
27+
golang.org/x/tools v0.36.0 // indirect
28+
google.golang.org/protobuf v1.36.7 // indirect
2529
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
2630
)

0 commit comments

Comments
 (0)