Skip to content
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

Add support for ElasticSearch 7.8+ component templates #139

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 20 additions & 0 deletions es/diff_suppress_funcs.go
Expand Up @@ -51,6 +51,26 @@ func diffSuppressComposableIndexTemplate(k, old, new string, d *schema.ResourceD
return reflect.DeepEqual(oo, no)
}

func diffSuppressComponentTemplate(k, old, new string, d *schema.ResourceData) bool {
var oo, no interface{}
if err := json.Unmarshal([]byte(old), &oo); err != nil {
return false
}
if err := json.Unmarshal([]byte(new), &no); err != nil {
return false
}

if om, ok := oo.(map[string]interface{}); ok {
normalizeComponentTemplate(om)
}

if nm, ok := no.(map[string]interface{}); ok {
normalizeComponentTemplate(nm)
}

return reflect.DeepEqual(oo, no)
}

func diffSuppressDestination(k, old, new string, d *schema.ResourceData) bool {
var oo, no interface{}
if err := json.Unmarshal([]byte(old), &oo); err != nil {
Expand Down
1 change: 1 addition & 0 deletions es/provider.go
Expand Up @@ -169,6 +169,7 @@ func Provider() terraform.ResourceProvider {
"elasticsearch_index_lifecycle_policy": resourceElasticsearchDeprecatedIndexLifecyclePolicy(),
"elasticsearch_index_template": resourceElasticsearchIndexTemplate(),
"elasticsearch_composable_index_template": resourceElasticsearchComposableIndexTemplate(),
"elasticsearch_component_template": resourceElasticsearchComponentTemplate(),
"elasticsearch_ingest_pipeline": resourceElasticsearchIngestPipeline(),
"elasticsearch_kibana_object": resourceElasticsearchKibanaObject(),
"elasticsearch_monitor": resourceElasticsearchDeprecatedMonitor(),
Expand Down
178 changes: 178 additions & 0 deletions es/resource_elasticsearch_component_template.go
@@ -0,0 +1,178 @@
package es

import (
"context"
"encoding/json"
"fmt"
"log"

"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
elastic7 "github.com/olivere/elastic/v7"
)

var componentTemplateMinimalVersion, _ = version.NewVersion("7.8.0")

func resourceElasticsearchComponentTemplate() *schema.Resource {
return &schema.Resource{
Create: resourceElasticsearchComponentTemplateCreate,
Read: resourceElasticsearchComponentTemplateRead,
Update: resourceElasticsearchComponentTemplateUpdate,
Delete: resourceElasticsearchComponentTemplateDelete,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
ForceNew: true,
Required: true,
},
"body": {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: diffSuppressComponentTemplate,
ValidateFunc: validation.StringIsJSON,
},
},
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
}
}

func resourceElasticsearchComponentTemplateCreate(d *schema.ResourceData, meta interface{}) error {
err := resourceElasticsearchPutComponentTemplate(d, meta, true)
if err != nil {
return err
}
d.SetId(d.Get("name").(string))
return nil
}

func resourceElasticsearchComponentTemplateRead(d *schema.ResourceData, meta interface{}) error {
id := d.Id()

var result string
var elasticVersion *version.Version

esClient, err := getClient(meta.(*ProviderConf))
if err != nil {
return err
}

switch client := esClient.(type) {
case *elastic7.Client:
elasticVersion, err = elastic7GetVersion(client)
if err == nil {
if elasticVersion.LessThan(componentTemplateMinimalVersion) {
err = fmt.Errorf("component_template endpoint only available from ElasticSearch >= 7.8, got version %s", elasticVersion.String())
} else {
result, err = elastic7GetComponentTemplate(client, id)
}
}
default:
err = fmt.Errorf("component_template endpoint only available from ElasticSearch >= 7.8, got version < 7.0.0")
}
if err != nil {
if elastic7.IsNotFound(err) {
log.Printf("[WARN] Index template (%s) not found, removing from state", id)
d.SetId("")
return nil
}

return err
}

ds := &resourceDataSetter{d: d}
ds.set("name", d.Id())
ds.set("body", result)
return ds.err
}

func elastic7GetComponentTemplate(client *elastic7.Client, id string) (string, error) {
res, err := client.IndexGetComponentTemplate(id).Do(context.TODO())
if err != nil {
return "", err
}

// No more than 1 element is expected, if the index template is not found, previous call should
// return a 404 error
t := res.ComponentTemplates[0].ComponentTemplate
tj, err := json.Marshal(t)
if err != nil {
return "", err
}
return string(tj), nil
}

func resourceElasticsearchComponentTemplateUpdate(d *schema.ResourceData, meta interface{}) error {
return resourceElasticsearchPutComponentTemplate(d, meta, false)
}

func resourceElasticsearchComponentTemplateDelete(d *schema.ResourceData, meta interface{}) error {
id := d.Id()

var elasticVersion *version.Version

esClient, err := getClient(meta.(*ProviderConf))
if err != nil {
return err
}

switch client := esClient.(type) {
case *elastic7.Client:
elasticVersion, err = elastic7GetVersion(client)
if err == nil {
if elasticVersion.LessThan(componentTemplateMinimalVersion) {
err = fmt.Errorf("component_template endpoint only available from ElasticSearch >= 7.8, got version %s", elasticVersion.String())
} else {
err = elastic7DeleteComponentTemplate(client, id)
}
}
default:
err = fmt.Errorf("component_template endpoint only available from ElasticSearch >= 7.8, got version < 7.0.0")
}

if err != nil {
return err
}
d.SetId("")
return nil
}

func elastic7DeleteComponentTemplate(client *elastic7.Client, id string) error {
_, err := client.IndexDeleteComponentTemplate(id).Do(context.TODO())
return err
}

func resourceElasticsearchPutComponentTemplate(d *schema.ResourceData, meta interface{}, create bool) error {
name := d.Get("name").(string)
body := d.Get("body").(string)

var elasticVersion *version.Version

esClient, err := getClient(meta.(*ProviderConf))
if err != nil {
return err
}

switch client := esClient.(type) {
case *elastic7.Client:
elasticVersion, err = elastic7GetVersion(client)
if err == nil {
if elasticVersion.LessThan(componentTemplateMinimalVersion) {
err = fmt.Errorf("component_template endpoint only available from ElasticSearch >= 7.8, got version %s", elasticVersion.String())
} else {
err = elastic7PutComponentTemplate(client, name, body, create)
}
}
default:
err = fmt.Errorf("component_template endpoint only available from ElasticSearch >= 7.8, got version < 7.0.0")
}

return err
}

func elastic7PutComponentTemplate(client *elastic7.Client, name string, body string, create bool) error {
_, err := client.IndexPutComponentTemplate(name).BodyString(body).Create(create).Do(context.TODO())
return err
}