Skip to content

Commit

Permalink
Merge branch 'main' into mashail/main
Browse files Browse the repository at this point in the history
* main:
  feat: add yugabytedb module (testcontainers#2825)
  fix: update module container struct name and missing imports (testcontainers#2831)
  • Loading branch information
mdelapenya committed Oct 18, 2024
2 parents 14f86e0 + 27f699b commit 615afbb
Show file tree
Hide file tree
Showing 18 changed files with 876 additions and 49 deletions.
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, etcd, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, meilisearch, 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, meilisearch, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate, yugabytedb]
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 @@ -205,6 +205,10 @@
"name": "module / weaviate",
"path": "../modules/weaviate"
},
{
"name": "module / yugabytedb",
"path": "../modules/yugabytedb"
},
{
"name": "modulegen",
"path": "../modulegen"
Expand Down
94 changes: 94 additions & 0 deletions docs/modules/yugabytedb.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# YugabyteDB

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

## Adding this module to your project dependencies

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

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

## Usage example

<!--codeinclude-->
[Creating a yugabyteDB container](../../modules/yugabytedb/examples_test.go) inside_block:runyugabyteDBContainer
<!--/codeinclude-->

## Module Reference

### Run function

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

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

#### Image

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

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

#### Initial Database

By default the yugabyteDB container will start with a database named `yugabyte` and the default credentials `yugabyte` and `yugabyte`.

If you need to set a different database, and its credentials, you can use the `WithDatabaseName(dbName string)`, `WithDatabaseUser(dbUser string)` and `WithDatabasePassword(dbPassword string)` options.

#### Initial Cluster Configuration

By default the yugabyteDB container will start with a cluster keyspace named `yugabyte` and the default credentials `yugabyte` and `yugabyte`.

If you need to set a different cluster keyspace, and its credentials, you can use the `WithKeyspace(keyspace string)`, `WithUser(user string)` and `WithPassword(password string)` options.

### Container Methods

The yugabyteDB container exposes the following methods:

#### YSQLConnectionString

This method returns the connection string for the yugabyteDB container when using
the YSQL query language.
The connection string can then be used to connect to the yugabyteDB container using
a standard PostgreSQL client.

<!--codeinclude-->
[Create a postgres client using the connection string](../../modules/yugabytedb/examples_test.go) block:ExampleContainer_YSQLConnectionString
<!--/codeinclude-->

### Usage examples

#### Usage with YSQL and gocql

To use the YCQL query language, you need to configure the cluster
with the keyspace, user, and password.

By default, the yugabyteDB container will start with a cluster keyspace named `yugabyte` and the default credentials `yugabyte` and `yugabyte` but you can change it using the `WithKeyspace`, `WithUser` and `WithPassword` options.

In order to get the appropriate host and port to connect to the yugabyteDB container,
you can use the `GetHost` and `GetMappedPort` methods on the Container struct.
See the examples below:

<!--codeinclude-->
[Create a yugabyteDB client using the cluster configuration](../../modules/yugabytedb/yugabytedb_test.go) block:TestYugabyteDB_YCQL
<!--/codeinclude-->
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ nav:
- modules/vault.md
- modules/vearch.md
- modules/weaviate.md
- modules/yugabytedb.md
- Examples:
- examples/index.md
- examples/nginx.md
Expand Down
4 changes: 2 additions & 2 deletions modulegen/_template/examples_test.go.tmpl
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{{ $entrypoint := Entrypoint }}{{ $image := Image }}{{ $lower := ToLower }}{{ $title := Title }}package {{ $lower }}_test
{{ $entrypoint := Entrypoint }}{{ $image := Image }}{{ $lower := ToLower }}package {{ $lower }}_test

import (
"context"
"fmt"
"log"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/{{ ParentDir }}/{{ $lower }}"
)

func Example{{ $entrypoint }}() {
// run{{ $title }}Container {
ctx := context.Background()

{{ $lower }}Container, err := {{ $lower }}.{{ $entrypoint }}(ctx, "{{ $image }}")
Expand Down
10 changes: 5 additions & 5 deletions modulegen/_template/module.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (
"github.com/testcontainers/testcontainers-go"
)

// {{ $containerName }} represents the {{ $title }} container type used in the module
type {{ $containerName }} struct {
// Container represents the {{ $title }} container type used in the module
type Container struct {
testcontainers.Container
}

// {{ $entrypoint }} creates an instance of the {{ $title }} container type
func {{ $entrypoint }}(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*{{ $containerName }}, error) {
func {{ $entrypoint }}(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) {
req := testcontainers.ContainerRequest{
Image: img,
}
Expand All @@ -30,9 +30,9 @@ func {{ $entrypoint }}(ctx context.Context, img string, opts ...testcontainers.C
}

container, err := testcontainers.GenericContainer(ctx, genericContainerReq)
var c *{{ $containerName }}
var c *Container
if container != nil {
c = &{{ $containerName }}{Container: container}
c = &Container{Container: container}
}

if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions modulegen/_template/module.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{ $lower := ToLower }}{{ $title := Title }}# {{ $title }}
{{ $entrypoint := Entrypoint }}{{ $lower := ToLower }}{{ $title := Title }}# {{ $title }}

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>

Expand All @@ -17,7 +17,7 @@ go get github.com/testcontainers/testcontainers-go/{{ ParentDir }}/{{ $lower }}
## Usage example

<!--codeinclude-->
[Creating a {{ $title }} container](../../{{ ParentDir }}/{{ $lower }}/examples_test.go) inside_block:run{{ $title }}Container
[Creating a {{ $title }} container](../../{{ ParentDir }}/{{ $lower }}/examples_test.go) inside_block:Example{{ $entrypoint }}
<!--/codeinclude-->

## Module Reference
Expand Down
1 change: 1 addition & 0 deletions modulegen/_template/module_test.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/stretchr/testify/require"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/{{ ParentDir }}/{{ $lower }}"
)

Expand Down
13 changes: 1 addition & 12 deletions modulegen/internal/context/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"fmt"
"regexp"
"strings"
"unicode"
"unicode/utf8"

"golang.org/x/text/cases"
"golang.org/x/text/language"
Expand All @@ -22,16 +20,7 @@ type TestcontainersModule struct {
// ContainerName returns the name of the container, which is the lower-cased title of the example
// If the title is set, it will be used instead of the name
func (m *TestcontainersModule) ContainerName() string {
name := m.Lower()

if m.IsModule {
name = m.Title()
} else if m.TitleName != "" {
r, n := utf8.DecodeRuneInString(m.TitleName)
name = string(unicode.ToLower(r)) + m.TitleName[n:]
}

return name + "Container"
return "Container"
}

// Entrypoint returns the name of the entrypoint function, which is the lower-cased title of the example
Expand Down
48 changes: 22 additions & 26 deletions modulegen/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ import (

func TestModule(t *testing.T) {
tests := []struct {
name string
module context.TestcontainersModule
expectedContainerName string
expectedEntrypoint string
expectedTitle string
name string
module context.TestcontainersModule
expectedEntrypoint string
expectedTitle string
}{
{
name: "Module with title",
Expand All @@ -31,9 +30,8 @@ func TestModule(t *testing.T) {
Image: "mongodb:latest",
TitleName: "MongoDB",
},
expectedContainerName: "MongoDBContainer",
expectedEntrypoint: "Run",
expectedTitle: "MongoDB",
expectedEntrypoint: "Run",
expectedTitle: "MongoDB",
},
{
name: "Module without title",
Expand All @@ -42,9 +40,8 @@ func TestModule(t *testing.T) {
IsModule: true,
Image: "mongodb:latest",
},
expectedContainerName: "MongodbContainer",
expectedEntrypoint: "Run",
expectedTitle: "Mongodb",
expectedEntrypoint: "Run",
expectedTitle: "Mongodb",
},
{
name: "Example with title",
Expand All @@ -54,9 +51,8 @@ func TestModule(t *testing.T) {
Image: "mongodb:latest",
TitleName: "MongoDB",
},
expectedContainerName: "mongoDBContainer",
expectedEntrypoint: "run",
expectedTitle: "MongoDB",
expectedEntrypoint: "run",
expectedTitle: "MongoDB",
},
{
name: "Example without title",
Expand All @@ -65,9 +61,9 @@ func TestModule(t *testing.T) {
IsModule: false,
Image: "mongodb:latest",
},
expectedContainerName: "mongodbContainer",
expectedEntrypoint: "run",
expectedTitle: "Mongodb",

expectedEntrypoint: "run",
expectedTitle: "Mongodb",
},
}

Expand All @@ -77,7 +73,7 @@ func TestModule(t *testing.T) {

assert.Equal(t, "mongodb", module.Lower())
assert.Equal(t, test.expectedTitle, module.Title())
assert.Equal(t, test.expectedContainerName, module.ContainerName())
assert.Equal(t, "Container", module.ContainerName())
assert.Equal(t, test.expectedEntrypoint, module.Entrypoint())
})
}
Expand Down Expand Up @@ -366,6 +362,7 @@ func assertModuleDocContent(t *testing.T, module context.TestcontainersModule, m

lower := module.Lower()
title := module.Title()
entrypoint := module.Entrypoint()

data := sanitiseContent(content)
assert.Equal(t, "# "+title, data[0])
Expand All @@ -376,7 +373,7 @@ func assertModuleDocContent(t *testing.T, module context.TestcontainersModule, m
assert.Equal(t, "Please run the following command to add the "+title+" module to your Go dependencies:", data[10])
assert.Equal(t, "go get github.com/testcontainers/testcontainers-go/"+module.ParentDir()+"/"+lower, data[13])
assert.Equal(t, "<!--codeinclude-->", data[18])
assert.Equal(t, "[Creating a "+title+" container](../../"+module.ParentDir()+"/"+lower+"/examples_test.go) inside_block:run"+title+"Container", data[19])
assert.Equal(t, "[Creating a "+title+" container](../../"+module.ParentDir()+"/"+lower+"/examples_test.go) inside_block:Example"+entrypoint, data[19])
assert.Equal(t, "<!--/codeinclude-->", data[20])
assert.Equal(t, "The "+title+" module exposes one entrypoint function to create the "+title+" container, and this function receives three parameters:", data[31])
assert.True(t, strings.HasSuffix(data[34], "(*"+title+"Container, error)"))
Expand All @@ -391,13 +388,12 @@ func assertExamplesTestContent(t *testing.T, module context.TestcontainersModule

lower := module.Lower()
entrypoint := module.Entrypoint()
title := module.Title()

data := sanitiseContent(content)
assert.Equal(t, "package "+lower+"_test", data[0])
assert.Equal(t, "\t\"github.com/testcontainers/testcontainers-go/modules/"+lower+"\"", data[7])
assert.Equal(t, "func Example"+entrypoint+"() {", data[10])
assert.Equal(t, "\t// run"+title+"Container {", data[11])
assert.Equal(t, "\t\"github.com/testcontainers/testcontainers-go\"", data[7])
assert.Equal(t, "\t\"github.com/testcontainers/testcontainers-go/modules/"+lower+"\"", data[8])
assert.Equal(t, "func Example"+entrypoint+"() {", data[11])
assert.Equal(t, "\t"+lower+"Container, err := "+lower+"."+entrypoint+"(ctx, \""+module.Image+"\")", data[14])
assert.Equal(t, "\tfmt.Println(state.Running)", data[32])
assert.Equal(t, "\t// Output:", data[34])
Expand All @@ -411,8 +407,8 @@ func assertModuleTestContent(t *testing.T, module context.TestcontainersModule,

data := sanitiseContent(content)
assert.Equal(t, "package "+module.Lower()+"_test", data[0])
assert.Equal(t, "func Test"+module.Title()+"(t *testing.T) {", data[11])
assert.Equal(t, "\tctr, err := "+module.Lower()+"."+module.Entrypoint()+"(ctx, \""+module.Image+"\")", data[14])
assert.Equal(t, "func Test"+module.Title()+"(t *testing.T) {", data[12])
assert.Equal(t, "\tctr, err := "+module.Lower()+"."+module.Entrypoint()+"(ctx, \""+module.Image+"\")", data[15])
}

// assert content module
Expand All @@ -427,7 +423,7 @@ func assertModuleContent(t *testing.T, module context.TestcontainersModule, exam

data := sanitiseContent(content)
require.Equal(t, "package "+lower, data[0])
require.Equal(t, "// "+containerName+" represents the "+exampleName+" container type used in the module", data[9])
require.Equal(t, "// Container represents the "+exampleName+" container type used in the module", data[9])
require.Equal(t, "type "+containerName+" struct {", data[10])
require.Equal(t, "// "+entrypoint+" creates an instance of the "+exampleName+" container type", data[14])
require.Equal(t, "func "+entrypoint+"(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*"+containerName+", error) {", data[15])
Expand Down
5 changes: 5 additions & 0 deletions modules/yugabytedb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include ../../commons-test.mk

.PHONY: test
test:
$(MAKE) test-yugabytedb
Loading

0 comments on commit 615afbb

Please sign in to comment.