diff --git a/CHANGELOG.md b/CHANGELOG.md index 05175b131..f15c973b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## [Unreleased] +### Fixed + +- Prevent a provider panic when an `elasticstack_elasticsearch_template` or `elasticstack_elasticsearch_component_template` includes an empty `template` (`template {}`) block. ([#598](https://github.com/elastic/terraform-provider-elasticstack/pull/598)) + ## [0.11.2] - 2024-03-13 ### Fixed diff --git a/internal/elasticsearch/index/component_template.go b/internal/elasticsearch/index/component_template.go index 8d0448dd8..52f419e44 100644 --- a/internal/elasticsearch/index/component_template.go +++ b/internal/elasticsearch/index/component_template.go @@ -156,62 +156,14 @@ func resourceComponentTemplatePut(ctx context.Context, d *schema.ResourceData, m } if v, ok := d.GetOk("template"); ok { - // only one template block allowed to be declared - definedTempl := v.([]interface{})[0].(map[string]interface{}) - definedAliases := definedTempl["alias"].(*schema.Set) - templ := models.Template{} - - aliases := make(map[string]models.IndexAlias, definedAliases.Len()) - for _, a := range definedAliases.List() { - alias := a.(map[string]interface{}) - templAlias := models.IndexAlias{} - - if f, ok := alias["filter"]; ok { - if f.(string) != "" { - filterMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(f.(string)), &filterMap); err != nil { - return diag.FromErr(err) - } - templAlias.Filter = filterMap - } - } - if ir, ok := alias["index_routing"]; ok { - templAlias.IndexRouting = ir.(string) - } - templAlias.IsHidden = alias["is_hidden"].(bool) - templAlias.IsWriteIndex = alias["is_write_index"].(bool) - if r, ok := alias["routing"]; ok { - templAlias.Routing = r.(string) - } - if sr, ok := alias["search_routing"]; ok { - templAlias.SearchRouting = sr.(string) - } - - aliases[alias["name"].(string)] = templAlias - } - templ.Aliases = aliases - - if mappings, ok := definedTempl["mappings"]; ok { - if mappings.(string) != "" { - maps := make(map[string]interface{}) - if err := json.Unmarshal([]byte(mappings.(string)), &maps); err != nil { - return diag.FromErr(err) - } - templ.Mappings = maps - } + templ, ok, diags := expandTemplate(v) + if diags != nil { + return diags } - if settings, ok := definedTempl["settings"]; ok { - if settings.(string) != "" { - sets := make(map[string]interface{}) - if err := json.Unmarshal([]byte(settings.(string)), &sets); err != nil { - return diag.FromErr(err) - } - templ.Settings = sets - } + if ok { + componentTemplate.Template = &templ } - - componentTemplate.Template = &templ } if v, ok := d.GetOk("version"); ok { diff --git a/internal/elasticsearch/index/template.go b/internal/elasticsearch/index/template.go index 9df3b649f..3d079dcd1 100644 --- a/internal/elasticsearch/index/template.go +++ b/internal/elasticsearch/index/template.go @@ -257,37 +257,14 @@ func resourceIndexTemplatePut(ctx context.Context, d *schema.ResourceData, meta } if v, ok := d.GetOk("template"); ok { - templ := models.Template{} - // only one template block allowed to be declared - definedTempl := v.([]interface{})[0].(map[string]interface{}) - - aliases, diags := ExpandIndexAliases(definedTempl["alias"].(*schema.Set)) - if diags.HasError() { + templ, ok, diags := expandTemplate(v) + if diags != nil { return diags } - templ.Aliases = aliases - - if mappings, ok := definedTempl["mappings"]; ok { - if mappings.(string) != "" { - maps := make(map[string]interface{}) - if err := json.Unmarshal([]byte(mappings.(string)), &maps); err != nil { - return diag.FromErr(err) - } - templ.Mappings = maps - } - } - if settings, ok := definedTempl["settings"]; ok { - if settings.(string) != "" { - sets := make(map[string]interface{}) - if err := json.Unmarshal([]byte(settings.(string)), &sets); err != nil { - return diag.FromErr(err) - } - templ.Settings = sets - } + if ok { + indexTemplate.Template = &templ } - - indexTemplate.Template = &templ } if v, ok := d.GetOk("version"); ok { @@ -303,6 +280,43 @@ func resourceIndexTemplatePut(ctx context.Context, d *schema.ResourceData, meta return resourceIndexTemplateRead(ctx, d, meta) } +func expandTemplate(config interface{}) (models.Template, bool, diag.Diagnostics) { + templ := models.Template{} + // only one template block allowed to be declared + definedTempl, ok := config.([]interface{})[0].(map[string]interface{}) + if !ok { + return templ, false, nil + } + + aliases, diags := ExpandIndexAliases(definedTempl["alias"].(*schema.Set)) + if diags.HasError() { + return templ, false, diags + } + templ.Aliases = aliases + + if mappings, ok := definedTempl["mappings"]; ok { + if mappings.(string) != "" { + maps := make(map[string]interface{}) + if err := json.Unmarshal([]byte(mappings.(string)), &maps); err != nil { + return templ, false, diag.FromErr(err) + } + templ.Mappings = maps + } + } + + if settings, ok := definedTempl["settings"]; ok { + if settings.(string) != "" { + sets := make(map[string]interface{}) + if err := json.Unmarshal([]byte(settings.(string)), &sets); err != nil { + return templ, false, diag.FromErr(err) + } + templ.Settings = sets + } + } + + return templ, true, nil +} + func resourceIndexTemplateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client, diags := clients.NewApiClientFromSDKResource(d, meta) if diags.HasError() { diff --git a/internal/elasticsearch/index/template_test.go b/internal/elasticsearch/index/template_test.go index c3f0cd657..e0d3ce7a4 100644 --- a/internal/elasticsearch/index/template_test.go +++ b/internal/elasticsearch/index/template_test.go @@ -111,6 +111,8 @@ resource "elasticstack_elasticsearch_index_template" "test2" { data_stream { hidden = false } + + template {} } `, name, name, name) }