Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ alias = [
- Support `.bedrock` and `.gen-ai` connectors ([#1467](https://github.com/elastic/terraform-provider-elasticstack/pull/1467))
- Support the `solution` attribute in `elasticstack_kibana_space` from 8.16 ([#1486](https://github.com/elastic/terraform-provider-elasticstack/pull/1486))
- Add `elasticstack_elasticsearch_alias` resource ([#1343](https://github.com/elastic/terraform-provider-elasticstack/pull/1343))
- Add `mapping_total_fields_limit` to `elasticstack_elasticsearch_index` ([#1494](https://github.com/elastic/terraform-provider-elasticstack/pull/1494))

## [0.12.2] - 2025-11-19
- Fix `elasticstack_elasticsearch_snapshot_lifecycle` metadata type conversion causing terraform apply to fail ([#1409](https://github.com/elastic/terraform-provider-elasticstack/issues/1409))
Expand Down
1 change: 1 addition & 0 deletions docs/resources/elasticsearch_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ resource "elasticstack_elasticsearch_index" "my_index" {
- `indexing_slowlog_threshold_index_warn` (String) Set the cutoff for shard level slow search logging of slow searches for indexing queries, in time units, e.g. `10s`
- `load_fixed_bitset_filters_eagerly` (Boolean) Indicates whether cached filters are pre-loaded for nested queries. This can be set only on creation.
- `mapping_coerce` (Boolean) Set index level coercion setting that is applied to all mapping types.
- `mapping_total_fields_limit` (Number) The maximum number of fields in an index. Field type parameters count towards this limit. The default value is 1000.
- `mappings` (String) Mapping for fields in the index.
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).
**NOTE:**
Expand Down
116 changes: 32 additions & 84 deletions internal/elasticsearch/index/index/acc_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package index_test

import (
_ "embed"
"fmt"
"regexp"
"testing"

"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
"github.com/hashicorp/terraform-plugin-testing/config"
sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
Expand Down Expand Up @@ -77,6 +79,9 @@ func TestAccResourceIndex(t *testing.T) {
})
}

//go:embed testdata/TestAccResourceIndexFromSDK/index.tf
var sdkCreateTestConfig string

func TestAccResourceIndexFromSDK(t *testing.T) {
indexName := sdkacctest.RandStringFromCharSet(22, sdkacctest.CharSetAlphaNum)

Expand All @@ -92,7 +97,10 @@ func TestAccResourceIndexFromSDK(t *testing.T) {
VersionConstraint: "0.11.3",
},
},
Config: testAccResourceIndexSettingsCreate(indexName),
Config: sdkCreateTestConfig,
ConfigVariables: config.Variables{
"index_name": config.StringVariable(indexName),
},
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "name", indexName),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "number_of_shards", "2"),
Expand Down Expand Up @@ -132,7 +140,10 @@ func TestAccResourceIndexFromSDK(t *testing.T) {
},
{
ProtoV6ProviderFactories: acctest.Providers,
Config: testAccResourceIndexSettingsCreate(indexName),
ConfigDirectory: acctest.NamedTestCaseDirectory(""),
ConfigVariables: config.Variables{
"index_name": config.StringVariable(indexName),
},
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "name", indexName),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "number_of_shards", "2"),
Expand Down Expand Up @@ -178,12 +189,15 @@ func TestAccResourceIndexSettings(t *testing.T) {
indexName := sdkacctest.RandStringFromCharSet(22, sdkacctest.CharSetAlphaNum)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
CheckDestroy: checkResourceIndexDestroy,
ProtoV6ProviderFactories: acctest.Providers,
PreCheck: func() { acctest.PreCheck(t) },
CheckDestroy: checkResourceIndexDestroy,
Steps: []resource.TestStep{
{
Config: testAccResourceIndexSettingsCreate(indexName),
ProtoV6ProviderFactories: acctest.Providers,
ConfigDirectory: acctest.NamedTestCaseDirectory("create"),
ConfigVariables: config.Variables{
"index_name": config.StringVariable(indexName),
},
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "name", indexName),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "number_of_shards", "2"),
Expand All @@ -194,6 +208,7 @@ func TestAccResourceIndexSettings(t *testing.T) {
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "sort_field.0", "sort_key"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "sort_order.0", "asc"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "mapping_coerce", "true"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "mapping_total_fields_limit", "2000"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "auto_expand_replicas", "0-5"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "search_idle_after", "30s"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "refresh_interval", "10s"),
Expand Down Expand Up @@ -221,6 +236,17 @@ func TestAccResourceIndexSettings(t *testing.T) {
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "settings.0.setting.0.value", "2"),
),
},
{
ProtoV6ProviderFactories: acctest.Providers,
ConfigDirectory: acctest.NamedTestCaseDirectory("update"),
ConfigVariables: config.Variables{
"index_name": config.StringVariable(indexName),
},
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "name", indexName),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index.test_settings", "mapping_total_fields_limit", "3000"),
),
},
},
})
}
Expand Down Expand Up @@ -348,84 +374,6 @@ resource "elasticstack_elasticsearch_index" "test" {
`, name)
}

func testAccResourceIndexSettingsCreate(name string) string {
return fmt.Sprintf(`
provider "elasticstack" {
elasticsearch {}
}

resource "elasticstack_elasticsearch_index" "test_settings" {
name = "%s"

mappings = jsonencode({
properties = {
field1 = { type = "text" }
sort_key = { type = "keyword" }
}
})

number_of_shards = 2
number_of_routing_shards = 2
codec = "best_compression"
routing_partition_size = 1
shard_check_on_startup = "false"
sort_field = ["sort_key"]
sort_order = ["asc"]
mapping_coerce = true
auto_expand_replicas = "0-5"
search_idle_after = "30s"
refresh_interval = "10s"
max_result_window = 5000
max_inner_result_window = 2000
max_rescore_window = 1000
max_docvalue_fields_search = 1500
max_script_fields = 500
max_ngram_diff = 100
max_shingle_diff = 200
max_refresh_listeners = 10
analyze_max_token_count = 500000
highlight_max_analyzed_offset = 1000
max_terms_count = 10000
max_regex_length = 1000
query_default_field = ["field1"]
routing_allocation_enable = "primaries"
routing_rebalance_enable = "primaries"
gc_deletes = "30s"
unassigned_node_left_delayed_timeout = "5m"

analysis_char_filter = jsonencode({
zero_width_spaces = {
type = "mapping"
mappings = ["\\u200C=>\\u0020"]
}
})
analysis_filter = jsonencode({
minimal_english_stemmer = {
type = "stemmer"
language = "minimal_english"
}
})
analysis_analyzer = jsonencode({
text_en = {
type = "custom"
tokenizer = "standard"
char_filter = "zero_width_spaces"
filter = ["lowercase", "minimal_english_stemmer"]
}
})

settings {
setting {
name = "number_of_replicas"
value = "2"
}
}

deletion_protection = false
}
`, name)
}

func testAccResourceIndexRemovingFieldCreate(name string) string {
return fmt.Sprintf(`
provider "elasticstack" {
Expand Down
2 changes: 2 additions & 0 deletions internal/elasticsearch/index/index/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var (
"auto_expand_replicas",
"refresh_interval",
"search.idle.after",
"mapping.total_fields.limit",
"max_result_window",
"max_inner_result_window",
"max_rescore_window",
Expand Down Expand Up @@ -97,6 +98,7 @@ type tfModel struct {
SortField types.Set `tfsdk:"sort_field"`
SortOrder types.List `tfsdk:"sort_order"`
MappingCoerce types.Bool `tfsdk:"mapping_coerce"`
MappingTotalFieldsLimit types.Int64 `tfsdk:"mapping_total_fields_limit"`
NumberOfReplicas types.Int64 `tfsdk:"number_of_replicas"`
AutoExpandReplicas types.String `tfsdk:"auto_expand_replicas"`
SearchIdleAfter types.String `tfsdk:"search_idle_after"`
Expand Down
4 changes: 4 additions & 0 deletions internal/elasticsearch/index/index/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ func getSchema() schema.Schema {
},
},
// Dynamic settings that can be changed at runtime
"mapping_total_fields_limit": schema.Int64Attribute{
Description: "The maximum number of fields in an index. Field type parameters count towards this limit. The default value is 1000.",
Optional: true,
},
"number_of_replicas": schema.Int64Attribute{
Description: "Number of shard replicas.",
Optional: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
variable "index_name" {
description = "The index name"
type = string
}

provider "elasticstack" {
elasticsearch {}
}

resource "elasticstack_elasticsearch_index" "test_settings" {
name = var.index_name

mappings = jsonencode({
properties = {
field1 = { type = "text" }
sort_key = { type = "keyword" }
}
})

number_of_shards = 2
number_of_routing_shards = 2
codec = "best_compression"
routing_partition_size = 1
shard_check_on_startup = "false"
sort_field = ["sort_key"]
sort_order = ["asc"]
mapping_coerce = true
auto_expand_replicas = "0-5"
search_idle_after = "30s"
refresh_interval = "10s"
max_result_window = 5000
max_inner_result_window = 2000
max_rescore_window = 1000
max_docvalue_fields_search = 1500
max_script_fields = 500
max_ngram_diff = 100
max_shingle_diff = 200
max_refresh_listeners = 10
analyze_max_token_count = 500000
highlight_max_analyzed_offset = 1000
max_terms_count = 10000
max_regex_length = 1000
query_default_field = ["field1"]
routing_allocation_enable = "primaries"
routing_rebalance_enable = "primaries"
gc_deletes = "30s"
unassigned_node_left_delayed_timeout = "5m"

analysis_char_filter = jsonencode({
zero_width_spaces = {
type = "mapping"
mappings = ["\\u200C=>\\u0020"]
}
})
analysis_filter = jsonencode({
minimal_english_stemmer = {
type = "stemmer"
language = "minimal_english"
}
})
analysis_analyzer = jsonencode({
text_en = {
type = "custom"
tokenizer = "standard"
char_filter = "zero_width_spaces"
filter = ["lowercase", "minimal_english_stemmer"]
}
})

settings {
setting {
name = "number_of_replicas"
value = "2"
}
}

deletion_protection = false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
variable "index_name" {
description = "The index name"
type = string
}

provider "elasticstack" {
elasticsearch {}
}

resource "elasticstack_elasticsearch_index" "test_settings" {
name = var.index_name

mappings = jsonencode({
properties = {
field1 = { type = "text" }
sort_key = { type = "keyword" }
}
})

number_of_shards = 2
number_of_routing_shards = 2
codec = "best_compression"
routing_partition_size = 1
shard_check_on_startup = "false"
sort_field = ["sort_key"]
sort_order = ["asc"]
mapping_coerce = true
mapping_total_fields_limit = 2000
auto_expand_replicas = "0-5"
search_idle_after = "30s"
refresh_interval = "10s"
max_result_window = 5000
max_inner_result_window = 2000
max_rescore_window = 1000
max_docvalue_fields_search = 1500
max_script_fields = 500
max_ngram_diff = 100
max_shingle_diff = 200
max_refresh_listeners = 10
analyze_max_token_count = 500000
highlight_max_analyzed_offset = 1000
max_terms_count = 10000
max_regex_length = 1000
query_default_field = ["field1"]
routing_allocation_enable = "primaries"
routing_rebalance_enable = "primaries"
gc_deletes = "30s"
unassigned_node_left_delayed_timeout = "5m"

analysis_char_filter = jsonencode({
zero_width_spaces = {
type = "mapping"
mappings = ["\\u200C=>\\u0020"]
}
})
analysis_filter = jsonencode({
minimal_english_stemmer = {
type = "stemmer"
language = "minimal_english"
}
})
analysis_analyzer = jsonencode({
text_en = {
type = "custom"
tokenizer = "standard"
char_filter = "zero_width_spaces"
filter = ["lowercase", "minimal_english_stemmer"]
}
})

settings {
setting {
name = "number_of_replicas"
value = "2"
}
}

deletion_protection = false
}
Loading