Skip to content

Commit de65ccf

Browse files
authored
Migrate index resource to plugin framework (#698)
* Migrate the index resource to the tf framework * Docs * Mapping replacement * Fixup build * PR feedback
1 parent ca13c73 commit de65ccf

File tree

28 files changed

+3060
-1327
lines changed

28 files changed

+3060
-1327
lines changed

docs/resources/elasticsearch_index.md

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,9 @@ resource "elasticstack_elasticsearch_index" "my_index" {
4444
}
4545
})
4646
47-
number_of_shards = 1
48-
number_of_replicas = 2
49-
search_idle_after = "20s"
50-
total_shards_per_node = 200
47+
number_of_shards = 1
48+
number_of_replicas = 2
49+
search_idle_after = "20s"
5150
}
5251
```
5352

@@ -76,7 +75,7 @@ resource "elasticstack_elasticsearch_index" "my_index" {
7675
- `codec` (String) The `default` value compresses stored data with LZ4 compression, but this can be set to `best_compression` which uses DEFLATE for a higher compression ratio. This can be set only on creation.
7776
- `default_pipeline` (String) The default ingest node pipeline for this index. Index requests will fail if the default pipeline is set and the pipeline does not exist.
7877
- `deletion_protection` (Boolean) Whether to allow Terraform to destroy the index. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply command that deletes the instance will fail.
79-
- `elasticsearch_connection` (Block List, Max: 1, Deprecated) Elasticsearch connection configuration block. This property will be removed in a future provider version. Configure the Elasticsearch connection via the provider configuration instead. (see [below for nested schema](#nestedblock--elasticsearch_connection))
78+
- `elasticsearch_connection` (Block List, Deprecated) Elasticsearch connection configuration block. (see [below for nested schema](#nestedblock--elasticsearch_connection))
8079
- `final_pipeline` (String) Final ingest pipeline for the index. Indexing requests will fail if the final pipeline is set and the pipeline does not exist. The final pipeline always runs after the request pipeline (if specified) and the default pipeline (if it exists). The special pipeline name _none indicates no ingest pipeline will run.
8180
- `gc_deletes` (String) The length of time that a deleted document's version number remains available for further versioned operations.
8281
- `highlight_max_analyzed_offset` (Number) The maximum number of characters that will be analyzed for a highlight request.
@@ -90,10 +89,10 @@ resource "elasticstack_elasticsearch_index" "my_index" {
9089
- `load_fixed_bitset_filters_eagerly` (Boolean) Indicates whether cached filters are pre-loaded for nested queries. This can be set only on creation.
9190
- `mapping_coerce` (Boolean) Set index level coercion setting that is applied to all mapping types.
9291
- `mappings` (String) Mapping for fields in the index.
93-
If specified, this mapping can include: field names, [field data types](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html), [mapping parameters](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-params.html).
94-
**NOTE:**
95-
- Changing datatypes in the existing _mappings_ will force index to be re-created.
96-
- Removing field will be ignored by default same as elasticsearch. You need to recreate the index to remove field completely.
92+
If specified, this mapping can include: field names, [field data types](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html), [mapping parameters](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-params.html).
93+
**NOTE:**
94+
- Changing datatypes in the existing _mappings_ will force index to be re-created.
95+
- Removing field will be ignored by default same as elasticsearch. You need to recreate the index to remove field completely.
9796
- `master_timeout` (String) Period to wait for a connection to the master node. If no response is received before the timeout expires, the request fails and returns an error. Defaults to `30s`. This value is ignored when running against Serverless projects.
9897
- `max_docvalue_fields_search` (Number) The maximum number of `docvalue_fields` that are allowed in a query.
9998
- `max_inner_result_window` (Number) The maximum value of `from + size` for inner hits definition and top hits aggregations to this index.
@@ -123,7 +122,7 @@ If specified, this mapping can include: field names, [field data types](https://
123122
- `search_slowlog_threshold_query_info` (String) Set the cutoff for shard level slow search logging of slow searches in the query phase, in time units, e.g. `5s`
124123
- `search_slowlog_threshold_query_trace` (String) Set the cutoff for shard level slow search logging of slow searches in the query phase, in time units, e.g. `500ms`
125124
- `search_slowlog_threshold_query_warn` (String) Set the cutoff for shard level slow search logging of slow searches in the query phase, in time units, e.g. `10s`
126-
- `settings` (Block List, Max: 1, Deprecated) DEPRECATED: Please use dedicated setting field. Configuration options for the index. See, https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#index-modules-settings.
125+
- `settings` (Block List, Deprecated) DEPRECATED: Please use dedicated setting field. Configuration options for the index. See, https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#index-modules-settings.
127126
**NOTE:** Static index settings (see: https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#_static_index_settings) can be only set on the index creation and later cannot be removed or updated - _apply_ will return error (see [below for nested schema](#nestedblock--settings))
128127
- `shard_check_on_startup` (String) Whether or not shards should be checked for corruption before opening. When corruption is detected, it will prevent the shard from being opened. Accepts `false`, `true`, `checksum`.
129128
- `sort_field` (Set of String) The field to sort shards in this index by.
@@ -177,9 +176,9 @@ Optional:
177176
<a id="nestedblock--settings"></a>
178177
### Nested Schema for `settings`
179178

180-
Required:
179+
Optional:
181180

182-
- `setting` (Block Set, Min: 1) Defines the setting for the index. (see [below for nested schema](#nestedblock--settings--setting))
181+
- `setting` (Block Set) Defines the setting for the index. (see [below for nested schema](#nestedblock--settings--setting))
183182

184183
<a id="nestedblock--settings--setting"></a>
185184
### Nested Schema for `settings.setting`

examples/resources/elasticstack_elasticsearch_index/resource.tf

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ resource "elasticstack_elasticsearch_index" "my_index" {
2929
}
3030
})
3131

32-
number_of_shards = 1
33-
number_of_replicas = 2
34-
search_idle_after = "20s"
35-
total_shards_per_node = 200
32+
number_of_shards = 1
33+
number_of_replicas = 2
34+
search_idle_after = "20s"
3635
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ toolchain go1.23.1
77
require (
88
github.com/disaster37/go-kibana-rest/v8 v8.5.0
99
github.com/elastic/go-elasticsearch/v7 v7.17.10
10+
github.com/google/gofuzz v1.2.0
1011
github.com/google/uuid v1.6.0
1112
github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637
1213
github.com/hashicorp/go-version v1.7.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
5151
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
5252
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
5353
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
54+
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
55+
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
5456
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
5557
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
5658
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=

internal/clients/api_client.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
2121
"github.com/hashicorp/go-version"
2222
fwdiags "github.com/hashicorp/terraform-plugin-framework/diag"
23+
"github.com/hashicorp/terraform-plugin-framework/types"
2324
"github.com/hashicorp/terraform-plugin-log/tflog"
2425
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
2526
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging"
@@ -156,6 +157,35 @@ func ConvertProviderData(providerData any) (*ApiClient, fwdiags.Diagnostics) {
156157
return client, diags
157158
}
158159

160+
func MaybeNewApiClientFromFrameworkResource(ctx context.Context, esConnList types.List, defaultClient *ApiClient) (*ApiClient, fwdiags.Diagnostics) {
161+
var esConns []config.ElasticsearchConnection
162+
if diags := esConnList.ElementsAs(ctx, &esConns, true); diags.HasError() {
163+
return nil, diags
164+
}
165+
166+
if len(esConns) == 0 {
167+
return defaultClient, nil
168+
}
169+
170+
cfg, diags := config.NewFromFramework(ctx, config.ProviderConfiguration{Elasticsearch: esConns}, defaultClient.version)
171+
if diags.HasError() {
172+
return nil, diags
173+
}
174+
175+
esClient, err := buildEsClient(cfg)
176+
if err != nil {
177+
return nil, fwdiags.Diagnostics{fwdiags.NewErrorDiagnostic(err.Error(), err.Error())}
178+
}
179+
180+
return &ApiClient{
181+
elasticsearch: esClient,
182+
elasticsearchClusterInfo: defaultClient.elasticsearchClusterInfo,
183+
kibana: defaultClient.kibana,
184+
fleet: defaultClient.fleet,
185+
version: defaultClient.version,
186+
}, diags
187+
}
188+
159189
func NewApiClientFromSDKResource(d *schema.ResourceData, meta interface{}) (*ApiClient, diag.Diagnostics) {
160190
defaultClient := meta.(*ApiClient)
161191
version := defaultClient.version

internal/clients/elasticsearch/index.go

Lines changed: 76 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
1313
"github.com/elastic/terraform-provider-elasticstack/internal/models"
1414
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
15+
fwdiags "github.com/hashicorp/terraform-plugin-framework/diag"
1516
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1617
)
1718

@@ -245,16 +246,19 @@ func DeleteIndexTemplate(ctx context.Context, apiClient *clients.ApiClient, temp
245246
return diags
246247
}
247248

248-
func PutIndex(ctx context.Context, apiClient *clients.ApiClient, index *models.Index, params *models.PutIndexParams) diag.Diagnostics {
249-
var diags diag.Diagnostics
249+
func PutIndex(ctx context.Context, apiClient *clients.ApiClient, index *models.Index, params *models.PutIndexParams) fwdiags.Diagnostics {
250250
indexBytes, err := json.Marshal(index)
251251
if err != nil {
252-
return diag.FromErr(err)
252+
return fwdiags.Diagnostics{
253+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
254+
}
253255
}
254256

255257
esClient, err := apiClient.GetESClient()
256258
if err != nil {
257-
return diag.FromErr(err)
259+
return fwdiags.Diagnostics{
260+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
261+
}
258262
}
259263

260264
opts := []func(*esapi.IndicesCreateRequest){
@@ -272,45 +276,46 @@ func PutIndex(ctx context.Context, apiClient *clients.ApiClient, index *models.I
272276
opts...,
273277
)
274278
if err != nil {
275-
return diag.FromErr(err)
279+
return fwdiags.Diagnostics{
280+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
281+
}
276282
}
277283
defer res.Body.Close()
278-
if diags := utils.CheckError(res, fmt.Sprintf("Unable to create index: %s", index.Name)); diags.HasError() {
279-
return diags
280-
}
281-
return diags
284+
diags := utils.CheckError(res, fmt.Sprintf("Unable to create index: %s", index.Name))
285+
return utils.FrameworkDiagsFromSDK(diags)
282286
}
283287

284-
func DeleteIndex(ctx context.Context, apiClient *clients.ApiClient, name string) diag.Diagnostics {
285-
var diags diag.Diagnostics
286-
288+
func DeleteIndex(ctx context.Context, apiClient *clients.ApiClient, name string) fwdiags.Diagnostics {
287289
esClient, err := apiClient.GetESClient()
288290
if err != nil {
289-
return diag.FromErr(err)
291+
return fwdiags.Diagnostics{
292+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
293+
}
290294
}
291295
res, err := esClient.Indices.Delete([]string{name}, esClient.Indices.Delete.WithContext(ctx))
292296
if err != nil {
293-
return diag.FromErr(err)
297+
return fwdiags.Diagnostics{
298+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
299+
}
294300
}
295301
defer res.Body.Close()
296-
if diags := utils.CheckError(res, fmt.Sprintf("Unable to delete the index: %s", name)); diags.HasError() {
297-
return diags
298-
}
299-
300-
return diags
302+
diags := utils.CheckError(res, fmt.Sprintf("Unable to delete the index: %s", name))
303+
return utils.FrameworkDiagsFromSDK(diags)
301304
}
302305

303-
func GetIndex(ctx context.Context, apiClient *clients.ApiClient, name string) (*models.Index, diag.Diagnostics) {
304-
var diags diag.Diagnostics
305-
306+
func GetIndex(ctx context.Context, apiClient *clients.ApiClient, name string) (*models.Index, fwdiags.Diagnostics) {
306307
esClient, err := apiClient.GetESClient()
307308
if err != nil {
308-
return nil, diag.FromErr(err)
309+
return nil, fwdiags.Diagnostics{
310+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
311+
}
309312
}
310313
req := esClient.Indices.Get.WithFlatSettings(true)
311314
res, err := esClient.Indices.Get([]string{name}, req, esClient.Indices.Get.WithContext(ctx))
312315
if err != nil {
313-
return nil, diag.FromErr(err)
316+
return nil, fwdiags.Diagnostics{
317+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
318+
}
314319
}
315320
defer res.Body.Close()
316321
// if there is no index found, return the empty struct, which should force the creation of the index
@@ -319,94 +324,104 @@ func GetIndex(ctx context.Context, apiClient *clients.ApiClient, name string) (*
319324
}
320325

321326
if diags := utils.CheckError(res, fmt.Sprintf("Unable to get requested index: %s", name)); diags.HasError() {
322-
return nil, diags
327+
return nil, utils.FrameworkDiagsFromSDK(diags)
323328
}
324329

325330
indices := make(map[string]models.Index)
326331
if err := json.NewDecoder(res.Body).Decode(&indices); err != nil {
327-
return nil, diag.FromErr(err)
332+
return nil, fwdiags.Diagnostics{
333+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
334+
}
328335
}
329336
index := indices[name]
330-
return &index, diags
337+
return &index, nil
331338
}
332339

333-
func DeleteIndexAlias(ctx context.Context, apiClient *clients.ApiClient, index string, aliases []string) diag.Diagnostics {
334-
var diags diag.Diagnostics
340+
func DeleteIndexAlias(ctx context.Context, apiClient *clients.ApiClient, index string, aliases []string) fwdiags.Diagnostics {
335341
esClient, err := apiClient.GetESClient()
336342
if err != nil {
337-
return diag.FromErr(err)
343+
return fwdiags.Diagnostics{
344+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
345+
}
338346
}
339347
res, err := esClient.Indices.DeleteAlias([]string{index}, aliases, esClient.Indices.DeleteAlias.WithContext(ctx))
340348
if err != nil {
341-
return diag.FromErr(err)
349+
return fwdiags.Diagnostics{
350+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
351+
}
342352
}
343353
defer res.Body.Close()
344-
if diags := utils.CheckError(res, fmt.Sprintf("Unable to delete aliases '%v' for index '%s'", index, aliases)); diags.HasError() {
345-
return diags
346-
}
347-
return diags
354+
diags := utils.CheckError(res, fmt.Sprintf("Unable to delete aliases '%v' for index '%s'", index, aliases))
355+
return utils.FrameworkDiagsFromSDK(diags)
348356
}
349357

350-
func UpdateIndexAlias(ctx context.Context, apiClient *clients.ApiClient, index string, alias *models.IndexAlias) diag.Diagnostics {
351-
var diags diag.Diagnostics
358+
func UpdateIndexAlias(ctx context.Context, apiClient *clients.ApiClient, index string, alias *models.IndexAlias) fwdiags.Diagnostics {
352359
aliasBytes, err := json.Marshal(alias)
353360
if err != nil {
354-
return diag.FromErr(err)
361+
return fwdiags.Diagnostics{
362+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
363+
}
355364
}
356365
esClient, err := apiClient.GetESClient()
357366
if err != nil {
358-
return diag.FromErr(err)
367+
return fwdiags.Diagnostics{
368+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
369+
}
359370
}
360371
req := esClient.Indices.PutAlias.WithBody(bytes.NewReader(aliasBytes))
361372
res, err := esClient.Indices.PutAlias([]string{index}, alias.Name, req, esClient.Indices.PutAlias.WithContext(ctx))
362373
if err != nil {
363-
return diag.FromErr(err)
374+
return fwdiags.Diagnostics{
375+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
376+
}
364377
}
365378
defer res.Body.Close()
366-
if diags := utils.CheckError(res, fmt.Sprintf("Unable to update alias '%v' for index '%s'", index, alias.Name)); diags.HasError() {
367-
return diags
368-
}
369-
return diags
379+
diags := utils.CheckError(res, fmt.Sprintf("Unable to update alias '%v' for index '%s'", index, alias.Name))
380+
return utils.FrameworkDiagsFromSDK(diags)
370381
}
371382

372-
func UpdateIndexSettings(ctx context.Context, apiClient *clients.ApiClient, index string, settings map[string]interface{}) diag.Diagnostics {
373-
var diags diag.Diagnostics
383+
func UpdateIndexSettings(ctx context.Context, apiClient *clients.ApiClient, index string, settings map[string]interface{}) fwdiags.Diagnostics {
374384
settingsBytes, err := json.Marshal(settings)
375385
if err != nil {
376-
return diag.FromErr(err)
386+
return fwdiags.Diagnostics{
387+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
388+
}
377389
}
378390
esClient, err := apiClient.GetESClient()
379391
if err != nil {
380-
return diag.FromErr(err)
392+
return fwdiags.Diagnostics{
393+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
394+
}
381395
}
382396
req := esClient.Indices.PutSettings.WithIndex(index)
383397
res, err := esClient.Indices.PutSettings(bytes.NewReader(settingsBytes), req, esClient.Indices.PutSettings.WithContext(ctx))
384398
if err != nil {
385-
return diag.FromErr(err)
399+
return fwdiags.Diagnostics{
400+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
401+
}
386402
}
387403
defer res.Body.Close()
388-
if diags := utils.CheckError(res, "Unable to update index settings"); diags.HasError() {
389-
return diags
390-
}
391-
return diags
404+
diags := utils.CheckError(res, "Unable to update index settings")
405+
return utils.FrameworkDiagsFromSDK(diags)
392406
}
393407

394-
func UpdateIndexMappings(ctx context.Context, apiClient *clients.ApiClient, index, mappings string) diag.Diagnostics {
395-
var diags diag.Diagnostics
408+
func UpdateIndexMappings(ctx context.Context, apiClient *clients.ApiClient, index, mappings string) fwdiags.Diagnostics {
396409
esClient, err := apiClient.GetESClient()
397410
if err != nil {
398-
return diag.FromErr(err)
411+
return fwdiags.Diagnostics{
412+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
413+
}
399414
}
400415
req := esClient.Indices.PutMapping.WithIndex(index)
401416
res, err := esClient.Indices.PutMapping(strings.NewReader(mappings), req, esClient.Indices.PutMapping.WithContext(ctx))
402417
if err != nil {
403-
return diag.FromErr(err)
418+
return fwdiags.Diagnostics{
419+
fwdiags.NewErrorDiagnostic(err.Error(), err.Error()),
420+
}
404421
}
405422
defer res.Body.Close()
406-
if diags := utils.CheckError(res, "Unable to update index mappings"); diags.HasError() {
407-
return diags
408-
}
409-
return diags
423+
diags := utils.CheckError(res, "Unable to update index mappings")
424+
return utils.FrameworkDiagsFromSDK(diags)
410425
}
411426

412427
func PutDataStream(ctx context.Context, apiClient *clients.ApiClient, dataStreamName string) diag.Diagnostics {

0 commit comments

Comments
 (0)