Skip to content

Commit c296209

Browse files
authored
internal/elasticsearch: bug fixes (#104)
1 parent 9a479d9 commit c296209

23 files changed

+238
-260
lines changed

docs/plugins/elasticsearch.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The data source supports the following configuration parameters:
3232
config data elasticsearch {
3333
api_key = <list of string> # optional
3434
api_key_str = <string> # optional
35-
base_url = <string> # required
35+
base_url = <string> # optional
3636
basic_auth_password = <string> # optional
3737
basic_auth_username = <string> # optional
3838
bearer_auth = <string> # optional
@@ -52,5 +52,6 @@ data elasticsearch {
5252
index = <string> # required
5353
query = <map of dynamic> # optional
5454
query_string = <string> # optional
55+
size = <number> # optional
5556
}
5657
```

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ require (
1919
github.com/mattn/go-colorable v0.1.13
2020
github.com/mattn/go-sqlite3 v1.14.20
2121
github.com/pelletier/go-toml/v2 v2.1.1
22-
github.com/sanity-io/litter v1.5.5
2322
github.com/spf13/cobra v1.8.0
2423
github.com/spf13/pflag v1.0.5
2524
github.com/stretchr/testify v1.8.4

go.sum

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHf
3737
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
3838
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
3939
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
40-
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4140
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4241
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4342
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -151,16 +150,13 @@ github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOS
151150
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
152151
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
153152
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
154-
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
155153
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
156154
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
157155
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
158156
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
159157
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
160158
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
161159
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
162-
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
163-
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
164160
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
165161
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
166162
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
@@ -181,7 +177,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
181177
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
182178
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
183179
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
184-
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
185180
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
186181
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
187182
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=

internal/builtin/content_frontmatter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ var frontMatterAllowedFormats = []string{"yaml", "toml", "json"}
2727
func makeFrontMatterContentProvider() *plugin.ContentProvider {
2828
return &plugin.ContentProvider{
2929
ContentFunc: genFrontMatterContent,
30-
Args: &hcldec.ObjectSpec{
30+
Args: hcldec.ObjectSpec{
3131
"format": &hcldec.AttrSpec{
3232
Name: "format",
3333
Type: cty.String,

internal/builtin/content_image.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
func makeImageContentProvider() *plugin.ContentProvider {
1616
return &plugin.ContentProvider{
1717
ContentFunc: genImageContent,
18-
Args: &hcldec.ObjectSpec{
18+
Args: hcldec.ObjectSpec{
1919
"src": &hcldec.AttrSpec{
2020
Name: "src",
2121
Type: cty.String,

internal/builtin/content_list.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ var listAllowedFormats = []string{"unordered", "ordered", "tasklist"}
2626
func makeListContentProvider() *plugin.ContentProvider {
2727
return &plugin.ContentProvider{
2828
ContentFunc: genListContent,
29-
Args: &hcldec.ObjectSpec{
29+
Args: hcldec.ObjectSpec{
3030
"item_template": &hcldec.AttrSpec{
3131
Name: "item_template",
3232
Type: cty.String,

internal/builtin/content_table.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type tableCellTmpl = *template.Template
1919
func makeTableContentProvider() *plugin.ContentProvider {
2020
return &plugin.ContentProvider{
2121
ContentFunc: genTableContent,
22-
Args: &hcldec.ObjectSpec{
22+
Args: hcldec.ObjectSpec{
2323
"columns": &hcldec.AttrSpec{
2424
Name: "columns",
2525
Type: cty.List(cty.Object(map[string]cty.Type{

internal/builtin/content_text.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const (
2828
func makeTextContentProvider() *plugin.ContentProvider {
2929
return &plugin.ContentProvider{
3030
ContentFunc: genTextContent,
31-
Args: &hcldec.ObjectSpec{
31+
Args: hcldec.ObjectSpec{
3232
"text": &hcldec.AttrSpec{
3333
Name: "text",
3434
Type: cty.String,

internal/builtin/data_csv.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ const defaultCSVDelimiter = ','
2020
func makeCSVDataSource() *plugin.DataSource {
2121
return &plugin.DataSource{
2222
DataFunc: fetchCSVData,
23-
Config: &hcldec.ObjectSpec{
23+
Config: hcldec.ObjectSpec{
2424
"delimiter": &hcldec.AttrSpec{
2525
Name: "delimiter",
2626
Type: cty.String,
2727
Required: false,
2828
},
2929
},
30-
Args: &hcldec.ObjectSpec{
30+
Args: hcldec.ObjectSpec{
3131
"path": &hcldec.AttrSpec{
3232
Name: "path",
3333
Type: cty.String,

internal/builtin/data_json.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
func makeJSONDataSource() *plugin.DataSource {
1818
return &plugin.DataSource{
1919
DataFunc: fetchJSONData,
20-
Args: &hcldec.ObjectSpec{
20+
Args: hcldec.ObjectSpec{
2121
"glob": &hcldec.AttrSpec{
2222
Name: "glob",
2323
Type: cty.String,

internal/builtin/data_txt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
func makeTXTDataSource() *plugin.DataSource {
1616
return &plugin.DataSource{
1717
DataFunc: fetchTXTData,
18-
Args: &hcldec.ObjectSpec{
18+
Args: hcldec.ObjectSpec{
1919
"path": &hcldec.AttrSpec{
2020
Name: "path",
2121
Type: cty.String,

internal/elasticsearch/data_elasticsearch.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func makeElasticSearchDataSource() *plugin.DataSource {
1717
"base_url": &hcldec.AttrSpec{
1818
Name: "base_url",
1919
Type: cty.String,
20-
Required: true,
20+
Required: false,
2121
},
2222
"cloud_id": &hcldec.AttrSpec{
2323
Name: "cloud_id",
@@ -55,14 +55,14 @@ func makeElasticSearchDataSource() *plugin.DataSource {
5555
Required: false,
5656
},
5757
},
58-
Args: &hcldec.ObjectSpec{
58+
Args: hcldec.ObjectSpec{
5959
"index": &hcldec.AttrSpec{
6060
Name: "index",
6161
Type: cty.String,
6262
Required: true,
6363
},
6464
"id": &hcldec.AttrSpec{
65-
Name: "index",
65+
Name: "id",
6666
Type: cty.String,
6767
Required: false,
6868
},
@@ -81,6 +81,11 @@ func makeElasticSearchDataSource() *plugin.DataSource {
8181
Type: cty.List(cty.String),
8282
Required: false,
8383
},
84+
"size": &hcldec.AttrSpec{
85+
Name: "size",
86+
Type: cty.Number,
87+
Required: false,
88+
},
8489
},
8590
}
8691
}

internal/elasticsearch/data_elasticsearch_test.go

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import (
1818
"github.com/blackstork-io/fabric/plugin"
1919
)
2020

21-
// ElasticSearchDataTestSuite is a test suite to test integration with real elasticsearch
22-
type ElasticSearchDataTestSuite struct {
21+
// IntegrationTestSuite is a test suite to test integration with real elasticsearch
22+
type IntegrationTestSuite struct {
2323
suite.Suite
2424
container *elasticsearch.ElasticsearchContainer
2525
client *es.Client
@@ -28,14 +28,14 @@ type ElasticSearchDataTestSuite struct {
2828
ctx context.Context
2929
}
3030

31-
func TestElasticSearchDataSuite(t *testing.T) {
31+
func TestIntegrationSuite(t *testing.T) {
3232
if testing.Short() {
3333
t.Skip("skipping integration tests")
3434
}
35-
suite.Run(t, &ElasticSearchDataTestSuite{})
35+
suite.Run(t, &IntegrationTestSuite{})
3636
}
3737

38-
func (s *ElasticSearchDataTestSuite) SetupSuite() {
38+
func (s *IntegrationTestSuite) SetupSuite() {
3939
s.ctx = context.Background()
4040
opts := []testcontainers.ContainerCustomizer{
4141
testcontainers.WithImage("docker.io/elasticsearch:8.9.0"),
@@ -68,7 +68,7 @@ func (s *ElasticSearchDataTestSuite) SetupSuite() {
6868
s.plugin = Plugin("")
6969
}
7070

71-
func (s *ElasticSearchDataTestSuite) TearDownSuite() {
71+
func (s *IntegrationTestSuite) TearDownSuite() {
7272
s.Require().NoError(s.container.Terminate(s.ctx), "failed to stop elasticsearch container")
7373
}
7474

@@ -80,7 +80,7 @@ type testDataObject struct {
8080
Name string `json:"name"`
8181
}
8282

83-
func (s *ElasticSearchDataTestSuite) SetupTest() {
83+
func (s *IntegrationTestSuite) SetupTest() {
8484
file, err := os.ReadFile("testdata/data.json")
8585
s.Require().NoError(err, "failed to read data.json")
8686
dataList := []testDataObject{}
@@ -104,19 +104,20 @@ func (s *ElasticSearchDataTestSuite) SetupTest() {
104104
s.Require().False(res.IsError(), "failed to refresh indices")
105105
}
106106

107-
func (s *ElasticSearchDataTestSuite) TearDownTest() {
107+
func (s *IntegrationTestSuite) TearDownTest() {
108108
res, err := s.client.Indices.Delete([]string{"test_index"})
109109
s.Require().NoError(err, "failed to delete indices")
110110
s.Require().False(res.IsError(), "failed to delete indices: %s", res.String())
111111
}
112112

113-
func (s *ElasticSearchDataTestSuite) TestSearchDefaults() {
113+
func (s *IntegrationTestSuite) TestSearchDefaults() {
114114
args := cty.ObjectVal(map[string]cty.Value{
115115
"id": cty.NullVal(cty.String),
116116
"index": cty.StringVal("test_index"),
117117
"query": cty.NullVal(cty.DynamicPseudoType),
118118
"query_string": cty.NullVal(cty.String),
119119
"fields": cty.NullVal(cty.String),
120+
"size": cty.NullVal(cty.Number),
120121
})
121122
data, diags := s.plugin.RetrieveData(s.ctx, "elasticsearch", &plugin.RetrieveDataParams{
122123
Config: s.cfg,
@@ -173,13 +174,14 @@ func (s *ElasticSearchDataTestSuite) TestSearchDefaults() {
173174
}`, string(raw))
174175
}
175176

