Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ updates:
- /examples/nginx
- /examples/toxiproxy
- /modulegen
- /modules/aerospike
- /modules/arangodb
- /modules/artemis
- /modules/azure
Expand Down
48 changes: 48 additions & 0 deletions docs/modules/aerospike.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Aerospike

Not available until the next release of testcontainers-go <a href="https://github.com/testcontainers/testcontainers-go"><span class="tc-version">:material-tag: main</span></a>

## Introduction

The Testcontainers module for Aerospike.

## Adding this module to your project dependencies

Please run the following command to add the Aerospike module to your Go dependencies:

```
go get github.com/testcontainers/testcontainers-go/modules/aerospike
```

## Usage example

<!--codeinclude-->
[Creating a Aerospike container](../../modules/aerospike/examples_test.go) inside_block:runAerospikeContainer
<!--/codeinclude-->

## Module Reference

### Run function

- Not available until the next release of testcontainers-go <a href="https://github.com/testcontainers/testcontainers-go"><span class="tc-version">:material-tag: main</span></a>

The Aerospike module exposes one entrypoint function to create the Aerospike container, and this function receives three parameters:

```golang
func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*AerospikeContainer, error)
```

- `context.Context`, the Go context.
- `string`, the Docker image to use.
- `testcontainers.ContainerCustomizer`, a variadic argument for passing options.

### Container Options

When starting the Aerospike container, you can pass options in a variadic way to configure it.

#### Image

Use the second argument in the `Run` function to set a valid Docker image.
In example: `Run(context.Background(), "aerospike/aerospike-server:latest")`.

{% include "../features/common_functional_options.md" %}
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ nav:
- Walk: features/wait/walk.md
- Modules:
- modules/index.md
- modules/aerospike.md
- modules/arangodb.md
- modules/artemis.md
- modules/azure.md
Expand Down
5 changes: 5 additions & 0 deletions modules/aerospike/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include ../../commons-test.mk

.PHONY: test
test:
$(MAKE) test-aerospike
71 changes: 71 additions & 0 deletions modules/aerospike/aerospike.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package aerospike

import (
"context"
"fmt"
"time"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)

const (
port = "3000/tcp"
containerName = "tc_dynamodb_local"
)

type AerospikeContainer struct {
testcontainers.Container
Host string
Port int
}

// Run creates an instance of the Aerospike container type
func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*AerospikeContainer, error) {
req := testcontainers.ContainerRequest{
Image: img,
ExposedPorts: []string{"3000/tcp", "3001/tcp", "3002/tcp", "3003/tcp"},
Env: map[string]string{
"AEROSPIKE_CONFIG_FILE": "/etc/aerospike/aerospike.conf",
"NAMESPACE": "test",
},
WaitingFor: wait.ForAll(
wait.ForLog("migrations: complete"),
wait.ForListeningPort("3000/tcp").WithStartupTimeout(10*time.Second),
wait.ForListeningPort("3001/tcp").WithStartupTimeout(10*time.Second),
wait.ForListeningPort("3002/tcp").WithStartupTimeout(10*time.Second),
),
}

genericContainerReq := testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
}

for _, opt := range opts {
if err := opt.Customize(&genericContainerReq); err != nil {
return nil, fmt.Errorf("customize: %w", err)
}
}

container, err := testcontainers.GenericContainer(ctx, genericContainerReq)
if err != nil {
return nil, fmt.Errorf("failed to start Aerospike container: %w", err)
}

host, err := container.Host(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get container host: %w", err)
}

port, err := container.MappedPort(ctx, port)
if err != nil {
return nil, fmt.Errorf("failed to get container port: %w", err)
}

return &AerospikeContainer{
Container: container,
Host: host,
Port: port.Int(),
}, nil
}
54 changes: 54 additions & 0 deletions modules/aerospike/aerospike_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package aerospike_test

import (
"context"
"testing"
"time"

"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
as "github.com/testcontainers/testcontainers-go/modules/aerospike"
)

