Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 54 additions & 68 deletions modules/opensearch/opensearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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
Expand Down
8 changes: 5 additions & 3 deletions modules/opensearch/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
}
Loading