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

Add username and password functions to mongodb #1910

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 43 additions & 1 deletion modules/mongodb/mongodb.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package mongodb

import (
"context"
"fmt"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
Expand All @@ -13,6 +14,8 @@ const defaultImage = "mongo:6"
// MongoDBContainer represents the MongoDB container type used in the module
type MongoDBContainer struct {
testcontainers.Container
username string
password string
}

// RunContainer creates an instance of the MongoDB container type
Expand All @@ -24,6 +27,7 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize
wait.ForLog("Waiting for connections"),
wait.ForListeningPort("27017/tcp"),
),
Env: map[string]string{},
}

genericContainerReq := testcontainers.GenericContainerRequest{
Expand All @@ -34,16 +38,54 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize
for _, opt := range opts {
opt.Customize(&genericContainerReq)
}
username := req.Env["MONGO_INITDB_ROOT_USERNAME"]
password := req.Env["MONGO_INITDB_ROOT_PASSWORD"]
if username != "" && password == "" || username == "" && password != "" {
return nil, fmt.Errorf("if you specify username or password, you must provide both of them")
}

container, err := testcontainers.GenericContainer(ctx, genericContainerReq)
if err != nil {
return nil, err
}

if username != "" && password != "" {
return &MongoDBContainer{Container: container, username: username, password: password}, nil
}
ugrkm marked this conversation as resolved.
Show resolved Hide resolved
return &MongoDBContainer{Container: container}, nil
}

// ConnectionString returns the connection string for the MongoDB container
// WithUsername sets the initial username to be created when the container starts
// It is used in conjunction with WithPassword to set a username and its password.
// It will create the specified user with superuser power.
func WithUsername(username string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.GenericContainerRequest) {
req.Env["MONGO_INITDB_ROOT_USERNAME"] = username
}
}

// WithPassword sets the initial password of the user to be created when the container starts
// It is used in conjunction with WithUsername to set a username and its password.
// This environment variable sets the superuser password for MongoDB.
func WithPassword(password string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.GenericContainerRequest) {
req.Env["MONGO_INITDB_ROOT_PASSWORD"] = password
}
}

// ConnectionString returns the connection string for the MongoDB container.
// If you provide a username and a password, the connection string will also include them.
func (c *MongoDBContainer) ConnectionString(ctx context.Context) (string, error) {
host, err := c.Host(ctx)
if err != nil {
return "", err
}
port, err := c.MappedPort(ctx, "27017/tcp")
if err != nil {
return "", err
}
if c.username != "" && c.password != "" {
return fmt.Sprintf("mongodb://%s:%s@%s:%s", c.username, c.password, host, port.Port()), nil
}
return c.Endpoint(ctx, "mongodb")
}
42 changes: 42 additions & 0 deletions modules/mongodb/mongodb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package mongodb_test
import (
"context"
"fmt"
"strings"

"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"

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

func ExampleRunContainer() {
Expand Down Expand Up @@ -76,3 +78,43 @@ func ExampleRunContainer_connect() {
// Output:
// test
}

func ExampleRunContainer_withCredentials() {
ctx := context.Background()

container, err := mongodb.RunContainer(ctx,
testcontainers.WithImage("mongo:6"),
mongodb.WithUsername("root"),
mongodb.WithPassword("password"),
testcontainers.WithWaitStrategy(wait.ForLog("Waiting for connections")),
)
if err != nil {
panic(err)
}

// Clean up the container
defer func() {
if err := container.Terminate(ctx); err != nil {
panic(err)
}
}()

connStr, err := container.ConnectionString(ctx)
if err != nil {
panic(err)
ugrkm marked this conversation as resolved.
Show resolved Hide resolved
}

mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(connStr))
if err != nil {
panic(err)
ugrkm marked this conversation as resolved.
Show resolved Hide resolved
}

err = mongoClient.Ping(ctx, nil)
if err != nil {
panic(err)
ugrkm marked this conversation as resolved.
Show resolved Hide resolved
}
ugrkm marked this conversation as resolved.
Show resolved Hide resolved
fmt.Println(strings.Split(connStr, "@")[0])

// Output:
// mongodb://root:password
}