internal/elasticsearch/index/component_template.go (228 lines of code) (raw):

package index import ( "context" "encoding/json" "fmt" "strings" "github.com/elastic/terraform-provider-elasticstack/internal/clients" "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/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" ) func ResourceComponentTemplate() *schema.Resource { // NOTE: component_template and index_template uses the same schema componentTemplateSchema := map[string]*schema.Schema{ "id": { Description: "Internal identifier of the resource", Type: schema.TypeString, Computed: true, }, "name": { Description: "Name of the component template to create.", Type: schema.TypeString, Required: true, ForceNew: true, }, "metadata": { Description: "Optional user metadata about the component template.", Type: schema.TypeString, Optional: true, ValidateFunc: validation.StringIsJSON, DiffSuppressFunc: utils.DiffJsonSuppress, }, "template": { Description: "Template to be applied. It may optionally include an aliases, mappings, or settings configuration.", Type: schema.TypeList, Required: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "alias": { Description: "Alias to add.", Type: schema.TypeSet, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { Description: "The alias name. Index alias names support date math. See, https://www.elastic.co/guide/en/elasticsearch/reference/current/date-math-index-names.html", Type: schema.TypeString, Required: true, }, "filter": { Description: "Query used to limit documents the alias can access.", Type: schema.TypeString, Optional: true, DiffSuppressFunc: utils.DiffJsonSuppress, ValidateFunc: validation.StringIsJSON, }, "index_routing": { Description: "Value used to route indexing operations to a specific shard. If specified, this overwrites the routing value for indexing operations.", Type: schema.TypeString, Optional: true, }, "is_hidden": { Description: "If true, the alias is hidden.", Type: schema.TypeBool, Optional: true, Default: false, }, "is_write_index": { Description: "If true, the index is the write index for the alias.", Type: schema.TypeBool, Optional: true, Default: false, }, "routing": { Description: "Value used to route indexing and search operations to a specific shard.", Type: schema.TypeString, Optional: true, }, "search_routing": { Description: "Value used to route search operations to a specific shard. If specified, this overwrites the routing value for search operations.", Type: schema.TypeString, Optional: true, }, }, }, }, "mappings": { Description: "Mapping for fields in the index. Should be specified as a JSON object of field mappings. See the documentation (https://www.elastic.co/guide/en/elasticsearch/reference/current/explicit-mapping.html) for more details", Type: schema.TypeString, Optional: true, DiffSuppressFunc: utils.DiffJsonSuppress, ValidateFunc: validation.All( validation.StringIsJSON, stringIsJSONObject, ), }, "settings": { Description: "Configuration options for the index. See, https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#index-modules-settings", Type: schema.TypeString, Optional: true, DiffSuppressFunc: utils.DiffIndexSettingSuppress, ValidateFunc: validation.All( validation.StringIsJSON, stringIsJSONObject, ), }, }, }, }, "version": { Description: "Version number used to manage component templates externally.", Type: schema.TypeInt, Optional: true, }, } utils.AddConnectionSchema(componentTemplateSchema) return &schema.Resource{ Description: "Creates or updates a component template. Component templates are building blocks for constructing index templates that specify index mappings, settings, and aliases. See, https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-component-template.html", CreateContext: resourceComponentTemplatePut, UpdateContext: resourceComponentTemplatePut, ReadContext: resourceComponentTemplateRead, DeleteContext: resourceComponentTemplateDelete, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, Schema: componentTemplateSchema, } } func resourceComponentTemplatePut(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client, diags := clients.NewApiClientFromSDKResource(d, meta) if diags.HasError() { return diags } componentId := d.Get("name").(string) id, diags := client.ID(ctx, componentId) if diags.HasError() { return diags } var componentTemplate models.ComponentTemplate componentTemplate.Name = componentId if v, ok := d.GetOk("metadata"); ok { metadata := make(map[string]interface{}) if err := json.NewDecoder(strings.NewReader(v.(string))).Decode(&metadata); err != nil { return diag.FromErr(err) } componentTemplate.Meta = metadata } if v, ok := d.GetOk("template"); ok { templ, ok, diags := expandTemplate(v) if diags != nil { return diags } if ok { componentTemplate.Template = &templ } } if v, ok := d.GetOk("version"); ok { definedVer := v.(int) componentTemplate.Version = &definedVer } if diags := elasticsearch.PutComponentTemplate(ctx, client, &componentTemplate); diags.HasError() { return diags } d.SetId(id.String()) return resourceComponentTemplateRead(ctx, d, meta) } func resourceComponentTemplateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client, diags := clients.NewApiClientFromSDKResource(d, meta) if diags.HasError() { return diags } compId, diags := clients.CompositeIdFromStr(d.Id()) if diags.HasError() { return diags } templateId := compId.ResourceId tpl, diags := elasticsearch.GetComponentTemplate(ctx, client, templateId) if tpl == nil && diags == nil { tflog.Warn(ctx, fmt.Sprintf(`Component template "%s" not found, removing from state`, compId.ResourceId)) d.SetId("") return diags } if diags.HasError() { return diags } // set the fields if err := d.Set("name", tpl.Name); err != nil { return diag.FromErr(err) } if tpl.ComponentTemplate.Meta != nil { metadata, err := json.Marshal(tpl.ComponentTemplate.Meta) if err != nil { return diag.FromErr(err) } if err := d.Set("metadata", string(metadata)); err != nil { return diag.FromErr(err) } } if tpl.ComponentTemplate.Template != nil { template, diags := flattenTemplateData(tpl.ComponentTemplate.Template) if diags.HasError() { return diags } if err := d.Set("template", template); err != nil { return diag.FromErr(err) } } if err := d.Set("version", tpl.ComponentTemplate.Version); err != nil { return diag.FromErr(err) } return diags } func resourceComponentTemplateDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client, diags := clients.NewApiClientFromSDKResource(d, meta) if diags.HasError() { return diags } id := d.Id() compId, diags := clients.CompositeIdFromStr(id) if diags.HasError() { return diags } if diags := elasticsearch.DeleteComponentTemplate(ctx, client, compId.ResourceId); diags.HasError() { return diags } return diags }