Skip to content

Adding ignore_missing_component_templates #1206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jul 22, 2025
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## [Unreleased]

- Add `ignore_missing_component_templates` to `elasticstack_elasticsearch_index_template` ([#1206](https://github.com/elastic/terraform-provider-elasticstack/pull/1206))

## [0.11.17] - 2025-07-21

- Add `elasticstack_apm_agent_configuration` resource ([#1196](https://github.com/elastic/terraform-provider-elasticstack/pull/1196))
Expand Down
1 change: 1 addition & 0 deletions docs/data-sources/elasticsearch_index_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ output "template" {
- `composed_of` (List of String) An ordered list of component template names.
- `data_stream` (List of Object) If this object is included, the template is used to create data streams and their backing indices. Supports an empty object. (see [below for nested schema](#nestedatt--data_stream))
- `id` (String) Internal identifier of the resource
- `ignore_missing_component_templates` (List of String) A list of component template names that are ignored if missing.
- `index_patterns` (Set of String) Array of wildcard (*) expressions used to match the names of data streams and indices during creation.
- `metadata` (String) Optional user metadata about the index template.
- `priority` (Number) Priority to determine index template precedence when a new data stream or index is created.
Expand Down
1 change: 1 addition & 0 deletions docs/resources/elasticsearch_index_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ resource "elasticstack_elasticsearch_index_template" "my_data_stream" {
- `composed_of` (List of String) An ordered list of component template names.
- `data_stream` (Block List, Max: 1) If this object is included, the template is used to create data streams and their backing indices. Supports an empty object. (see [below for nested schema](#nestedblock--data_stream))
- `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))
- `ignore_missing_component_templates` (List of String) A list of component template names that are ignored if missing.
- `metadata` (String) Optional user metadata about the index template.
- `priority` (Number) Priority to determine index template precedence when a new data stream or index is created.
- `template` (Block List, Max: 1) Template to be applied. It may optionally include an aliases, mappings, lifecycle, or settings configuration. (see [below for nested schema](#nestedblock--template))
Expand Down
35 changes: 35 additions & 0 deletions internal/elasticsearch/index/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ import (
"github.com/elastic/terraform-provider-elasticstack/internal/clients/elasticsearch"
"github.com/elastic/terraform-provider-elasticstack/internal/models"
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

var (
MinSupportedIgnoreMissingComponentTemplateVersion = version.Must(version.NewVersion("8.7.0"))
)

func ResourceTemplate() *schema.Resource {
templateSchema := map[string]*schema.Schema{
"id": {
Expand All @@ -38,6 +43,15 @@ func ResourceTemplate() *schema.Resource {
Type: schema.TypeString,
},
},
"ignore_missing_component_templates": {
Description: "A list of component template names that are ignored if missing.",
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"data_stream": {
Description: "If this object is included, the template is used to create data streams and their backing indices. Supports an empty object.",
Type: schema.TypeList,
Expand Down Expand Up @@ -210,6 +224,12 @@ func resourceIndexTemplatePut(ctx context.Context, d *schema.ResourceData, meta
if diags.HasError() {
return diags
}

serverVersion, diags := client.ServerVersion(ctx)
if diags.HasError() {
return diags
}

var indexTemplate models.IndexTemplate
indexTemplate.Name = templateId

Expand All @@ -221,6 +241,18 @@ func resourceIndexTemplatePut(ctx context.Context, d *schema.ResourceData, meta
}
indexTemplate.ComposedOf = compsOf

if v, ok := d.GetOk("ignore_missing_component_templates"); ok {
compsOfIgnore := make([]string, 0)
for _, c := range v.([]interface{}) {
compsOfIgnore = append(compsOfIgnore, c.(string))
}

if len(compsOfIgnore) > 0 && serverVersion.LessThan(MinSupportedIgnoreMissingComponentTemplateVersion) {
return diag.FromErr(fmt.Errorf("'ignore_missing_component_templates' is supported only for Elasticsearch v%s and above", MinSupportedIgnoreMissingComponentTemplateVersion.String()))
}
indexTemplate.IgnoreMissingComponentTemplates = compsOfIgnore
}

if v, ok := d.GetOk("data_stream"); ok {
// 8.x workaround
hasAllowCustomRouting := false
Expand Down Expand Up @@ -371,6 +403,9 @@ 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 err := d.Set("ignore_missing_component_templates", tpl.IndexTemplate.IgnoreMissingComponentTemplates); err != nil {
return diag.FromErr(err)
}
if stream := tpl.IndexTemplate.DataStream; stream != nil {
ds := make([]interface{}, 1)
dSettings := make(map[string]interface{})
Expand Down
8 changes: 8 additions & 0 deletions internal/elasticsearch/index/template_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ func DataSourceTemplate() *schema.Resource {
Type: schema.TypeString,
},
},
"ignore_missing_component_templates": {
Description: "A list of component template names that are ignored if missing.",
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"data_stream": {
Description: "If this object is included, the template is used to create data streams and their backing indices. Supports an empty object.",
Type: schema.TypeList,
Expand Down
32 changes: 32 additions & 0 deletions internal/elasticsearch/index/template_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import (
"testing"

"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
"github.com/elastic/terraform-provider-elasticstack/internal/elasticsearch/index"
"github.com/elastic/terraform-provider-elasticstack/internal/versionutils"
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccIndexTemplateDataSource(t *testing.T) {
// generate a random role name
templateName := "test-template-" + sdkacctest.RandStringFromCharSet(10, sdkacctest.CharSetAlphaNum)
templateNameComponent := "test-template-" + sdkacctest.RandStringFromCharSet(10, sdkacctest.CharSetAlphaNum)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Expand All @@ -25,6 +28,16 @@ func TestAccIndexTemplateDataSource(t *testing.T) {
resource.TestCheckResourceAttr("data.elasticstack_elasticsearch_index_template.test", "priority", "100"),
),
},
{
SkipFunc: versionutils.CheckIfVersionIsUnsupported(index.MinSupportedIgnoreMissingComponentTemplateVersion),
Config: testAccIndexTemplateDataSourceWithIgnoreComponentConfig(templateNameComponent),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.elasticstack_elasticsearch_index_template.test_component", "name", templateNameComponent),
resource.TestCheckTypeSetElemAttr("data.elasticstack_elasticsearch_index_template.test_component", "index_patterns.*", fmt.Sprintf("tf-acc-component-%s-*", templateNameComponent)),
resource.TestCheckTypeSetElemAttr("data.elasticstack_elasticsearch_index_template.test_component", "composed_of.*", fmt.Sprintf("%s-logscomponent@custom", templateNameComponent)),
resource.TestCheckTypeSetElemAttr("data.elasticstack_elasticsearch_index_template.test_component", "ignore_missing_component_templates.*", fmt.Sprintf("%s-logscomponent@custom", templateNameComponent)),
),
},
},
})
}
Expand All @@ -47,3 +60,22 @@ data "elasticstack_elasticsearch_index_template" "test" {
}
`, templateName, templateName)
}

func testAccIndexTemplateDataSourceWithIgnoreComponentConfig(templateName string) string {
return fmt.Sprintf(`
provider "elasticstack" {
elasticsearch {}
}
resource "elasticstack_elasticsearch_index_template" "test_component" {
name = "%s"
index_patterns = ["tf-acc-component-%s-*"]
composed_of = ["%s-logscomponent@custom"]
ignore_missing_component_templates = ["%s-logscomponent@custom"]
}
data "elasticstack_elasticsearch_index_template" "test_component" {
name = elasticstack_elasticsearch_index_template.test_component.name
}
`, templateName, templateName, templateName, templateName)
}
58 changes: 58 additions & 0 deletions internal/elasticsearch/index/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
"github.com/elastic/terraform-provider-elasticstack/internal/elasticsearch/index"
"github.com/elastic/terraform-provider-elasticstack/internal/versionutils"
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
Expand All @@ -14,6 +16,7 @@ import (
func TestAccResourceIndexTemplate(t *testing.T) {
// generate random template name
templateName := sdkacctest.RandStringFromCharSet(10, sdkacctest.CharSetAlphaNum)
templateNameComponent := sdkacctest.RandStringFromCharSet(10, sdkacctest.CharSetAlphaNum)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Expand Down Expand Up @@ -41,6 +44,26 @@ func TestAccResourceIndexTemplate(t *testing.T) {
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test2", "data_stream.0.hidden", "false"),
),
},
{
SkipFunc: versionutils.CheckIfVersionIsUnsupported(index.MinSupportedIgnoreMissingComponentTemplateVersion),
Config: testAccResourceIndexTemplateCreateWithIgnoreComponent(templateNameComponent),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test_component", "name", templateNameComponent),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_index_template.test_component", "index_patterns.*", fmt.Sprintf("%s-logscomponent-*", templateNameComponent)),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_index_template.test_component", "composed_of.*", fmt.Sprintf("%s-logscomponent@custom", templateNameComponent)),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_index_template.test_component", "ignore_missing_component_templates.*", fmt.Sprintf("%s-logscomponent@custom", templateNameComponent)),
),
},
{
SkipFunc: versionutils.CheckIfVersionIsUnsupported(index.MinSupportedIgnoreMissingComponentTemplateVersion),
Config: testAccResourceIndexTemplateUpdateWithIgnoreComponent(templateNameComponent),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_index_template.test_component", "name", templateNameComponent),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_index_template.test_component", "index_patterns.*", fmt.Sprintf("%s-logscomponent-*", templateNameComponent)),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_index_template.test_component", "composed_of.*", fmt.Sprintf("%s-logscomponent-updated@custom", templateNameComponent)),
resource.TestCheckTypeSetElemAttr("elasticstack_elasticsearch_index_template.test_component", "ignore_missing_component_templates.*", fmt.Sprintf("%s-logscomponent-updated@custom", templateNameComponent)),
),
},
},
})
}
Expand Down Expand Up @@ -117,6 +140,41 @@ resource "elasticstack_elasticsearch_index_template" "test2" {
`, name, name, name)
}

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

resource "elasticstack_elasticsearch_index_template" "test_component" {
name = "%s"
index_patterns = ["%s-logscomponent-*"]

composed_of = ["%s-logscomponent@custom"]
ignore_missing_component_templates = ["%s-logscomponent@custom"]
}
`, name, name, name, name)
}

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

