diff --git a/modules/opensearch/opensearch.go b/modules/opensearch/opensearch.go index 09b54759ba..b2e400f0f9 100644 --- a/modules/opensearch/opensearch.go +++ b/modules/opensearch/opensearch.go @@ -35,17 +35,29 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize // Run creates an instance of the OpenSearch container type func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*OpenSearchContainer, error) { - req := testcontainers.ContainerRequest{ - Image: img, - ExposedPorts: []string{defaultHTTPPort, "9600/tcp"}, - Env: map[string]string{ + // Gather all config options (defaults and then apply provided options) + settings := defaultOptions() + for _, opt := range opts { + if apply, ok := opt.(Option); ok { + if err := apply(settings); err != nil { + return nil, fmt.Errorf("apply option: %w", err) + } + } + } + + username := settings.Username + password := settings.Password + + moduleOpts := []testcontainers.ContainerCustomizer{ + testcontainers.WithEnv(map[string]string{ "discovery.type": "single-node", "DISABLE_INSTALL_DEMO_CONFIG": "true", "DISABLE_SECURITY_PLUGIN": "true", - "OPENSEARCH_USERNAME": defaultUsername, - "OPENSEARCH_PASSWORD": defaultPassword, - }, - HostConfigModifier: func(hc *container.HostConfig) { + "OPENSEARCH_USERNAME": username, + "OPENSEARCH_PASSWORD": password, + }), + testcontainers.WithExposedPorts(defaultHTTPPort, "9600/tcp"), + testcontainers.WithHostConfigModifier(func(hc *container.HostConfig) { hc.Ulimits = []*units.Ulimit{ { Name: "memlock", @@ -58,73 +70,47 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom Hard: 65536, }, } - }, - } - - genericContainerReq := testcontainers.GenericContainerRequest{ - ContainerRequest: req, - Started: true, - } - - // Gather all config options (defaults and then apply provided options) - settings := defaultOptions() - for _, opt := range opts { - if apply, ok := opt.(Option); ok { - apply(settings) - } - if err := opt.Customize(&genericContainerReq); err != nil { - return nil, err - } - } - - // set credentials if they are provided, otherwise use the defaults - if settings.Username != "" { - genericContainerReq.Env["OPENSEARCH_USERNAME"] = settings.Username + }), + // the wait strategy does not support TLS at the moment, + // so we need to disable it in the strategy for now. + testcontainers.WithWaitStrategy(wait.ForHTTP("/"). + WithPort("9200"). + WithTLS(false). + WithStartupTimeout(120*time.Second). + WithStatusCodeMatcher(func(status int) bool { + return status == 200 + }). + WithBasicAuth(username, password). + WithResponseMatcher(func(body io.Reader) bool { + bs, err := io.ReadAll(body) + if err != nil { + return false + } + + type response struct { + Tagline string `json:"tagline"` + } + + var r response + err = json.Unmarshal(bs, &r) + if err != nil { + return false + } + + return r.Tagline == "The OpenSearch Project: https://opensearch.org/" + })), } - if settings.Password != "" { - genericContainerReq.Env["OPENSEARCH_PASSWORD"] = settings.Password - } - - username := genericContainerReq.Env["OPENSEARCH_USERNAME"] - password := genericContainerReq.Env["OPENSEARCH_PASSWORD"] - - // the wat strategy does not support TLS at the moment, - // so we need to disable it in the strategy for now. - genericContainerReq.WaitingFor = wait.ForHTTP("/"). - WithPort("9200"). - WithTLS(false). - WithStartupTimeout(120*time.Second). - WithStatusCodeMatcher(func(status int) bool { - return status == 200 - }). - WithBasicAuth(username, password). - WithResponseMatcher(func(body io.Reader) bool { - bs, err := io.ReadAll(body) - if err != nil { - return false - } - - type response struct { - Tagline string `json:"tagline"` - } - - var r response - err = json.Unmarshal(bs, &r) - if err != nil { - return false - } - return r.Tagline == "The OpenSearch Project: https://opensearch.org/" - }) + moduleOpts = append(moduleOpts, opts...) - container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + ctr, err := testcontainers.Run(ctx, img, moduleOpts...) var c *OpenSearchContainer - if container != nil { - c = &OpenSearchContainer{Container: container, User: username, Password: password} + if ctr != nil { + c = &OpenSearchContainer{Container: ctr, User: username, Password: password} } if err != nil { - return c, fmt.Errorf("generic container: %w", err) + return c, fmt.Errorf("run opensearch: %w", err) } return c, nil diff --git a/modules/opensearch/options.go b/modules/opensearch/options.go index f1223762a3..94f793b252 100644 --- a/modules/opensearch/options.go +++ b/modules/opensearch/options.go @@ -19,7 +19,7 @@ func defaultOptions() *Options { var _ testcontainers.ContainerCustomizer = (*Option)(nil) // Option is an option for the OpenSearch container. -type Option func(*Options) +type Option func(*Options) error // Customize is a NOOP. It's defined to satisfy the testcontainers.ContainerCustomizer interface. func (o Option) Customize(*testcontainers.GenericContainerRequest) error { @@ -29,14 +29,16 @@ func (o Option) Customize(*testcontainers.GenericContainerRequest) error { // WithPassword sets the password for the OpenSearch container. func WithPassword(password string) Option { - return func(o *Options) { + return func(o *Options) error { o.Password = password + return nil } } // WithUsername sets the username for the OpenSearch container. func WithUsername(username string) Option { - return func(o *Options) { + return func(o *Options) error { o.Username = username + return nil } }