Skip to content

Commit

Permalink
Merge pull request #21 from GokselKUCUKSAHIN/feature/testcontainers-i…
Browse files Browse the repository at this point in the history
…ntegration

Add elasticsearch testcontainers integration
  • Loading branch information
bayraktugrul authored Sep 1, 2024
2 parents 1c8252f + 64d835e commit 31f7a13
Show file tree
Hide file tree
Showing 8 changed files with 653 additions and 0 deletions.
6 changes: 6 additions & 0 deletions internal/testing/constants/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package constants

const (
Zero = 0
True = "true"
)
84 changes: 84 additions & 0 deletions internal/testing/container/elasticsearch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package container

import (
"context"
"fmt"
"runtime"

"github.com/docker/go-connections/nat"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)

const (
ElasticsearchImage = "docker.elastic.co/elasticsearch/elasticsearch:8.15.0"
defaultPort = "9200"
)

type ElasticsearchContainer struct {
address string
ip string
port nat.Port
container testcontainers.Container
containerRequest testcontainers.ContainerRequest
}

func NewContainer(image string) *ElasticsearchContainer {
req := testcontainers.ContainerRequest{
Image: image,
ExposedPorts: []string{fmt.Sprintf("%s:%s", defaultPort, defaultPort)},
Env: map[string]string{
"cluster.name": "testcontainers-go",
"discovery.type": "single-node",
"bootstrap.memory_lock": "true",
"xpack.security.enabled": "false", // Disable security features (including TLS)
"xpack.security.http.ssl.enabled": "false", // Disable HTTPS for the HTTP API
"ES_JAVA_OPTS": "-Xms1g -Xmx1g",
},
WaitingFor: wait.ForLog("up and running"),
}
return &ElasticsearchContainer{
containerRequest: req,
}
}

func (c *ElasticsearchContainer) Run() (err error) {
c.container, err = testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
ContainerRequest: c.containerRequest,
Started: true,
})
if err != nil {
return err
}

c.ip, err = c.container.Host(context.Background())
if err != nil {
return err
}
c.port, err = c.container.MappedPort(context.Background(), defaultPort)
if err != nil {
return err
}

if isRunningOnOSX() {
c.ip = "127.0.0.1"
}

return nil
}

func (c *ElasticsearchContainer) TerminateContainer() (err error) {
if c.container != nil {
return c.container.Terminate(context.Background())
}

return nil
}

func (c *ElasticsearchContainer) Host() string {
return fmt.Sprintf("http://%s:%s", c.ip, c.port.Port())
}

func isRunningOnOSX() bool {
return runtime.GOOS == "darwin"
}
108 changes: 108 additions & 0 deletions internal/testing/elasticsearch_repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package testing

import (
"context"
"encoding/json"
"fmt"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
"integration-tests/constants"
"net/http"
"strings"
)

type elasticsearchRepository struct {
client *elasticsearch.Client
}

type ElasticsearchRepository interface {
Search(index, query string) ([]FooDocument, error)
Insert(indexName, docId, document string) error
Delete(indexName, docId string) error
DeleteByQuery(indexName, query string) error
}

func NewElasticsearchRepository(client *elasticsearch.Client) ElasticsearchRepository {
return &elasticsearchRepository{client: client}
}

func (e *elasticsearchRepository) Search(index, query string) ([]FooDocument, error) {
res, err := e.client.Search(
e.client.Search.WithIndex(index),
e.client.Search.WithBody(strings.NewReader(query)),
)
defer func() {
if err = res.Body.Close(); err != nil {
panic(err)
}
}()
if err != nil {
return nil, fmt.Errorf("failed to execute search request: %w", err)
}
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code %d: %s", res.StatusCode, res.String())
}

var searchResponse SearchResponse
if err = json.NewDecoder(res.Body).Decode(&searchResponse); err != nil {
return nil, fmt.Errorf("failed to decode search response: %w", err)
}
if len(searchResponse.Hits.Hits) == constants.Zero {
return nil, nil
}

result := make([]FooDocument, 0)
for i := range searchResponse.Hits.Hits {
result = append(result, searchResponse.Hits.Hits[i].Source)
}

return result, nil
}

func (e *elasticsearchRepository) Insert(indexName, docId, document string) error {
request := esapi.IndexRequest{
Index: indexName,
DocumentID: docId,
Body: strings.NewReader(document),
Refresh: constants.True,
}

res, err := request.Do(context.Background(), e.client)
if err != nil {
return fmt.Errorf("failed to execute insert request: %w", err)
}
if res.IsError() {
return fmt.Errorf("insert request returned error: %s", res.String())
}
return err
}

func (e *elasticsearchRepository) Delete(indexName, docId string) error {
request := esapi.DeleteRequest{
Index: indexName,
DocumentID: docId,
}
res, err := request.Do(context.Background(), e.client)
if err != nil {
return fmt.Errorf("failed to execute insert request: %w", err)
}
if res.IsError() {
return fmt.Errorf("insert request returned error: %s", res.String())
}
return err
}

func (e *elasticsearchRepository) DeleteByQuery(indexName, query string) error {
request := esapi.DeleteByQueryRequest{
Index: []string{indexName},
Body: strings.NewReader(query),
}
res, err := request.Do(context.Background(), e.client)
if err != nil {
return fmt.Errorf("failed to execute insert request: %w", err)
}
if res.IsError() {
return fmt.Errorf("insert request returned error: %s", res.String())
}
return err
}
63 changes: 63 additions & 0 deletions internal/testing/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
module integration-tests

go 1.22

replace github.com/GokselKUCUKSAHIN/es-query-builder => ./../..

require (
github.com/GokselKUCUKSAHIN/es-query-builder v0.2.0
github.com/docker/go-connections v0.5.0
github.com/elastic/elastic-transport-go/v8 v8.6.0
github.com/elastic/go-elasticsearch/v8 v8.15.0
github.com/stretchr/testify v1.9.0
github.com/testcontainers/testcontainers-go v0.33.0
)

require (
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/containerd/containerd v1.7.18 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/docker v27.1.1+incompatible // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/kr/text v0.1.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/shirou/gopsutil/v3 v3.23.12 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/sys v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit 31f7a13

Please sign in to comment.