Skip to content

Commit

Permalink
Add support for ElasticSearch 7.8+ component templates
Browse files Browse the repository at this point in the history
Signed-off-by: Yann Soubeyrand <yann.soubeyrand@camptocamp.com>
  • Loading branch information
yann-soubeyrand committed Feb 4, 2021
1 parent 116c9ff commit e556f3c
Show file tree
Hide file tree
Showing 7 changed files with 405 additions and 15 deletions.
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
}

0 comments on commit e556f3c

Please sign in to comment.