// TestAerospikeDB tests the AerospikeDB container functionality
// It includes tests for starting the container with a valid image,
// applying container customizations, and handling context cancellation.
// It also includes a test for an invalid image to ensure proper error handling.
// The tests use the testcontainers-go library to manage container lifecycle
func TestAeroSpikeDB(t *testing.T) {
t.Run("fails with invalid image", func(t *testing.T) {
ctx := context.Background()
_, err := as.Run(ctx, "invalid-aerospike-image")
require.Error(t, err)
require.Contains(t, err.Error(), "failed to start Aerospike container")
})

t.Run("succeeds with valid image", func(t *testing.T) {
ctx := context.Background()
container, err := as.Run(ctx, "aerospike/aerospike-server:latest")
require.NoError(t, err)
require.NotNil(t, container)
defer container.Container.Terminate(ctx)

require.NotEmpty(t, container.Host)
require.NotEmpty(t, container.Port)
})

t.Run("applies container customizations", func(t *testing.T) {
ctx := context.Background()
customEnv := "TEST_ENV=value"
container, err := as.Run(ctx, "aerospike/aerospike-server:latest",
testcontainers.WithEnv(map[string]string{"CUSTOM_ENV": customEnv}))
require.NoError(t, err)
require.NotNil(t, container)
defer container.Container.Terminate(ctx)
})

t.Run("respects context cancellation", func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
defer cancel()

_, err := as.Run(ctx, "aerospike/aerospike-server:latest")
require.Error(t, err)
})
}
119 changes: 119 additions & 0 deletions modules/aerospike/examples_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package aerospike_test

import (
"context"
"fmt"
"log"
"time"

"github.com/aerospike/aerospike-client-go/v8"
"github.com/testcontainers/testcontainers-go"
as "github.com/testcontainers/testcontainers-go/modules/aerospike"
)

func ExampleRun() {
// runAerospikeContainer {
ctx := context.Background()

aerospikedbContainer, err := as.Run(ctx, "aerospike/aerospike-server:latest")
defer func() {
if err := testcontainers.TerminateContainer(aerospikedbContainer.Container); err != nil {
log.Printf("failed to terminate container: %s", err)
}
}()
if err != nil {
log.Printf("failed to start container: %s", err)
return
}
// }
state, err := aerospikedbContainer.State(ctx)
if err != nil {
log.Printf("failed to get container state: %s", err)
return
}

fmt.Println(state.Running)

// Output:
// true
}

func ExampleRun_usingClient() {
ctx := context.Background()

aerospikedbContainer, err := as.Run(
ctx, "aerospike/aerospike-server:latest",
)
defer func() {
if err := testcontainers.TerminateContainer(aerospikedbContainer.Container); err != nil {
log.Printf("failed to terminate container: %s", err)
}
}()
if err != nil {
log.Printf("failed to start container: %s", err)
return
}

aeroHost := []*aerospike.Host{aerospike.NewHost(aerospikedbContainer.Host, aerospikedbContainer.Port)}

// connect to the host
cp := aerospike.NewClientPolicy()
cp.Timeout = 10 * time.Second

// Create a client
client, err := aerospike.NewClientWithPolicyAndHost(cp, aeroHost...)
if err != nil {
log.Printf("Failed to create aerospike client: %v", err)
return
}

// Close the client
defer client.Close()

// Create a key
schemaKey, err := aerospike.NewKey("test", "test", "_schema_info")
if err != nil {
log.Printf("Failed to create key: %v", err)
return
}

version := 1
description := "test aerospike schema info"
nowStr := time.Now().Format(time.RFC3339)

// Create schema record
bins := aerospike.BinMap{
"version": version,
"created_at": nowStr,
"updated_at": nowStr,
"description": description,
}

// Never expire the schema info
writePolicy := aerospike.NewWritePolicy(0, 0)

// Store in Aerospike
err = client.Put(writePolicy, schemaKey, bins)
if err != nil {
log.Printf("Failed to put schema info: %v", err)
return
}

// Get schema record
record, err := client.Get(nil, schemaKey, "version", "created_at", "updated_at", "description")
if err != nil {
log.Printf("Failed to get schema info: %v", err)
return
}

// Schema exists, check version
existingVersion, _ := record.Bins["version"].(int)
existingDescription, _ := record.Bins["description"].(string)

fmt.Println(existingVersion)
fmt.Println(existingDescription)

// Output:
// 1
// test aerospike schema info
}
68 changes: 68 additions & 0 deletions modules/aerospike/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
module github.com/testcontainers/testcontainers-go/modules/aerospike

go 1.23.0

require (
github.com/aerospike/aerospike-client-go/v8 v8.2.0
github.com/stretchr/testify v1.10.0
github.com/testcontainers/testcontainers-go v0.36.0
)

require (
dario.cat/mergo v1.0.1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/docker v28.0.1+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/ebitengine/purego v0.8.2 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.9 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/shirou/gopsutil/v4 v4.25.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/wadey/gocovmerge v0.0.0-20160331181800-b5bfa59ec0ad // indirect
github.com/yuin/gopher-lua v1.1.1 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/tools v0.28.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading
Loading