resource "elasticstack_elasticsearch_index_template" "test_component" {
name = "%s"
index_patterns = ["%s-logscomponent-*"]

composed_of = ["%s-logscomponent-updated@custom"]
ignore_missing_component_templates = ["%s-logscomponent-updated@custom"]

template {
}
}
`, name, name, name, name)
}

func checkResourceIndexTemplateDestroy(s *terraform.State) error {
client, err := clients.NewAcceptanceTestingClient()
if err != nil {
Expand Down
21 changes: 11 additions & 10 deletions internal/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,17 @@ type Application struct {
}

type IndexTemplate struct {
Name string `json:"-"`
Create bool `json:"-"`
Timeout string `json:"-"`
ComposedOf []string `json:"composed_of"`
DataStream *DataStreamSettings `json:"data_stream,omitempty"`
IndexPatterns []string `json:"index_patterns"`
Meta map[string]interface{} `json:"_meta,omitempty"`
Priority *int `json:"priority,omitempty"`
Template *Template `json:"template,omitempty"`
Version *int `json:"version,omitempty"`
Name string `json:"-"`
Create bool `json:"-"`
Timeout string `json:"-"`
ComposedOf []string `json:"composed_of"`
IgnoreMissingComponentTemplates []string `json:"ignore_missing_component_templates,omitempty"`
DataStream *DataStreamSettings `json:"data_stream,omitempty"`
IndexPatterns []string `json:"index_patterns"`
Meta map[string]interface{} `json:"_meta,omitempty"`
Priority *int `json:"priority,omitempty"`
Template *Template `json:"template,omitempty"`
Version *int `json:"version,omitempty"`
}

type DataStreamSettings struct {
Expand Down