Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add etcd module #2788

Merged
merged 50 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
d67869c
chore: scaffolding for etcd module
mdelapenya Sep 18, 2024
59f2c33
feat: add etcd with cluster support
mdelapenya Sep 19, 2024
1d3d0f4
feat: support for AutoTLS
mdelapenya Sep 19, 2024
16aa1f5
chore: add unit test for cmd
mdelapenya Sep 19, 2024
6b3b691
Merge branch 'main' into etcd-module
mdelapenya Sep 19, 2024
4629dda
fix: remove non-existent module
mdelapenya Sep 19, 2024
33f7dcc
chore: simplify removing auto-tls support
mdelapenya Sep 19, 2024
60af87a
docs: remove old deprecated function
mdelapenya Sep 20, 2024
aa1cea5
Merge branch 'main' into etcd-module
mdelapenya Sep 20, 2024
236ea84
docs: document functions
mdelapenya Sep 20, 2024
0f039d0
docs: remove commented code
mdelapenya Sep 20, 2024
b0eedbd
chore: more readable tests
mdelapenya Sep 24, 2024
1bce3b8
chore: move logic to the functional option
mdelapenya Sep 24, 2024
761ad15
chore: simplify passing current node opts
mdelapenya Sep 24, 2024
b81b996
fix: return the parent node when creating the child nodes
mdelapenya Sep 24, 2024
8885b44
chore: move to constant
mdelapenya Sep 24, 2024
6c30d88
chore: use zero values
mdelapenya Sep 24, 2024
dda3352
fix: typo after wrong copy&paste
mdelapenya Sep 24, 2024
db70ad3
Merge branch 'main' into etcd-module
mdelapenya Sep 24, 2024
6f954bf
chore: remove must methods
mdelapenya Sep 24, 2024
99f646a
chore: use private fields in the container
mdelapenya Sep 25, 2024
e8d85aa
chore: use private fields in the options struct
mdelapenya Sep 25, 2024
06f33e7
chore: simplify public API
mdelapenya Sep 25, 2024
aefd26a
chore: make constants private
mdelapenya Sep 25, 2024
10cd435
fix: lint
mdelapenya Sep 25, 2024
2728290
chore: rename field to childNodes
mdelapenya Sep 25, 2024
17e83cc
docs: enrich container comments
mdelapenya Sep 25, 2024
72ee43b
fix: assert on the right node
mdelapenya Sep 25, 2024
1d14664
Merge branch 'main' into etcd-module
mdelapenya Sep 26, 2024
60b1c37
chore: bump dockercfg
mdelapenya Sep 26, 2024
b55faac
Merge branch 'main' into etcd-module
mdelapenya Sep 27, 2024
5ebde1e
feat: implement termination of the cluster
mdelapenya Sep 27, 2024
4b5b17c
chore: use require.Zero
mdelapenya Sep 27, 2024
7254893
chore: proper test name
mdelapenya Sep 27, 2024
93c9bc5
chore: preallocate slice
mdelapenya Sep 27, 2024
05a3008
chore: do not allow single-node clusters
mdelapenya Sep 27, 2024
146c37d
fix: join errors on terminate cluster
mdelapenya Sep 27, 2024
c3b23b5
fix: check parent container is terminated
mdelapenya Sep 27, 2024
f52460d
chore: extract to function
mdelapenya Sep 27, 2024
2dc6f94
fix: check if container is not nil
mdelapenya Sep 27, 2024
6d73971
chor: do not orphan the network
mdelapenya Sep 27, 2024
533da13
chore: simplify
mdelapenya Sep 27, 2024
923079c
docs: fix comment
mdelapenya Sep 27, 2024
1c4361b
chore: wrap errors in endpoint functions
mdelapenya Sep 27, 2024
c44457d
Revert "chore: wrap errors in endpoint functions"
mdelapenya Sep 27, 2024
8e3d3c7
chore: simplify eval
mdelapenya Sep 27, 2024
1f60a3b
Merge branch 'main' into etcd-module
mdelapenya Sep 30, 2024
70859ab
fix: not needed
mdelapenya Sep 30, 2024
a8dd1bc
chore: simplify container initialisation
mdelapenya Sep 30, 2024
bf67013
chore: simplify even more
mdelapenya Sep 30, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
matrix:
go-version: [1.22.x, 1.x]
platform: [ubuntu-latest]
module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate]
module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, etcd, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate]
uses: ./.github/workflows/ci-test-go.yml
with:
go-version: ${{ matrix.go-version }}
Expand Down
4 changes: 4 additions & 0 deletions .vscode/.testcontainers-go.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
"name": "module / elasticsearch",
"path": "../modules/elasticsearch"
},
{
"name": "module / etcd",
"path": "../modules/etcd"
},
{
"name": "module / gcloud",
"path": "../modules/gcloud"
Expand Down
95 changes: 95 additions & 0 deletions docs/modules/etcd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# etcd

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 etcd.

## Adding this module to your project dependencies

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

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

## Usage example

<!--codeinclude-->
[Creating a etcd container](../../modules/etcd/examples_test.go) inside_block:runetcdContainer
<!--/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 etcd module exposes one entrypoint function to create the etcd container, and this function receives three parameters:

```golang
func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*etcdContainer, 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 etcd container, you can pass options in a variadic way to configure it.

#### Image

If you need to set a different etcd Docker image, you can set a valid Docker image as the second argument in the `Run` function.
E.g. `Run(context.Background(), "bitnami/etcd:latest")`.

{% include "../features/common_functional_options.md" %}

#### WithAdditionalArgs

- 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>

You can pass additional arguments to the etcd container by using the `WithAdditionalArgs` option. The arguments are passed to the CMD of the etcd container.

#### WithDataDir

- 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>

You can set the data directory for the etcd container by using the `WithDataDir` boolean option. The data directory where the etcd data is stored is `/data.etcd`.

#### WithNodes

- 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>

You can set the number of nodes for the etcd cluster by using the `WithNodes` option, passing the node names for each of the nodes. Single-node clusters are not allowed,
for that reason the functional option receives three string arguments: the first node, the second node, and a variadic argument for the rest of the nodes.
The module starts a container for each node, having the first node a reference to the other nodes. E.g. `WithNodes("etcd-1", "etcd-2")`, `WithNodes("etcd-1", "etcd-2", "etcd-3")` and so on.

The module creates a Docker network for the etcd cluster, and the nodes are connected to this network, so that they can communicate with each other through the network.

#### WithClusterToken

- 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>

Sets the cluster token for the etcd cluster. The cluster token is used to identify the etcd cluster. The default value is `mys3cr3ttok3n`.
The etcd container holds a reference to the cluster token, so you can use it with e.g. `ctr.ClusterToken`.

### Container Methods

- 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 etcd container exposes the following methods:

#### ClientEndpoint

- 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>

Returns the client endpoint for the etcd container and an error, if any. In the case of a cluster, it returns the client endpoint for the first node.

#### PeerEndpoint

- 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>

Returns the peer endpoint for the etcd container and an error, if any. In the case of a cluster, it returns the peer endpoint for the first node.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ nav:
- modules/dolt.md
- modules/dynamodb.md
- modules/elasticsearch.md
- modules/etcd.md
- modules/gcloud.md
- modules/grafana-lgtm.md
- modules/inbucket.md
Expand Down
5 changes: 5 additions & 0 deletions modules/etcd/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include ../../commons-test.mk

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

import (
"testing"

"github.com/stretchr/testify/require"
)

func Test_configureCMD(t *testing.T) {
t.Run("default", func(t *testing.T) {
got := configureCMD(options{})
want := []string{"etcd", "--name=default"}
require.Equal(t, want, got)
})

t.Run("with-node", func(t *testing.T) {
got := configureCMD(options{
nodeNames: []string{"node1"},
})
want := []string{
"etcd",
"--name=node1",
"--initial-advertise-peer-urls=http://node1:2380",
"--advertise-client-urls=http://node1:2379",
"--listen-peer-urls=http://0.0.0.0:2380",
"--listen-client-urls=http://0.0.0.0:2379",
"--initial-cluster-state=new",
"--initial-cluster=node1=http://node1:2380",
}
require.Equal(t, want, got)
})

t.Run("with-node-datadir", func(t *testing.T) {
got := configureCMD(options{
nodeNames: []string{"node1"},
mountDataDir: true,
})
want := []string{
"etcd",
"--name=node1",
"--initial-advertise-peer-urls=http://node1:2380",
"--advertise-client-urls=http://node1:2379",
"--listen-peer-urls=http://0.0.0.0:2380",
"--listen-client-urls=http://0.0.0.0:2379",
"--initial-cluster-state=new",
"--initial-cluster=node1=http://node1:2380",
"--data-dir=/data.etcd",
}
require.Equal(t, want, got)
})

t.Run("with-node-datadir-additional-args", func(t *testing.T) {
got := configureCMD(options{
nodeNames: []string{"node1"},
mountDataDir: true,
additionalArgs: []string{"--auto-compaction-retention=1"},
})
want := []string{
"etcd",
"--name=node1",
"--initial-advertise-peer-urls=http://node1:2380",
"--advertise-client-urls=http://node1:2379",
"--listen-peer-urls=http://0.0.0.0:2380",
"--listen-client-urls=http://0.0.0.0:2379",
"--initial-cluster-state=new",
"--initial-cluster=node1=http://node1:2380",
"--data-dir=/data.etcd",
"--auto-compaction-retention=1",
}
require.Equal(t, want, got)
})

t.Run("with-cluster", func(t *testing.T) {
got := configureCMD(options{
nodeNames: []string{"node1", "node2"},
})
want := []string{
"etcd",
"--name=node1",
"--initial-advertise-peer-urls=http://node1:2380",
"--advertise-client-urls=http://node1:2379",
"--listen-peer-urls=http://0.0.0.0:2380",
"--listen-client-urls=http://0.0.0.0:2379",
"--initial-cluster-state=new",
"--initial-cluster=node1=http://node1:2380,node2=http://node2:2380",
}
require.Equal(t, want, got)
})

t.Run("with-cluster-token", func(t *testing.T) {
got := configureCMD(options{
nodeNames: []string{"node1", "node2"},
clusterToken: "token",
})
want := []string{
"etcd",
"--name=node1",
"--initial-advertise-peer-urls=http://node1:2380",
"--advertise-client-urls=http://node1:2379",
"--listen-peer-urls=http://0.0.0.0:2380",
"--listen-client-urls=http://0.0.0.0:2379",
"--initial-cluster-state=new",
"--initial-cluster=node1=http://node1:2380,node2=http://node2:2380",
"--initial-cluster-token=token",
}
require.Equal(t, want, got)
})
}
Loading