Skip to content

Commit 61a08e1

Browse files
authored
feat: add arangodb module (#3083)
* feat: add arangodb module * fix: proper fmt usage * chore: expose container credentials * chore: rename method to a more meaningful name * fix: use new name in docs * docs: fix embedded snippet
1 parent 822a8bd commit 61a08e1

11 files changed

Lines changed: 603 additions & 0 deletions

File tree

.github/dependabot.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ updates:
1616
- /examples/nginx
1717
- /examples/toxiproxy
1818
- /modulegen
19+
- /modules/arangodb
1920
- /modules/artemis
2021
- /modules/azure
2122
- /modules/azurite

.vscode/.testcontainers-go.code-workspace

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
"name": "example / toxiproxy",
1414
"path": "../examples/toxiproxy"
1515
},
16+
{
17+
"name": "module / arangodb",
18+
"path": "../modules/arangodb"
19+
},
1620
{
1721
"name": "module / artemis",
1822
"path": "../modules/artemis"

docs/modules/arangodb.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# ArangoDB
2+
3+
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>
4+
5+
## Introduction
6+
7+
The Testcontainers module for ArangoDB.
8+
9+
## Adding this module to your project dependencies
10+
11+
Please run the following command to add the ArangoDB module to your Go dependencies:
12+
13+
```
14+
go get github.com/testcontainers/testcontainers-go/modules/arangodb
15+
```
16+
17+
## Usage example
18+
19+
<!--codeinclude-->
20+
[Creating a ArangoDB container](../../modules/arangodb/examples_test.go) inside_block:runArangoDBContainer
21+
<!--/codeinclude-->
22+
23+
## Module Reference
24+
25+
### Run function
26+
27+
- 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>
28+
29+
The ArangoDB module exposes one entrypoint function to create the ArangoDB container, and this function receives three parameters:
30+
31+
```golang
32+
func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*ArangoDBContainer, error)
33+
```
34+
35+
- `context.Context`, the Go context.
36+
- `string`, the Docker image to use.
37+
- `testcontainers.ContainerCustomizer`, a variadic argument for passing options.
38+
39+
### Container Options
40+
41+
When starting the ArangoDB container, you can pass options in a variadic way to configure it.
42+
43+
#### Image
44+
45+
Use the second argument in the `Run` function to set a valid Docker image.
46+
In example: `Run(context.Background(), "arangodb:3.11.5")`.
47+
48+
{% include "../features/common_functional_options.md" %}
49+
50+
#### WithRootPassword
51+
52+
- 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>
53+
54+
The `WithRootPassword` function sets the root password for the ArangoDB container.
55+
56+
### Container Methods
57+
58+
The ArangoDB container exposes the following methods:
59+
60+
#### Credentials
61+
62+
- 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>
63+
64+
The `Credentials` method returns the credentials for the ArangoDB container, in the form of a tuple of two strings: the username and the password.
65+
66+
```golang
67+
func (c *Container) Credentials() (string, string)
68+
```
69+
70+
#### HTTPEndpoint
71+
72+
- 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>
73+
74+
The `HTTPEndpoint` method returns the HTTP endpoint of the ArangoDB container, using the following format: `http://$host:$port`.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ nav:
6868
- Walk: features/wait/walk.md
6969
- Modules:
7070
- modules/index.md
71+
- modules/arangodb.md
7172
- modules/artemis.md
7273
- modules/azure.md
7374
- modules/azurite.md

modules/arangodb/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include ../../commons-test.mk
2+
3+
.PHONY: test
4+
test:
5+
$(MAKE) test-arangodb

modules/arangodb/arangodb.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package arangodb
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
8+
"github.com/testcontainers/testcontainers-go"
9+
"github.com/testcontainers/testcontainers-go/wait"
10+
)
11+
12+
const (
13+
defaultPort = "8529/tcp"
14+
15+
// DefaultUser is the default username for the ArangoDB container.
16+
// This is the username to be used when connecting to the ArangoDB instance.
17+
DefaultUser = "root"
18+
19+
defaultPassword = "root"
20+
)
21+
22+
// Container represents the ArangoDB container type used in the module
23+
type Container struct {
24+
testcontainers.Container
25+
password string
26+
}
27+
28+
// Credentials returns the credentials for the ArangoDB container:
29+
// first return value is the username, second is the password.
30+
func (c *Container) Credentials() (string, string) {
31+
return DefaultUser, c.password
32+
}
33+
34+
// HTTPEndpoint returns the HTTP endpoint of the ArangoDB container, using the following format: `http://$host:$port`.
35+
func (c *Container) HTTPEndpoint(ctx context.Context) (string, error) {
36+
hostPort, err := c.PortEndpoint(ctx, defaultPort, "http")
37+
if err != nil {
38+
return "", fmt.Errorf("port endpoint: %w", err)
39+
}
40+
41+
return hostPort, nil
42+
}
43+
44+
// Run creates an instance of the ArangoDB container type
45+
func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) {
46+
req := testcontainers.ContainerRequest{
47+
Image: img,
48+
ExposedPorts: []string{defaultPort},
49+
Env: map[string]string{
50+
"ARANGO_ROOT_PASSWORD": defaultPassword,
51+
},
52+
}
53+
54+
genericContainerReq := testcontainers.GenericContainerRequest{
55+
ContainerRequest: req,
56+
Started: true,
57+
}
58+
59+
for _, opt := range opts {
60+
if err := opt.Customize(&genericContainerReq); err != nil {
61+
return nil, fmt.Errorf("customize: %w", err)
62+
}
63+
}
64+
65+
// Wait for the container to be ready once we know the credentials
66+
genericContainerReq.WaitingFor = wait.ForAll(
67+
wait.ForListeningPort(defaultPort),
68+
wait.ForHTTP("/_admin/status").
69+
WithPort(defaultPort).
70+
WithBasicAuth(DefaultUser, req.Env["ARANGO_ROOT_PASSWORD"]).
71+
WithHeaders(map[string]string{
72+
"Accept": "application/json",
73+
}).
74+
WithStatusCodeMatcher(func(status int) bool {
75+
return status == http.StatusOK
76+
}),
77+
)
78+
79+
container, err := testcontainers.GenericContainer(ctx, genericContainerReq)
80+
var c *Container
81+
if container != nil {
82+
c = &Container{Container: container, password: req.Env["ARANGO_ROOT_PASSWORD"]}
83+
}
84+
85+
if err != nil {
86+
return c, fmt.Errorf("generic container: %w", err)
87+
}
88+
89+
return c, nil
90+
}

