Skip to content

Commit

Permalink
Merge branch 'main' into v1
Browse files Browse the repository at this point in the history
* main:
  feat: support databend module (#2779)
  chore: golangci-lint 1.61.0 (#2787)
  fix(mssql): bump Docker image version (#2786)
  fix: handle 127 error code for podman compatibility (#2778)
  fix: do not override ImageBuildOptions.Labels when building from a Dockerfile (#2775)
  feat(mongodb): Wait for mongodb module with a replicaset to finish (#2777)
  fix(postgres): Apply default snapshot name if no name specified (#2783)
  • Loading branch information
mdelapenya committed Sep 20, 2024
2 parents 8ef4dd1 + c1bb0bb commit 1a9498b
Show file tree
Hide file tree
Showing 28 changed files with 973 additions and 118 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci-test-go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ jobs:

- name: golangci-lint
if: ${{ inputs.platform == 'ubuntu-latest' }}
uses: golangci/golangci-lint-action@9d1e0624a798bb64f6c3cea93db47765312263dc # v5
uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: v1.59.1
version: v1.61.0
# Optional: working directory, useful for monorepos
working-directory: ${{ inputs.project-directory }}
# Optional: golangci-lint command line arguments.
Expand Down
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, dolt, 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, 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]
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 @@ -49,6 +49,10 @@
"name": "module / couchbase",
"path": "../modules/couchbase"
},
{
"name": "module / databend",
"path": "../modules/databend"
},
{
"name": "module / dolt",
"path": "../modules/dolt"
Expand Down
2 changes: 1 addition & 1 deletion commons-test.mk
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ define go_install
endef

$(GOBIN)/golangci-lint:
$(call go_install,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.1)
$(call go_install,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0)

$(GOBIN)/gotestsum:
$(call go_install,gotest.tools/gotestsum@latest)
Expand Down
72 changes: 72 additions & 0 deletions docs/modules/databend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Databend

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

## Adding this module to your project dependencies

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

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

## Usage example

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

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

#### Image

If you need to set a different Databend Docker image, you can set a valid Docker image as the second argument in the `Run` function.
E.g. `Run(context.Background(), "datafuselabs/databend:v1.2.615")`.

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

#### Set username, password

If you need to set a different user/password/database, you can use `WithUsername`, `WithPassword` options.

!!!info
The default values for the username is `databend`, for password is `databend` and for the default database name is `default`.

### Container Methods

The Databend container exposes the following methods:

#### ConnectionString

This method returns the connection string to connect to the Databend container, using the default `8000` port.
It's possible to pass extra parameters to the connection string, e.g. `sslmode=disable`.
<!--codeinclude-->
[Get connection string](../../modules/databend/databend_test.go) inside_block:connectionString
<!--/codeinclude-->
#### MustGetConnectionString
`MustConnectionString` panics if the address cannot be determined.
3 changes: 1 addition & 2 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package config

import (
"fmt"
"os"
"path/filepath"
"testing"
Expand Down Expand Up @@ -518,7 +517,7 @@ func TestReadTCConfig(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(fmt.Sprintf(tt.name), func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
tmpDir := t.TempDir()
t.Setenv("HOME", tmpDir)
t.Setenv("USERPROFILE", tmpDir) // Windows support
Expand Down
20 changes: 20 additions & 0 deletions internal/core/labels.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package core

import (
"errors"
"fmt"
"strings"

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

Expand All @@ -21,3 +25,19 @@ func DefaultLabels(sessionID string) map[string]string {
LabelVersion: internal.Version,
}
}

// MergeCustomLabels sets labels from src to dst.
// If a key in src has [LabelBase] prefix returns an error.
// If dst is nil returns an error.
func MergeCustomLabels(dst, src map[string]string) error {
if dst == nil {
return errors.New("destination map is nil")
}
for key, value := range src {
if strings.HasPrefix(key, LabelBase) {
return fmt.Errorf("key %q has %q prefix", key, LabelBase)
}
dst[key] = value
}
return nil
}
34 changes: 34 additions & 0 deletions internal/core/labels_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package core

import (
"testing"

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

func TestMergeCustomLabels(t *testing.T) {
t.Run("success", func(t *testing.T) {
dst := map[string]string{"A": "1", "B": "2"}
src := map[string]string{"B": "X", "C": "3"}

err := MergeCustomLabels(dst, src)
require.NoError(t, err)
require.Equal(t, map[string]string{"A": "1", "B": "X", "C": "3"}, dst)
})

t.Run("invalid-prefix", func(t *testing.T) {
dst := map[string]string{"A": "1", "B": "2"}
src := map[string]string{"B": "X", LabelLang: "go"}

err := MergeCustomLabels(dst, src)

require.EqualError(t, err, `key "org.testcontainers.lang" has "org.testcontainers" prefix`)
require.Equal(t, map[string]string{"A": "1", "B": "X"}, dst)
})

t.Run("nil-destination", func(t *testing.T) {
src := map[string]string{"A": "1"}
err := MergeCustomLabels(nil, src)
require.Error(t, err)
})
}
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ nav:
- modules/cockroachdb.md
- modules/consul.md
- modules/couchbase.md
- modules/databend.md
- modules/dolt.md
- modules/elasticsearch.md
- modules/gcloud.md
Expand Down
5 changes: 2 additions & 3 deletions modules/consul/consul_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"testing"

capi "github.com/hashicorp/consul/api"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/testcontainers/testcontainers-go"
Expand Down Expand Up @@ -47,11 +46,11 @@ func TestConsul(t *testing.T) {
// Check if API is up
host, err := ctr.ApiEndpoint(ctx)
require.NoError(t, err)
assert.NotEmpty(t, len(host))
require.NotEmpty(t, host)

res, err := http.Get("http://" + host)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, res.StatusCode)
require.Equal(t, http.StatusOK, res.StatusCode)

cfg := capi.DefaultConfig()
cfg.Address = host
Expand Down
5 changes: 5 additions & 0 deletions modules/databend/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include ../../commons-test.mk

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

import (
"context"
"errors"
"fmt"
"strings"

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

const (
databendUser = "databend"
defaultUser = "databend"
defaultPassword = "databend"
defaultDatabaseName = "default"
)

// Container represents the Databend container type used in the module
type Container struct {
*testcontainers.DockerContainer
username string
password string
database string
}

var _ testcontainers.RequestCustomizer = (*DatabendOption)(nil)

// DatabendOption is an option for the Databend container.
type DatabendOption func(*Container)

// Customize is a NOOP. It's defined to satisfy the testcontainers.ContainerCustomizer interface.
func (o DatabendOption) Customize(*testcontainers.Request) error {
// NOOP to satisfy interface.
return nil
}

// Run creates an instance of the Databend container type
func Run(ctx context.Context, img string, opts ...testcontainers.RequestCustomizer) (*Container, error) {
req := testcontainers.Request{
Image: img,
ExposedPorts: []string{"8000/tcp"},
Env: map[string]string{
"QUERY_DEFAULT_USER": defaultUser,
"QUERY_DEFAULT_PASSWORD": defaultPassword,
},
WaitingFor: wait.ForListeningPort("8000/tcp"),
Started: true,
}

for _, opt := range opts {
if err := opt.Customize(&req); err != nil {
return nil, err
}
}

username := req.Env["QUERY_DEFAULT_USER"]
password := req.Env["QUERY_DEFAULT_PASSWORD"]
if password == "" && username == "" {
return nil, errors.New("empty password and user")
}

container, err := testcontainers.Run(ctx, req)
var c *Container
if container != nil {
c = &Container{
DockerContainer: container,
password: password,
username: username,
database: defaultDatabaseName,
}
}

if err != nil {
return c, fmt.Errorf("generic container: %w", err)
}

return c, nil
}

// MustConnectionString panics if the address cannot be determined.
func (c *Container) MustConnectionString(ctx context.Context, args ...string) string {
addr, err := c.ConnectionString(ctx, args...)
if err != nil {
panic(err)
}
return addr
}

func (c *Container) ConnectionString(ctx context.Context, args ...string) (string, error) {
containerPort, err := c.MappedPort(ctx, "8000/tcp")
if err != nil {
return "", fmt.Errorf("mapped port: %w", err)
}

host, err := c.Host(ctx)
if err != nil {
return "", err
}

extraArgs := ""
if len(args) > 0 {
extraArgs = "?" + strings.Join(args, "&")
}
if c.database == "" {
return "", errors.New("database name is empty")
}

// databend://databend:databend@localhost:8000/default?sslmode=disable
connectionString := fmt.Sprintf("databend://%s:%s@%s:%s/%s%s", c.username, c.password, host, containerPort.Port(), c.database, extraArgs)
return connectionString, nil
}

// WithUsername sets the username for the Databend container.
// WithUsername is [Run] option that configures the default query user by setting
// the `QUERY_DEFAULT_USER` container environment variable.
func WithUsername(username string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.Request) error {
req.Env["QUERY_DEFAULT_USER"] = username
return nil
}
}

// WithPassword sets the password for the Databend container.
func WithPassword(password string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.Request) error {
req.Env["QUERY_DEFAULT_PASSWORD"] = password
return nil
}
}
Loading

0 comments on commit 1a9498b

Please sign in to comment.