forked from testcontainers/testcontainers-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support databend module (testcontainers#2779)
* feat: support databend module * chore: add project scaffolding * chore: more file * chore: run make lint * fix: proper pinned version * fix comment * add the detail documents * Update modules/databend/databend.go Co-authored-by: Steven Hartland <[email protected]> * fix review comment * fix * default database * Update modules/databend/databend_test.go Co-authored-by: Steven Hartland <[email protected]> * fix review comments * Update modules/databend/databend.go Co-authored-by: Steven Hartland <[email protected]> * Update modules/databend/databend.go Co-authored-by: Steven Hartland <[email protected]> * fix comment * fix databend-go module * fix databend tests * fix golangci-lint * Update modules/databend/databend.go Co-authored-by: Steven Hartland <[email protected]> * remove WithDatabase * fix * chore: rollback pinned version We'll tackle that in a separate PR --------- Co-authored-by: Manuel de la Peña <[email protected]> Co-authored-by: Steven Hartland <[email protected]> Co-authored-by: Manuel de la Peña <[email protected]>
- Loading branch information
1 parent
fca9698
commit c1bb0bb
Showing
11 changed files
with
643 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
include ../../commons-test.mk | ||
|
||
.PHONY: test | ||
test: | ||
$(MAKE) test-databend |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
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" | ||
) | ||
|
||
// DatabendContainer represents the Databend container type used in the module | ||
type DatabendContainer struct { | ||
testcontainers.Container | ||
username string | ||
password string | ||
database string | ||
} | ||
|
||
var _ testcontainers.ContainerCustomizer = (*DatabendOption)(nil) | ||
|
||
// DatabendOption is an option for the Databend container. | ||
type DatabendOption func(*DatabendContainer) | ||
|
||
// Customize is a NOOP. It's defined to satisfy the testcontainers.ContainerCustomizer interface. | ||
func (o DatabendOption) Customize(*testcontainers.GenericContainerRequest) 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.ContainerCustomizer) (*DatabendContainer, error) { | ||
req := testcontainers.ContainerRequest{ | ||
Image: img, | ||
ExposedPorts: []string{"8000/tcp"}, | ||
Env: map[string]string{ | ||
"QUERY_DEFAULT_USER": defaultUser, | ||
"QUERY_DEFAULT_PASSWORD": defaultPassword, | ||
}, | ||
WaitingFor: wait.ForListeningPort("8000/tcp"), | ||
} | ||
|
||
genericContainerReq := testcontainers.GenericContainerRequest{ | ||
ContainerRequest: req, | ||
Started: true, | ||
} | ||
|
||
for _, opt := range opts { | ||
if err := opt.Customize(&genericContainerReq); 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.GenericContainer(ctx, genericContainerReq) | ||
var c *DatabendContainer | ||
if container != nil { | ||
c = &DatabendContainer{ | ||
Container: 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 *DatabendContainer) MustConnectionString(ctx context.Context, args ...string) string { | ||
addr, err := c.ConnectionString(ctx, args...) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return addr | ||
} | ||
|
||
func (c *DatabendContainer) 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.GenericContainerRequest) 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.GenericContainerRequest) error { | ||
req.Env["QUERY_DEFAULT_PASSWORD"] = password | ||
return nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package databend_test | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
"testing" | ||
|
||
_ "github.com/datafuselabs/databend-go" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/testcontainers/testcontainers-go" | ||
"github.com/testcontainers/testcontainers-go/modules/databend" | ||
) | ||
|
||
func TestDatabend(t *testing.T) { | ||
ctx := context.Background() | ||
|
||
ctr, err := databend.Run(ctx, "datafuselabs/databend:v1.2.615") | ||
testcontainers.CleanupContainer(t, ctr) | ||
require.NoError(t, err) | ||
|
||
// perform assertions | ||
// connectionString { | ||
connectionString, err := ctr.ConnectionString(ctx, "sslmode=disable") | ||
// } | ||
require.NoError(t, err) | ||
|
||
mustConnectionString := ctr.MustConnectionString(ctx, "sslmode=disable") | ||
require.Equal(t, connectionString, mustConnectionString) | ||
|
||
db, err := sql.Open("databend", connectionString) | ||
require.NoError(t, err) | ||
defer db.Close() | ||
|
||
err = db.Ping() | ||
require.NoError(t, err) | ||
|
||
_, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + | ||
" `col_1` VARCHAR(128) NOT NULL, \n" + | ||
" `col_2` VARCHAR(128) NOT NULL \n" + | ||
")") | ||
require.NoError(t, err) | ||
} | ||
|
||
func TestDatabendWithDefaultUserAndPassword(t *testing.T) { | ||
ctx := context.Background() | ||
|
||
ctr, err := databend.Run(ctx, | ||
"datafuselabs/databend:v1.2.615", | ||
databend.WithUsername("databend")) | ||
testcontainers.CleanupContainer(t, ctr) | ||
require.NoError(t, err) | ||
|
||
// perform assertions | ||
connectionString, err := ctr.ConnectionString(ctx, "sslmode=disable") | ||
require.NoError(t, err) | ||
|
||
db, err := sql.Open("databend", connectionString) | ||
require.NoError(t, err) | ||
defer db.Close() | ||
err = db.Ping() | ||
require.NoError(t, err) | ||
|
||
var i int | ||
row := db.QueryRow("select 1") | ||
err = row.Scan(&i) | ||
require.NoError(t, err) | ||
|
||
_, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + | ||
" `col_1` VARCHAR(128) NOT NULL, \n" + | ||
" `col_2` VARCHAR(128) NOT NULL \n" + | ||
")") | ||
require.NoError(t, err) | ||
} |
Oops, something went wrong.