From 6114050c9b081129dc5e08a23d54e634a796d2d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 9 Oct 2025 17:33:46 +0200 Subject: [PATCH] chore(yugabytedb): use Run function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit migrates the yugabytedb module to use the new testcontainers.Run() API. The main changes are: - Use testcontainers.Run() instead of testcontainers.GenericContainer() - Convert to moduleOpts pattern with functional options - Use WithCmd, WithWaitStrategy, WithExposedPorts, WithEnv - Use Inspect after Run to retrieve actual env var values after user customizations - Multiple wait strategies for logs and listening ports Tests: 9 tests, 93.0% coverage Ref: #3174 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- modules/yugabytedb/yugabytedb.go | 61 +++++++++++++++++++------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/modules/yugabytedb/yugabytedb.go b/modules/yugabytedb/yugabytedb.go index 8a49d7fb0d..fb5035f7f8 100644 --- a/modules/yugabytedb/yugabytedb.go +++ b/modules/yugabytedb/yugabytedb.go @@ -49,50 +49,61 @@ type Container struct { // [*Container.YSQLConnectionString] and [*Container.YCQLConfigureClusterConfig] // methods to use the container in their respective clients. func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) { - req := testcontainers.ContainerRequest{ - Image: img, - Cmd: []string{"bin/yugabyted", "start", "--background=false"}, - WaitingFor: wait.ForAll( + moduleOpts := []testcontainers.ContainerCustomizer{ + testcontainers.WithCmd("bin/yugabyted", "start", "--background=false"), + testcontainers.WithWaitStrategy( wait.ForLog("YugabyteDB Started").WithOccurrence(1), wait.ForLog("Data placement constraint successfully verified").WithOccurrence(1), wait.ForListeningPort(ysqlPort), wait.ForListeningPort(ycqlPort), ), - ExposedPorts: []string{ycqlPort, ysqlPort}, - Env: map[string]string{ + testcontainers.WithExposedPorts(ycqlPort, ysqlPort), + testcontainers.WithEnv(map[string]string{ ycqlKeyspaceEnv: ycqlKeyspace, ycqlUserNameEnv: ycqlUserName, ycqlPasswordEnv: ycqlPassword, ysqlDatabaseNameEnv: ysqlDatabaseName, ysqlDatabaseUserEnv: ysqlDatabaseUser, ysqlDatabasePasswordEnv: ysqlDatabasePassword, - }, + }), } - genericContainerReq := testcontainers.GenericContainerRequest{ - ContainerRequest: req, - Started: true, - } - - for _, opt := range opts { - if err := opt.Customize(&genericContainerReq); err != nil { - return nil, fmt.Errorf("customize: %w", err) - } - } - - container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + ctr, err := testcontainers.Run(ctx, img, append(moduleOpts, opts...)...) var c *Container - if container != nil { + if ctr != nil { c = &Container{ - Container: container, - ysqlDatabaseName: req.Env[ysqlDatabaseNameEnv], - ysqlDatabaseUser: req.Env[ysqlDatabaseUserEnv], - ysqlDatabasePassword: req.Env[ysqlDatabasePasswordEnv], + Container: ctr, + ysqlDatabaseName: ysqlDatabaseName, + ysqlDatabaseUser: ysqlDatabaseUser, + ysqlDatabasePassword: ysqlDatabasePassword, } } if err != nil { - return c, fmt.Errorf("generic container: %w", err) + return c, fmt.Errorf("run yugabytedb: %w", err) + } + + // Inspect the container to get the actual env var values after user customizations + inspect, err := ctr.Inspect(ctx) + if err != nil { + return c, fmt.Errorf("inspect yugabytedb: %w", err) + } + + var foundName, foundUser, foundPassword bool + for _, env := range inspect.Config.Env { + if v, ok := strings.CutPrefix(env, ysqlDatabaseNameEnv+"="); ok { + c.ysqlDatabaseName, foundName = v, true + } + if v, ok := strings.CutPrefix(env, ysqlDatabaseUserEnv+"="); ok { + c.ysqlDatabaseUser, foundUser = v, true + } + if v, ok := strings.CutPrefix(env, ysqlDatabasePasswordEnv+"="); ok { + c.ysqlDatabasePassword, foundPassword = v, true + } + + if foundName && foundUser && foundPassword { + break + } } return c, nil