diff --git a/modules/azure/eventhubs/eventhubs.go b/modules/azure/eventhubs/eventhubs.go index fda5bae85f..03235c97c9 100644 --- a/modules/azure/eventhubs/eventhubs.go +++ b/modules/azure/eventhubs/eventhubs.go @@ -68,17 +68,7 @@ func (c *Container) Terminate(ctx context.Context, opts ...testcontainers.Termin // Run creates an instance of the Azure Event Hubs container type func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) { - moduleOpts := []testcontainers.ContainerCustomizer{ - testcontainers.WithExposedPorts(defaultAMPQPort, defaultHTTPPort), - testcontainers.WithWaitStrategy(wait.ForAll( - wait.ForListeningPort(defaultAMPQPort), - wait.ForListeningPort(defaultHTTPPort), - wait.ForHTTP("/health").WithPort(defaultHTTPPort).WithStatusCodeMatcher(func(status int) bool { - return status == http.StatusOK - }), - )), - } - + // Process custom options first to extract settings defaultOptions := defaultOptions() for _, opt := range opts { if o, ok := opt.(Option); ok { @@ -90,6 +80,18 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom c := &Container{azuriteOptions: &defaultOptions} + // Build moduleOpts with defaults + moduleOpts := []testcontainers.ContainerCustomizer{ + testcontainers.WithExposedPorts(defaultAMPQPort, defaultHTTPPort), + testcontainers.WithWaitStrategy(wait.ForAll( + wait.ForListeningPort(defaultAMPQPort), + wait.ForListeningPort(defaultHTTPPort), + wait.ForHTTP("/health").WithPort(defaultHTTPPort).WithStatusCodeMatcher(func(status int) bool { + return status == http.StatusOK + }), + )), + } + if defaultOptions.azuriteContainer == nil { azuriteNetwork, err := network.New(ctx) if err != nil { diff --git a/modules/azure/servicebus/servicebus.go b/modules/azure/servicebus/servicebus.go index 45c3ac8698..0a48ad0c9e 100644 --- a/modules/azure/servicebus/servicebus.go +++ b/modules/azure/servicebus/servicebus.go @@ -73,6 +73,19 @@ func (c *Container) Terminate(ctx context.Context, opts ...testcontainers.Termin // Run creates an instance of the Azure ServiceBus container type func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) { + // Process custom options first to extract settings + defaultOptions := defaultOptions() + for _, opt := range opts { + if o, ok := opt.(Option); ok { + if err := o(&defaultOptions); err != nil { + return nil, fmt.Errorf("servicebus option: %w", err) + } + } + } + + c := &Container{mssqlOptions: &defaultOptions} + + // Build moduleOpts with defaults moduleOpts := []testcontainers.ContainerCustomizer{ testcontainers.WithExposedPorts(defaultPort, defaultHTTPPort), testcontainers.WithEnv(map[string]string{ @@ -87,17 +100,6 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom )), } - defaultOptions := defaultOptions() - for _, opt := range opts { - if o, ok := opt.(Option); ok { - if err := o(&defaultOptions); err != nil { - return nil, fmt.Errorf("servicebus option: %w", err) - } - } - } - - c := &Container{mssqlOptions: &defaultOptions} - if defaultOptions.mssqlContainer == nil { mssqlNetwork, err := network.New(ctx) if err != nil { diff --git a/modules/couchbase/couchbase.go b/modules/couchbase/couchbase.go index 6c558be517..5d46a2cd24 100644 --- a/modules/couchbase/couchbase.go +++ b/modules/couchbase/couchbase.go @@ -72,19 +72,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom indexStorageMode: MemoryOptimized, } - moduleOpts := []testcontainers.ContainerCustomizer{ - testcontainers.WithExposedPorts(MGMT_PORT+"/tcp", MGMT_SSL_PORT+"/tcp"), - } - - serviceCustomizers := make([]testcontainers.ContainerCustomizer, 0, len(initialServices)) + // Process custom options first to extract config + // Start with initial services + allCustomizers := make([]testcontainers.ContainerCustomizer, 0, len(initialServices)+len(opts)) for _, srv := range initialServices { - serviceCustomizers = append(serviceCustomizers, withService(srv)) + allCustomizers = append(allCustomizers, withService(srv)) } + allCustomizers = append(allCustomizers, opts...) - serviceCustomizers = append(serviceCustomizers, opts...) - - // transfer options to the config - for _, opt := range serviceCustomizers { + // Transfer custom options to the config + for _, opt := range allCustomizers { if bucketCustomizer, ok := opt.(bucketCustomizer); ok { // If the option is a bucketCustomizer, we need to add the buckets to the request config.buckets = append(config.buckets, bucketCustomizer.buckets...) @@ -100,12 +97,18 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom config.password = credentialsCustomizer.password if len(credentialsCustomizer.password) < 6 { - return nil, errors.New("admin password must be at most 6 characters long") + return nil, errors.New("admin password must be at least 6 characters long") } } } - moduleOpts = append(moduleOpts, serviceCustomizers...) + // Build moduleOpts with defaults + moduleOpts := []testcontainers.ContainerCustomizer{ + testcontainers.WithExposedPorts(MGMT_PORT+"/tcp", MGMT_SSL_PORT+"/tcp"), + } + + // Append all customizers (initial services + user opts) + moduleOpts = append(moduleOpts, allCustomizers...) ctr, err := testcontainers.Run(ctx, img, moduleOpts...) var couchbaseContainer *CouchbaseContainer diff --git a/modules/dockermcpgateway/dockermcpgateway.go b/modules/dockermcpgateway/dockermcpgateway.go index 40aa7ad8b0..799c675c20 100644 --- a/modules/dockermcpgateway/dockermcpgateway.go +++ b/modules/dockermcpgateway/dockermcpgateway.go @@ -27,19 +27,7 @@ type Container struct { func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) { dockerHostMount := core.MustExtractDockerSocket(ctx) - moduleOpts := []testcontainers.ContainerCustomizer{ - testcontainers.WithExposedPorts(defaultPort), - testcontainers.WithHostConfigModifier(func(hc *container.HostConfig) { - hc.Binds = []string{ - dockerHostMount + ":/var/run/docker.sock", - } - }), - testcontainers.WithWaitStrategy(wait.ForAll( - wait.ForListeningPort(defaultPort), - wait.ForLog(".*Start sse server on port.*").AsRegexp(), - )), - } - + // Process custom options first to extract settings settings := defaultOptions() for _, opt := range opts { if apply, ok := opt.(Option); ok { @@ -56,6 +44,21 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom cmds = append(cmds, "--tools="+tool) } } + + // Build moduleOpts with defaults + moduleOpts := []testcontainers.ContainerCustomizer{ + testcontainers.WithExposedPorts(defaultPort), + testcontainers.WithHostConfigModifier(func(hc *container.HostConfig) { + hc.Binds = []string{ + dockerHostMount + ":/var/run/docker.sock", + } + }), + testcontainers.WithWaitStrategy(wait.ForAll( + wait.ForListeningPort(defaultPort), + wait.ForLog(".*Start sse server on port.*").AsRegexp(), + )), + } + if len(settings.secrets) > 0 { cmds = append(cmds, "--secrets="+secretsPath) @@ -73,7 +76,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom moduleOpts = append(moduleOpts, testcontainers.WithCmd(cmds...)) - // append user-defined options + // Append user options moduleOpts = append(moduleOpts, opts...) container, err := testcontainers.Run(ctx, img, moduleOpts...) diff --git a/modules/etcd/etcd.go b/modules/etcd/etcd.go index 145646ad60..73989ce157 100644 --- a/modules/etcd/etcd.go +++ b/modules/etcd/etcd.go @@ -60,12 +60,7 @@ func (c *EtcdContainer) Terminate(ctx context.Context, opts ...testcontainers.Te // Run creates an instance of the etcd container type func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*EtcdContainer, error) { - moduleOpts := []testcontainers.ContainerCustomizer{ - testcontainers.WithExposedPorts(clientPort, peerPort), - } - - moduleOpts = append(moduleOpts, opts...) - + // Process custom options first to extract settings settings := defaultOptions() for _, opt := range opts { if apply, ok := opt.(Option); ok { @@ -80,6 +75,14 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom return nil, fmt.Errorf("configure cluster: %w", err) } + // Build moduleOpts with defaults + moduleOpts := []testcontainers.ContainerCustomizer{ + testcontainers.WithExposedPorts(clientPort, peerPort), + } + + // Append user options + moduleOpts = append(moduleOpts, opts...) + // configure CMD with the nodes moduleOpts = append(moduleOpts, testcontainers.WithCmd(configureCMD(settings)...)) diff --git a/modules/gcloud/firestore/firestore.go b/modules/gcloud/firestore/firestore.go index 5b7b1a7742..ebcfbd0c0b 100644 --- a/modules/gcloud/firestore/firestore.go +++ b/modules/gcloud/firestore/firestore.go @@ -34,14 +34,7 @@ func (c *Container) URI() string { // Run creates an instance of the Firestore GCloud container type. // The URI uses the empty string as the protocol. func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) { - moduleOpts := []testcontainers.ContainerCustomizer{ - testcontainers.WithExposedPorts(defaultPort), - testcontainers.WithWaitStrategy(wait.ForAll( - wait.ForListeningPort(defaultPort), - wait.ForLog("running"), - )), - } - + // Process custom options first to extract settings settings := defaultOptions() for _, opt := range opts { if apply, ok := opt.(Option); ok { @@ -56,12 +49,21 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom gcloudParameters += " --database-mode=datastore-mode" } - moduleOpts = append(moduleOpts, testcontainers.WithCmd( - "/bin/sh", - "-c", - "gcloud beta emulators firestore start --host-port 0.0.0.0:"+defaultPortNumber+" "+gcloudParameters, - )) + // Build moduleOpts with defaults + moduleOpts := []testcontainers.ContainerCustomizer{ + testcontainers.WithExposedPorts(defaultPort), + testcontainers.WithWaitStrategy(wait.ForAll( + wait.ForListeningPort(defaultPort), + wait.ForLog("running"), + )), + testcontainers.WithCmd( + "/bin/sh", + "-c", + "gcloud beta emulators firestore start --host-port 0.0.0.0:"+defaultPortNumber+" "+gcloudParameters, + ), + } + // Append user options moduleOpts = append(moduleOpts, opts...) ctr, err := testcontainers.Run(ctx, img, moduleOpts...)