modules/arangodb/arangodb_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package arangodb_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/arangodb/go-driver/v2/arangodb"
8+
"github.com/arangodb/go-driver/v2/connection"
9+
"github.com/stretchr/testify/require"
10+
11+
"github.com/testcontainers/testcontainers-go"
12+
tcarangodb "github.com/testcontainers/testcontainers-go/modules/arangodb"
13+
)
14+
15+
func TestArangoDB(t *testing.T) {
16+
ctx := context.Background()
17+
18+
const password = "t3stc0ntain3rs!"
19+
20+
ctr, err := tcarangodb.Run(ctx, "arangodb:3.11.5", tcarangodb.WithRootPassword(password))
21+
testcontainers.CleanupContainer(t, ctr)
22+
require.NoError(t, err)
23+
24+
httpAddress, err := ctr.HTTPEndpoint(ctx)
25+
require.NoError(t, err)
26+
27+
endpoint := connection.NewRoundRobinEndpoints([]string{httpAddress})
28+
conn := connection.NewHttp2Connection(connection.DefaultHTTP2ConfigurationWrapper(endpoint, true))
29+
30+
auth := connection.NewBasicAuth(ctr.Credentials())
31+
err = conn.SetAuthentication(auth)
32+
require.NoError(t, err)
33+
34+
client := arangodb.NewClient(conn)
35+
36+
versionInfo, err := client.Version(context.Background())
37+
require.NoError(t, err)
38+
require.Equal(t, "arango", versionInfo.Server)
39+
}

modules/arangodb/examples_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package arangodb_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
8+
"github.com/arangodb/go-driver/v2/arangodb"
9+
"github.com/arangodb/go-driver/v2/connection"
10+
11+
"github.com/testcontainers/testcontainers-go"
12+
tcarangodb "github.com/testcontainers/testcontainers-go/modules/arangodb"
13+
)
14+
15+
func ExampleRun() {
16+
// runArangoDBContainer {
17+
ctx := context.Background()
18+
19+
const password = "t3stc0ntain3rs!"
20+
21+
arangodbContainer, err := tcarangodb.Run(ctx, "arangodb:3.11.5", tcarangodb.WithRootPassword(password))
22+
defer func() {
23+
if err := testcontainers.TerminateContainer(arangodbContainer); err != nil {
24+
log.Printf("failed to terminate container: %s", err)
25+
}
26+
}()
27+
if err != nil {
28+
log.Printf("failed to start container: %s", err)
29+
return
30+
}
31+
// }
32+
33+
state, err := arangodbContainer.State(ctx)
34+
if err != nil {
35+
log.Printf("failed to get container state: %s", err)
36+
return
37+
}
38+
39+
fmt.Println(state.Running)
40+
41+
// Output:
42+
// true
43+
}
44+
45+
func ExampleRun_usingClient() {
46+
ctx := context.Background()
47+
48+
const password = "t3stc0ntain3rs!"
49+
50+
arangodbContainer, err := tcarangodb.Run(
51+
ctx, "arangodb:3.11.5",
52+
tcarangodb.WithRootPassword(password),
53+
)
54+
defer func() {
55+
if err := testcontainers.TerminateContainer(arangodbContainer); err != nil {
56+
log.Printf("failed to terminate container: %s", err)
57+
}
58+
}()
59+
if err != nil {
60+
log.Printf("failed to start container: %s", err)
61+
return
62+
}
63+
// }
64+
65+
httpAddress, err := arangodbContainer.HTTPEndpoint(ctx)
66+
if err != nil {
67+
log.Printf("failed to get transport address: %s", err)
68+
return
69+
}
70+
71+
// Create an HTTP connection to the database
72+
endpoint := connection.NewRoundRobinEndpoints([]string{httpAddress})
73+
conn := connection.NewHttp2Connection(connection.DefaultHTTP2ConfigurationWrapper(endpoint, true))
74+
75+
// Add authentication
76+
auth := connection.NewBasicAuth(arangodbContainer.Credentials())
77+
err = conn.SetAuthentication(auth)
78+
if err != nil {
79+
log.Printf("Failed to set authentication: %v", err)
80+
return
81+
}
82+
83+
// Create a client
84+
client := arangodb.NewClient(conn)
85+
86+
// Ask the version of the server
87+
versionInfo, err := client.Version(context.Background())
88+
if err != nil {
89+
log.Printf("Failed to get version info: %v", err)
90+
return
91+
}
92+
93+
fmt.Println(versionInfo.Server)
94+
95+
// Output:
96+
// arango
97+
}

0 commit comments

Comments
 (0)