From 104bac4c34c932767e536bfd1e7ab5c9201a9e17 Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Thu, 6 Jun 2019 13:48:04 +0200 Subject: [PATCH] Add support for index_lifecycle_policy resources --- diff_suppress_funcs.go | 20 +++ go.mod | 4 +- go.sum | 12 ++ provider.go | 17 +- ...ce_elasticsearch_index_lifecycle_policy.go | 158 ++++++++++++++++++ ...asticsearch_index_lifecycle_policy_test.go | 141 ++++++++++++++++ util.go | 18 ++ 7 files changed, 360 insertions(+), 10 deletions(-) create mode 100644 resource_elasticsearch_index_lifecycle_policy.go create mode 100644 resource_elasticsearch_index_lifecycle_policy_test.go diff --git a/diff_suppress_funcs.go b/diff_suppress_funcs.go index 3617bfd4..9d6afc2f 100644 --- a/diff_suppress_funcs.go +++ b/diff_suppress_funcs.go @@ -37,3 +37,23 @@ func suppressEquivalentJson(k, old, new string, d *schema.ResourceData) bool { } return reflect.DeepEqual(oldObj, newObj) } + +func diffSuppressIndexLifecyclePolicy(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 { + normalizeIndexLifecyclePolicy(om) + } + + if nm, ok := no.(map[string]interface{}); ok { + normalizeIndexLifecyclePolicy(nm) + } + + return reflect.DeepEqual(oo, no) +} diff --git a/go.mod b/go.mod index de3ed85e..3e96713d 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.6.2 // indirect github.com/hashicorp/terraform v0.12.0 github.com/olivere/elastic v6.2.18+incompatible - github.com/olivere/elastic/v7 v7.0.1 + github.com/olivere/elastic/v7 v7.0.5 gopkg.in/olivere/elastic.v5 v5.0.81 - gopkg.in/olivere/elastic.v6 v6.2.18 + gopkg.in/olivere/elastic.v6 v6.2.22 ) diff --git a/go.sum b/go.sum index b31d88ab..ebba5e18 100644 --- a/go.sum +++ b/go.sum @@ -106,6 +106,8 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -208,6 +210,8 @@ github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5 h1:0x4qcEHDpruK6ML github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe h1:W/GaMY0y69G4cFlmsC6B9sbuo2fP8OFP1ABjt4kPz+w= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= github.com/masterzen/winrm v0.0.0-20190223112901-5e5c9a7fe54b/go.mod h1:wr1VqkwW0AB5JS0QLy5GpVMS9E3VtRoSYXUYyVk46KY= @@ -260,6 +264,8 @@ github.com/olivere/elastic v6.2.18+incompatible h1:sd4eZY7YExzuvTz4tpBAvWY6go/SZ github.com/olivere/elastic v6.2.18+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8= github.com/olivere/elastic/v7 v7.0.1 h1:nPwkahx1Js+pILviQ9Cjl2O4Otfx0LhElnd30rEaGVQ= github.com/olivere/elastic/v7 v7.0.1/go.mod h1:h2vSaBKzz7eL+VsYPtIOXOURZlXmp+yY5MgyIW3Y/M0= +github.com/olivere/elastic/v7 v7.0.5 h1:A+kj32UgnUGoiVZfy84rjnYYgOcA9InugIb93La99/A= +github.com/olivere/elastic/v7 v7.0.5/go.mod h1:nut831m8vw5KQbQxX1oXjj3/buiDpDZc5pqNVdH9xYk= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -353,6 +359,8 @@ go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A= go.opencensus.io v0.19.2 h1:ZZpq6xI6kv/LuE/5s5UQvBU5vMjvRnPb8PvJrIntAnc= go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M= +go.opencensus.io v0.20.1 h1:pMEjRZ1M4ebWGikflH7nQpV6+Zr88KBMA2XJD3sbijw= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -438,6 +446,8 @@ google.golang.org/api v0.1.0 h1:K6z2u68e86TPdSdefXdzvXgR1zEMa+459vBSfWYAZkI= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= google.golang.org/api v0.2.0 h1:B5VXkdjt7K2Gm6fGBC9C9a1OAKJDT95cTqwet+2zib0= google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU= +google.golang.org/api v0.3.1 h1:oJra/lMfmtm13/rgY/8i3MzjFWYXvQIAKjQ3HqofMk8= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -469,6 +479,8 @@ gopkg.in/olivere/elastic.v5 v5.0.81 h1:21Vu9RMT2qXVLqXINtiOhwVPYz/87+Omsxh/Re+gK gopkg.in/olivere/elastic.v5 v5.0.81/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0= gopkg.in/olivere/elastic.v6 v6.2.18 h1:oy3daaY8S0eXi6G/HPwgQ6lw3NFVvjAxpMSCEHfuogg= gopkg.in/olivere/elastic.v6 v6.2.18/go.mod h1:2cTT8Z+/LcArSWpCgvZqBgt3VOqXiy7v00w12Lz8bd4= +gopkg.in/olivere/elastic.v6 v6.2.22 h1:kELB6519O38lz4RN6OzRzxB3RsXo2nA7ZCGPW0gjlaY= +gopkg.in/olivere/elastic.v6 v6.2.22/go.mod h1:2cTT8Z+/LcArSWpCgvZqBgt3VOqXiy7v00w12Lz8bd4= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/provider.go b/provider.go index 0041574d..2986a969 100644 --- a/provider.go +++ b/provider.go @@ -101,14 +101,15 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "elasticsearch_index_template": resourceElasticsearchIndexTemplate(), - "elasticsearch_snapshot_repository": resourceElasticsearchSnapshotRepository(), - "elasticsearch_kibana_object": resourceElasticsearchKibanaObject(), - "elasticsearch_watch": resourceElasticsearchWatch(), - "elasticsearch_monitor": resourceElasticsearchMonitor(), - "elasticsearch_destination": resourceElasticsearchDestination(), - "elasticsearch_xpack_role_mapping": resourceElasticsearchXpackRoleMapping(), - "elasticsearch_xpack_role": resourceElasticsearchXpackRole(), + "elasticsearch_index_template": resourceElasticsearchIndexTemplate(), + "elasticsearch_index_lifecycle_policy": resourceElasticsearchIndexLifecyclePolicy(), + "elasticsearch_snapshot_repository": resourceElasticsearchSnapshotRepository(), + "elasticsearch_kibana_object": resourceElasticsearchKibanaObject(), + "elasticsearch_watch": resourceElasticsearchWatch(), + "elasticsearch_monitor": resourceElasticsearchMonitor(), + "elasticsearch_destination": resourceElasticsearchDestination(), + "elasticsearch_xpack_role_mapping": resourceElasticsearchXpackRoleMapping(), + "elasticsearch_xpack_role": resourceElasticsearchXpackRole(), }, DataSourcesMap: map[string]*schema.Resource{ diff --git a/resource_elasticsearch_index_lifecycle_policy.go b/resource_elasticsearch_index_lifecycle_policy.go new file mode 100644 index 00000000..2c4637da --- /dev/null +++ b/resource_elasticsearch_index_lifecycle_policy.go @@ -0,0 +1,158 @@ +package main + +import ( + "context" + "encoding/json" + "errors" + + "github.com/hashicorp/terraform/helper/schema" + elastic7 "github.com/olivere/elastic/v7" + elastic6 "gopkg.in/olivere/elastic.v6" +) + +func resourceElasticsearchIndexLifecyclePolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceElasticsearchIndexLifecyclePolicyCreate, + Read: resourceElasticsearchIndexLifecyclePolicyRead, + Update: resourceElasticsearchIndexLifecyclePolicyUpdate, + Delete: resourceElasticsearchIndexLifecyclePolicyDelete, + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "body": &schema.Schema{ + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: diffSuppressIndexLifecyclePolicy, + }, + }, + } +} + +func resourceElasticsearchIndexLifecyclePolicyCreate(d *schema.ResourceData, meta interface{}) error { + err := resourceElasticsearchPutIndexLifecyclePolicy(d, meta) + if err != nil { + return err + } + d.SetId(d.Get("name").(string)) + return nil +} + +func resourceElasticsearchIndexLifecyclePolicyRead(d *schema.ResourceData, meta interface{}) error { + id := d.Id() + + var result string + var err error + switch meta.(type) { + case *elastic7.Client: + client := meta.(*elastic7.Client) + result, err = elastic7IndexGetLifecyclePolicy(client, id) + case *elastic6.Client: + client := meta.(*elastic6.Client) + result, err = elastic6IndexGetLifecyclePolicy(client, id) + default: + err = errors.New("Index Lifecycle Management is only supported by the elastic library >= v6!") + } + if err != nil { + return err + } + + d.Set("name", d.Id()) + d.Set("body", result) + return nil +} + +func elastic7IndexGetLifecyclePolicy(client *elastic7.Client, id string) (string, error) { + res, err := client.XPackIlmGetLifecycle().Policy(id).Do(context.TODO()) + if err != nil { + return "", err + } + + t := res[id] + tj, err := json.Marshal(t) + if err != nil { + return "", err + } + return string(tj), nil +} + +func elastic6IndexGetLifecyclePolicy(client *elastic6.Client, id string) (string, error) { + res, err := client.XPackIlmGetLifecycle().Policy(id).Do(context.TODO()) + if err != nil { + return "", err + } + + t := res[id] + tj, err := json.Marshal(t) + if err != nil { + return "", err + } + return string(tj), nil +} + +func resourceElasticsearchIndexLifecyclePolicyUpdate(d *schema.ResourceData, meta interface{}) error { + return resourceElasticsearchPutIndexLifecyclePolicy(d, meta) +} + +func resourceElasticsearchIndexLifecyclePolicyDelete(d *schema.ResourceData, meta interface{}) error { + id := d.Id() + + var err error + switch meta.(type) { + case *elastic7.Client: + client := meta.(*elastic7.Client) + err = elastic7IndexDeleteLifecyclePolicy(client, id) + case *elastic6.Client: + client := meta.(*elastic6.Client) + err = elastic6IndexDeleteLifecyclePolicy(client, id) + default: + err = errors.New("Index Lifecycle Management is only supported by the elastic library >= v6!") + } + + if err != nil { + return err + } + d.SetId("") + return nil +} + +func elastic7IndexDeleteLifecyclePolicy(client *elastic7.Client, id string) error { + _, err := client.XPackIlmDeleteLifecycle().Policy(id).Do(context.TODO()) + return err +} + +func elastic6IndexDeleteLifecyclePolicy(client *elastic6.Client, id string) error { + _, err := client.XPackIlmDeleteLifecycle().Policy(id).Do(context.TODO()) + return err +} + +func resourceElasticsearchPutIndexLifecyclePolicy(d *schema.ResourceData, meta interface{}) error { + name := d.Get("name").(string) + body := d.Get("body").(string) + + var err error + switch meta.(type) { + case *elastic7.Client: + client := meta.(*elastic7.Client) + err = elastic7IndexPutLifecyclePolicy(client, name, body) + case *elastic6.Client: + client := meta.(*elastic6.Client) + err = elastic6IndexPutLifecyclePolicy(client, name, body) + default: + err = errors.New("resourceElasticsearchPutIndexLifecyclePolicy Index Lifecycle Management is only supported by the elastic library >= v6!") + } + + return err +} + +func elastic7IndexPutLifecyclePolicy(client *elastic7.Client, name string, body string) error { + _, err := client.XPackIlmPutLifecycle().Policy(name).BodyString(body).Do(context.TODO()) + return err +} + +func elastic6IndexPutLifecyclePolicy(client *elastic6.Client, name string, body string) error { + _, err := client.XPackIlmPutLifecycle().Policy(name).BodyString(body).Do(context.TODO()) + return err +} diff --git a/resource_elasticsearch_index_lifecycle_policy_test.go b/resource_elasticsearch_index_lifecycle_policy_test.go new file mode 100644 index 00000000..8adcb21c --- /dev/null +++ b/resource_elasticsearch_index_lifecycle_policy_test.go @@ -0,0 +1,141 @@ +package main + +import ( + "context" + "errors" + "fmt" + "testing" + + elastic7 "github.com/olivere/elastic/v7" + elastic5 "gopkg.in/olivere/elastic.v5" + elastic6 "gopkg.in/olivere/elastic.v6" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccElasticsearchIndexLifecyclePolicy(t *testing.T) { + provider := Provider().(*schema.Provider) + err := provider.Configure(&terraform.ResourceConfig{}) + if err != nil { + t.Skipf("err: %s", err) + } + meta := provider.Meta() + var allowed bool + switch meta.(type) { + case *elastic5.Client: + allowed = false + default: + allowed = true + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + if !allowed { + t.Skip("Destinations only supported on ES >= 6") + } + }, + Providers: testAccXPackProviders, + CheckDestroy: testCheckElasticsearchIndexLifecyclePolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccElasticsearchIndexLifecyclePolicy, + Check: resource.ComposeTestCheckFunc( + testCheckElasticsearchIndexLifecyclePolicyExists("elasticsearch_index_lifecycle_policy.test"), + ), + }, + }, + }) +} + +func testCheckElasticsearchIndexLifecyclePolicyExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + if rs.Primary.ID == "" { + return fmt.Errorf("No index lifecycle policy ID is set") + } + + meta := testAccXPackProvider.Meta() + + var err error + switch meta.(type) { + case *elastic7.Client: + client := meta.(*elastic7.Client) + _, err = client.XPackIlmGetLifecycle().Policy(rs.Primary.ID).Do(context.TODO()) + case *elastic6.Client: + client := meta.(*elastic6.Client) + _, err = client.XPackIlmGetLifecycle().Policy(rs.Primary.ID).Do(context.TODO()) + default: + err = errors.New("Index Lifecycle Management is only supported by the elastic library >= v6!") + } + + if err != nil { + return err + } + + return nil + } +} + +func testCheckElasticsearchIndexLifecyclePolicyDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "elasticsearch_index_lifecycle_policy" { + continue + } + + meta := testAccXPackProvider.Meta() + + var err error + switch meta.(type) { + case *elastic7.Client: + client := meta.(*elastic7.Client) + _, err = client.XPackIlmGetLifecycle().Policy(rs.Primary.ID).Do(context.TODO()) + case *elastic6.Client: + client := meta.(*elastic6.Client) + _, err = client.XPackIlmGetLifecycle().Policy(rs.Primary.ID).Do(context.TODO()) + default: + err = errors.New("Index Lifecycle Management is only supported by the elastic library >= v6!") + } + + if err != nil { + return nil // should be not found error + } + + return fmt.Errorf("Index lifecycle policy %q still exists", rs.Primary.ID) + } + + return nil +} + +var testAccElasticsearchIndexLifecyclePolicy = ` +resource "elasticsearch_index_lifecycle_policy" "test" { + name = "terraform-test" + body = <