diff --git a/.ci/Makefile.ci b/.ci/Makefile.ci index 1f2705801..559b7615e 100644 --- a/.ci/Makefile.ci +++ b/.ci/Makefile.ci @@ -4,7 +4,7 @@ GOVERSION ?= 1.17 ELASTICSEARCH_NAME ?= terraform-elasticstack-es ELASTICSEARCH_ENDPOINTS ?= http://$(ELASTICSEARCH_NAME):9200 -ELASTICSEARCH_VERSION ?= 7.15.1 +ELASTICSEARCH_VERSION ?= 8.0.0 ELASTICSEARCH_USERNAME ?= elastic ELASTICSEARCH_PASSWORD ?= changeme ELASTICSEARCH_NETWORK ?= elasticstack-network diff --git a/CHANGELOG.md b/CHANGELOG.md index 258e756e5..18f3f3663 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ ## [Unreleased] +### Fixed +- Add new field `allow_custom_routing` in `data_stream` section of [`index_template`](https://www.elastic.co/guide/en/elasticsearch/reference/8.0/indices-put-template.html#put-index-template-api-request-body), which appears only in Elasticsearch version **8.0.0**. Make sure `index_template` resource can work with both **7.x** and **8.x** versions ([#72](https://github.com/elastic/terraform-provider-elasticstack/pull/72)) ## [0.3.0] - 2022-02-17 ### Added diff --git a/docs/resources/elasticsearch_cluster_settings.md b/docs/resources/elasticsearch_cluster_settings.md index b92f5eb91..d28334788 100644 --- a/docs/resources/elasticsearch_cluster_settings.md +++ b/docs/resources/elasticsearch_cluster_settings.md @@ -28,8 +28,8 @@ resource "elasticstack_elasticsearch_cluster_settings" "my_cluster_settings" { value = "50mb" } setting { - name = "indices.breaker.accounting.limit" - value = "100%" + name = "indices.breaker.total.limit" + value = "65%" } setting { name = "xpack.security.audit.logfile.events.include" @@ -39,8 +39,8 @@ resource "elasticstack_elasticsearch_cluster_settings" "my_cluster_settings" { transient { setting { - name = "indices.breaker.accounting.limit" - value = "99%" + name = "indices.breaker.total.limit" + value = "60%" } } } diff --git a/docs/resources/elasticsearch_index_template.md b/docs/resources/elasticsearch_index_template.md index 3447a19e2..44bcfedd8 100644 --- a/docs/resources/elasticsearch_index_template.md +++ b/docs/resources/elasticsearch_index_template.md @@ -72,6 +72,7 @@ resource "elasticstack_elasticsearch_index_template" "my_data_stream" { Optional: +- **allow_custom_routing** (Boolean) If `true`, the data stream supports custom routing. Defaults to `false`. Available only in **8.x** - **hidden** (Boolean) If true, the data stream is hidden. diff --git a/examples/resources/elasticstack_elasticsearch_cluster_settings/resource.tf b/examples/resources/elasticstack_elasticsearch_cluster_settings/resource.tf index 66b21ffc6..87a4b5b53 100644 --- a/examples/resources/elasticstack_elasticsearch_cluster_settings/resource.tf +++ b/examples/resources/elasticstack_elasticsearch_cluster_settings/resource.tf @@ -13,8 +13,8 @@ resource "elasticstack_elasticsearch_cluster_settings" "my_cluster_settings" { value = "50mb" } setting { - name = "indices.breaker.accounting.limit" - value = "100%" + name = "indices.breaker.total.limit" + value = "65%" } setting { name = "xpack.security.audit.logfile.events.include" @@ -24,8 +24,8 @@ resource "elasticstack_elasticsearch_cluster_settings" "my_cluster_settings" { transient { setting { - name = "indices.breaker.accounting.limit" - value = "99%" + name = "indices.breaker.total.limit" + value = "60%" } } } diff --git a/internal/elasticsearch/cluster/settings_test.go b/internal/elasticsearch/cluster/settings_test.go index 74fc4c9f5..5b4b113b2 100644 --- a/internal/elasticsearch/cluster/settings_test.go +++ b/internal/elasticsearch/cluster/settings_test.go @@ -32,13 +32,13 @@ func TestAccResourceClusterSettings(t *testing.T) { }), resource.TestCheckTypeSetElemNestedAttrs("elasticstack_elasticsearch_cluster_settings.test", "persistent.0.setting.*", map[string]string{ - "name": "indices.breaker.accounting.limit", - "value": "100%", + "name": "indices.breaker.total.limit", + "value": "65%", }), resource.TestCheckTypeSetElemNestedAttrs("elasticstack_elasticsearch_cluster_settings.test", "transient.0.setting.*", map[string]string{ - "name": "indices.breaker.accounting.limit", - "value": "99%", + "name": "indices.breaker.total.limit", + "value": "60%", }), ), }, @@ -57,8 +57,8 @@ func TestAccResourceClusterSettings(t *testing.T) { }), resource.TestCheckTypeSetElemNestedAttrs("elasticstack_elasticsearch_cluster_settings.test", "persistent.0.setting.*", map[string]string{ - "name": "indices.breaker.accounting.limit", - "value": "100%", + "name": "indices.breaker.total.limit", + "value": "60%", }), resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_cluster_settings.test", "persistent.0.setting.*.value_list.*", "ACCESS_DENIED"), resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_cluster_settings.test", "persistent.0.setting.*.value_list.*", "ACCESS_GRANTED"), @@ -86,15 +86,15 @@ resource "elasticstack_elasticsearch_cluster_settings" "test" { value = "50mb" } setting { - name = "indices.breaker.accounting.limit" - value = "100%" + name = "indices.breaker.total.limit" + value = "65%" } } transient { setting { - name = "indices.breaker.accounting.limit" - value = "99%" + name = "indices.breaker.total.limit" + value = "60%" } } } @@ -118,8 +118,8 @@ resource "elasticstack_elasticsearch_cluster_settings" "test" { value = "40mb" } setting { - name = "indices.breaker.accounting.limit" - value = "100%" + name = "indices.breaker.total.limit" + value = "60%" } setting { name = "xpack.security.audit.logfile.events.include" @@ -136,7 +136,7 @@ func checkResourceClusterSettingsDestroy(s *terraform.State) error { listOfSettings := []string{ "indices.lifecycle.poll_interval", "indices.recovery.max_bytes_per_sec", - "indices.breaker.accounting.limit", + "indices.breaker.total.limit", "xpack.security.audit.logfile.events.include", } diff --git a/internal/elasticsearch/index/template.go b/internal/elasticsearch/index/template.go index fef3123a7..91e248725 100644 --- a/internal/elasticsearch/index/template.go +++ b/internal/elasticsearch/index/template.go @@ -48,6 +48,11 @@ func ResourceTemplate() *schema.Resource { Default: false, Optional: true, }, + "allow_custom_routing": { + Description: "If `true`, the data stream supports custom routing. Defaults to `false`. Available only in **8.x**", + Type: schema.TypeBool, + Optional: true, + }, }, }, }, @@ -195,10 +200,36 @@ func resourceIndexTemplatePut(ctx context.Context, d *schema.ResourceData, meta } indexTemplate.ComposedOf = compsOf - if v, ok := d.GetOk("data_stream"); ok { - // only one definition of stream allowed - stream := v.([]interface{})[0].(map[string]interface{}) - indexTemplate.DataStream = stream + if d.HasChange("data_stream") { + old, _ := d.GetChange("data_stream") + + // 8.x workaround + hasAllowCustomRouting := false + if old != nil && len(old.([]interface{})) == 1 { + if old.([]interface{})[0] != nil { + setting := old.([]interface{})[0].(map[string]interface{}) + if _, ok := setting["allow_custom_routing"]; ok { + hasAllowCustomRouting = true + } + } + } + + if v, ok := d.GetOk("data_stream"); ok { + // only one definition of stream allowed + if v.([]interface{})[0] != nil { + stream := v.([]interface{})[0].(map[string]interface{}) + dSettings := &models.DataStreamSettings{} + if s, ok := stream["hidden"]; ok { + hidden := s.(bool) + dSettings.Hidden = &hidden + } + if s, ok := stream["allow_custom_routing"]; ok && (hasAllowCustomRouting || s.(bool)) { + allow := s.(bool) + dSettings.AllowCustomRouting = &allow + } + indexTemplate.DataStream = dSettings + } + } } if v, ok := d.GetOk("index_patterns"); ok { @@ -298,9 +329,16 @@ func resourceIndexTemplateRead(ctx context.Context, d *schema.ResourceData, meta if err := d.Set("composed_of", tpl.IndexTemplate.ComposedOf); err != nil { return diag.FromErr(err) } - if tpl.IndexTemplate.DataStream != nil { - ds := make([]interface{}, 0) - ds = append(ds, tpl.IndexTemplate.DataStream) + if stream := tpl.IndexTemplate.DataStream; stream != nil { + ds := make([]interface{}, 1) + dSettings := make(map[string]interface{}) + if v := stream.Hidden; v != nil { + dSettings["hidden"] = *v + } + if v := stream.AllowCustomRouting; v != nil { + dSettings["allow_custom_routing"] = *v + } + ds[0] = dSettings if err := d.Set("data_stream", ds); err != nil { return diag.FromErr(err) } diff --git a/internal/elasticsearch/index/template_test.go b/internal/elasticsearch/index/template_test.go index 7d12e57b6..766d7b711 100644 --- a/internal/elasticsearch/index/template_test.go +++ b/internal/elasticsearch/index/template_test.go @@ -26,6 +26,19 @@ func TestAccResourceIndexTemplate(t *testing.T) { resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test", "name", templateName), resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_index_template.test", "index_patterns.*", fmt.Sprintf("%s-logs-*", templateName)), resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test", "priority", "42"), + resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test", "template.0.alias.#", "1"), + resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test2", "name", fmt.Sprintf("%s-stream", templateName)), + resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test2", "data_stream.0.allow_custom_routing", "true"), + ), + }, + { + Config: testAccResourceIndexTemplateUpdate(templateName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test", "name", templateName), + resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_index_template.test", "index_patterns.*", fmt.Sprintf("%s-logs-*", templateName)), + resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test", "template.0.alias.#", "2"), + resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test2", "name", fmt.Sprintf("%s-stream", templateName)), + resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test2", "data_stream.0.allow_custom_routing", "false"), ), }, }, @@ -54,7 +67,52 @@ resource "elasticstack_elasticsearch_index_template" "test" { }) } } - `, name, name) + +resource "elasticstack_elasticsearch_index_template" "test2" { + name = "%s-stream" + + index_patterns = ["index-pattern-streams*"] + data_stream { + allow_custom_routing = true + } +} + `, name, name, name) +} + +func testAccResourceIndexTemplateUpdate(name string) string { + return fmt.Sprintf(` +provider "elasticstack" { + elasticsearch {} +} + +resource "elasticstack_elasticsearch_index_template" "test" { + name = "%s" + + index_patterns = ["%s-logs-*"] + + template { + alias { + name = "my_template_test" + } + alias { + name = "alias2" + } + + settings = jsonencode({ + number_of_shards = "3" + }) + } +} + +resource "elasticstack_elasticsearch_index_template" "test2" { + name = "%s-stream" + + index_patterns = ["index-pattern-streams*"] + data_stream { + allow_custom_routing = false + } +} + `, name, name, name) } func checkResourceIndexTemplateDestroy(s *terraform.State) error { diff --git a/internal/models/models.go b/internal/models/models.go index e60f72af0..826e54a93 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -44,7 +44,7 @@ type IndexTemplate struct { Create bool `json:"-"` Timeout string `json:"-"` ComposedOf []string `json:"composed_of"` - DataStream map[string]interface{} `json:"data_stream,omitempty"` + DataStream *DataStreamSettings `json:"data_stream,omitempty"` IndexPatterns []string `json:"index_patterns"` Meta map[string]interface{} `json:"_meta,omitempty"` Priority *int `json:"priority,omitempty"` @@ -52,6 +52,11 @@ type IndexTemplate struct { Version *int `json:"version,omitempty"` } +type DataStreamSettings struct { + Hidden *bool `json:"hidden,omitempty"` + AllowCustomRouting *bool `json:"allow_custom_routing,omitempty"` +} + type Template struct { Aliases map[string]IndexAlias `json:"aliases,omitempty"` Mappings map[string]interface{} `json:"mappings,omitempty"`