176-
func (s *ElasticSearchDataTestSuite) TestSearchFields() {
177+
func (s *IntegrationTestSuite) TestSearchFields() {
177178
args := cty.ObjectVal(map[string]cty.Value{
178179
"id": cty.NullVal(cty.String),
179180
"index": cty.StringVal("test_index"),
180181
"query": cty.NullVal(cty.DynamicPseudoType),
181182
"query_string": cty.NullVal(cty.String),
182183
"fields": cty.ListVal([]cty.Value{cty.StringVal("name"), cty.StringVal("age")}),
184+
"size": cty.NullVal(cty.Number),
183185
})
184186
data, diags := s.plugin.RetrieveData(s.ctx, "elasticsearch", &plugin.RetrieveDataParams{
185187
Config: s.cfg,
@@ -227,13 +229,14 @@ func (s *ElasticSearchDataTestSuite) TestSearchFields() {
227229
}`, string(raw))
228230
}
229231

230-
func (s *ElasticSearchDataTestSuite) TestSearchQueryString() {
232+
func (s *IntegrationTestSuite) TestSearchQueryString() {
231233
args := cty.ObjectVal(map[string]cty.Value{
232234
"id": cty.NullVal(cty.String),
233235
"index": cty.StringVal("test_index"),
234236
"query": cty.NullVal(cty.DynamicPseudoType),
235237
"query_string": cty.StringVal("type:foo"),
236238
"fields": cty.NullVal(cty.String),
239+
"size": cty.NullVal(cty.Number),
237240
})
238241
data, diags := s.plugin.RetrieveData(s.ctx, "elasticsearch", &plugin.RetrieveDataParams{
239242
Config: s.cfg,
@@ -278,7 +281,7 @@ func (s *ElasticSearchDataTestSuite) TestSearchQueryString() {
278281
}`, string(raw))
279282
}
280283

281-
func (s *ElasticSearchDataTestSuite) TestSearchQuery() {
284+
func (s *IntegrationTestSuite) TestSearchQuery() {
282285
args := cty.ObjectVal(map[string]cty.Value{
283286
"id": cty.NullVal(cty.String),
284287
"index": cty.StringVal("test_index"),
@@ -287,6 +290,7 @@ func (s *ElasticSearchDataTestSuite) TestSearchQuery() {
287290
}),
288291
"query_string": cty.NullVal(cty.String),
289292
"fields": cty.NullVal(cty.String),
293+
"size": cty.NullVal(cty.Number),
290294
})
291295
data, diags := s.plugin.RetrieveData(s.ctx, "elasticsearch", &plugin.RetrieveDataParams{
292296
Config: s.cfg,
@@ -343,7 +347,47 @@ func (s *ElasticSearchDataTestSuite) TestSearchQuery() {
343347
}`, string(raw))
344348
}
345349

346-
func (s *ElasticSearchDataTestSuite) TestGetByID() {
350+
func (s *IntegrationTestSuite) TestSearchSize() {
351+
args := cty.ObjectVal(map[string]cty.Value{
352+
"id": cty.NullVal(cty.String),
353+
"index": cty.StringVal("test_index"),
354+
"query": cty.NullVal(cty.DynamicPseudoType),
355+
"query_string": cty.NullVal(cty.String),
356+
"fields": cty.NullVal(cty.String),
357+
"size": cty.NumberIntVal(1),
358+
})
359+
data, diags := s.plugin.RetrieveData(s.ctx, "elasticsearch", &plugin.RetrieveDataParams{
360+
Config: s.cfg,
361+
Args: args,
362+
})
363+
s.Require().Nil(diags)
364+
m := data.(plugin.MapData)
365+
raw, err := json.MarshalIndent(m["hits"], "", " ")
366+
s.Require().NoError(err, "failed to marshal data: %v", err)
367+
s.JSONEq(`{
368+
"hits": [
369+
{
370+
"_id": "54f7a815-eac5-4f7c-a339-5fefd0f54967",
371+
"_index": "test_index",
372+
"_score": 1,
373+
"_source": {
374+
"active": false,
375+
"age": 39,
376+
"id": "54f7a815-eac5-4f7c-a339-5fefd0f54967",
377+
"name": "Davidson",
378+
"type": "foo"
379+
}
380+
}
381+
],
382+
"max_score": 1,
383+
"total": {
384+
"relation": "eq",
385+
"value": 3
386+
}
387+
}`, string(raw))
388+
}
389+
390+
func (s *IntegrationTestSuite) TestGetByID() {
347391
args := cty.ObjectVal(map[string]cty.Value{
348392
"id": cty.StringVal("0c68e63d-daaa-4a62-92e6-e855bd144fb6"),
349393
"index": cty.StringVal("test_index"),
@@ -376,7 +420,7 @@ func (s *ElasticSearchDataTestSuite) TestGetByID() {
376420
}`, string(raw))
377421
}
378422

379-
func (s *ElasticSearchDataTestSuite) TestGetByIDFields() {
423+
func (s *IntegrationTestSuite) TestGetByIDFields() {
380424
args := cty.ObjectVal(map[string]cty.Value{
381425
"id": cty.StringVal("0c68e63d-daaa-4a62-92e6-e855bd144fb6"),
382426
"index": cty.StringVal("test_index"),
@@ -406,7 +450,7 @@ func (s *ElasticSearchDataTestSuite) TestGetByIDFields() {
406450
}`, string(raw))
407451
}
408452

409-
func (s *ElasticSearchDataTestSuite) TestGetByIDNotFound() {
453+
func (s *IntegrationTestSuite) TestGetByIDNotFound() {
410454
args := cty.ObjectVal(map[string]cty.Value{
411455
"id": cty.StringVal("00000000-0000-0000-0000-000000000000"),
412456
"index": cty.StringVal("test_index"),

internal/elasticsearch/plugin.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,18 @@ func makeClient(pcfg cty.Value) (*es.Client, error) {
3434
Addresses: []string{defaultBaseURL},
3535
Username: defaultUsername,
3636
}
37+
if pcfg.IsNull() {
38+
return nil, fmt.Errorf("configuration is required")
39+
}
3740
if baseURL := pcfg.GetAttr("base_url"); !baseURL.IsNull() {
3841
cfg.Addresses = []string{baseURL.AsString()}
3942
}
4043
if cloudID := pcfg.GetAttr("cloud_id"); !cloudID.IsNull() {
4144
cfg.CloudID = cloudID.AsString()
4245
}
46+
if len(cfg.Addresses) == 0 && cfg.CloudID == "" {
47+
return nil, fmt.Errorf("either one of base_url or cloud_id is required")
48+
}
4349
if apiKeyStr := pcfg.GetAttr("api_key_str"); !apiKeyStr.IsNull() {
4450
cfg.APIKey = apiKeyStr.AsString()
4551
}
@@ -123,6 +129,13 @@ func search(fn esapi.Search, args cty.Value) (plugin.Data, error) {
123129
}
124130
opts = append(opts, fn.WithBody(bytes.NewReader(queryRaw)))
125131
}
132+
if size := args.GetAttr("size"); !size.IsNull() {
133+
n, _ := size.AsBigFloat().Int64()
134+
if n <= 0 {
135+
return nil, fmt.Errorf("size must be greater than 0")
136+
}
137+
opts = append(opts, fn.WithSize(int(n)))
138+
}
126139
if fields := args.GetAttr("fields"); !fields.IsNull() {
127140
fieldSlice := fields.AsValueSlice()
128141
fieldStrings := make([]string, len(fieldSlice))

0 commit comments

Comments
 (0)