Skip to content

Commit ba0d2b8

Browse files
committed
Allow updates to mappings on live indices
1 parent 4e08f24 commit ba0d2b8

File tree

4 files changed

+88
-46
lines changed

4 files changed

+88
-46
lines changed

es/resource_elasticsearch_index.go

Lines changed: 84 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1212
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
13+
"github.com/nsf/jsondiff"
1314

1415
elastic7 "github.com/olivere/elastic/v7"
1516
elastic6 "gopkg.in/olivere/elastic.v6"
@@ -355,7 +356,6 @@ var (
355356
Type: schema.TypeString,
356357
Description: "A JSON string defining how documents in the index, and the fields they contain, are stored and indexed. To avoid the complexities of field mapping updates, updates of this field are not allowed via this provider. See the upstream [Elasticsearch docs](https://www.elastic.co/guide/en/elasticsearch/reference/6.8/indices-put-mapping.html#updating-field-mappings) for more details.",
357358
Optional: true,
358-
ForceNew: true,
359359
ValidateFunc: validation.StringIsJSON,
360360
},
361361
"aliases": {
@@ -670,52 +670,92 @@ func allowIndexDestroy(indexName string, d *schema.ResourceData, meta interface{
670670
}
671671

672672
func resourceElasticsearchIndexUpdate(d *schema.ResourceData, meta interface{}) error {
673-
settings := make(map[string]interface{})
674-
for _, key := range settingsKeys {
675-
schemaName := strings.Replace(key, ".", "_", -1)
676-
if d.HasChange(schemaName) {
677-
settings[key] = d.Get(schemaName)
678-
}
679-
}
680-
681-
// if we're not changing any settings, no-op this function
682-
if len(settings) == 0 {
683-
return resourceElasticsearchIndexRead(d, meta)
684-
}
685-
686-
body := map[string]interface{}{
687-
// Note you do not have to explicitly specify the `index` section inside
688-
// the `settings` section
689-
"settings": settings,
690-
}
691-
692-
var (
693-
name = d.Id()
694-
ctx = context.Background()
695-
err error
696-
)
673+
var err error
674+
settings := make(map[string]interface{})
675+
for _, key := range settingsKeys {
676+
schemaName := strings.Replace(key, ".", "_", -1)
677+
if d.HasChange(schemaName) {
678+
settings[key] = d.Get(schemaName)
679+
}
680+
}
681+
682+
o, n := d.GetChange("mappings")
683+
difference, _ := jsondiff.Compare([]byte(n.(string)), []byte(o.(string)), &jsondiff.Options{})
684+
685+
// if we're not changing any settings, no-op this function
686+
if len(settings) == 0 && difference == jsondiff.FullMatch {
687+
return resourceElasticsearchIndexRead(d, meta)
688+
}
689+
690+
if len(settings) != 0 {
691+
err = updateIndexSettings(d, meta, settings)
692+
}
693+
if err != nil {
694+
return err
695+
}
696+
697+
if difference == jsondiff.SupersetMatch {
698+
err = updateIndexMappings(d, meta, n.(string))
699+
}
700+
if err != nil {
701+
return err
702+
}
703+
704+
return resourceElasticsearchIndexRead(d, meta.(*ProviderConf))
705+
}
697706

698-
if alias, ok := d.GetOk("rollover_alias"); ok {
699-
name = getWriteIndexByAlias(alias.(string), d, meta)
700-
}
707+
func updateIndexSettings(d *schema.ResourceData, meta interface{}, settings map[string]interface{}) error {
708+
body := map[string]interface{}{
709+
// Note you do not have to explicitly specify the `index` section inside
710+
// the `settings` section
711+
"settings": settings,
712+
}
713+
714+
var (
715+
name = d.Id()
716+
ctx = context.Background()
717+
err error
718+
)
719+
720+
if alias, ok := d.GetOk("rollover_alias"); ok {
721+
name = getWriteIndexByAlias(alias.(string), d, meta)
722+
}
723+
724+
esClient, err := getClient(meta.(*ProviderConf))
725+
if err != nil {
726+
return err
727+
}
728+
switch client := esClient.(type) {
729+
case *elastic7.Client:
730+
_, err = client.IndexPutSettings(name).BodyJson(body).Do(ctx)
731+
case *elastic6.Client:
732+
_, err = client.IndexPutSettings(name).BodyJson(body).Do(ctx)
733+
default:
734+
return errors.New("Elasticsearch version not supported")
735+
}
736+
return err
737+
}
701738

702-
esClient, err := getClient(meta.(*ProviderConf))
703-
if err != nil {
704-
return err
705-
}
706-
switch client := esClient.(type) {
707-
case *elastic7.Client:
708-
_, err = client.IndexPutSettings(name).BodyJson(body).Do(ctx)
709-
case *elastic6.Client:
710-
_, err = client.IndexPutSettings(name).BodyJson(body).Do(ctx)
711-
default:
712-
return errors.New("Elasticsearch version not supported")
713-
}
739+
func updateIndexMappings(d *schema.ResourceData, meta interface{}, mapping string) error {
740+
var (
741+
name = d.Id()
742+
ctx = context.Background()
743+
err error
744+
)
745+
esClient, err := getClient(meta.(*ProviderConf))
746+
if err != nil {
747+
return err
748+
}
749+
switch client := esClient.(type) {
750+
case *elastic7.Client:
751+
_, err = client.PutMapping().Index(name).BodyString(mapping).Do(ctx)
752+
case *elastic6.Client:
753+
_, err = client.PutMapping().Index(name).BodyString(mapping).Do(ctx)
754+
default:
755+
return errors.New("Elasticsearch version not supported")
756+
}
714757

715-
if err == nil {
716-
return resourceElasticsearchIndexRead(d, meta.(*ProviderConf))
717-
}
718-
return err
758+
return err
719759
}
720760

721761
func getWriteIndexByAlias(alias string, d *schema.ResourceData, meta interface{}) string {

es/resource_elasticsearch_index_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,8 @@ func TestAccElasticsearchIndex_mapping(t *testing.T) {
505505
checkElasticsearchIndexMapping("terraform-test", func(s *terraform.State, mapping map[string]interface{}) error {
506506
initialUUID, err = getElasticsearchIndexUUID("elasticsearch_index.test_mapping", s)
507507
if err != nil {
508-
return err
508+
return fmt.Errorf("Failed to get index uuid: %w", err)
509509
}
510-
fmt.Println(initialUUID)
511510
g.Expect(mapping).To(MatchAllKeys(Keys{
512511
"terraform-test": MatchAllKeys(Keys{
513512
"mappings": MatchAllKeys(Keys{

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ require (
1414
github.com/katbyte/terrafmt v0.4.0
1515
github.com/mattn/go-isatty v0.0.12 // indirect
1616
github.com/mitchellh/go-homedir v1.1.0
17+
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 // indirect
1718
github.com/olivere/elastic v6.2.26+incompatible
1819
github.com/olivere/elastic/v7 v7.0.32
1920
github.com/onsi/gomega v1.27.1 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
426426
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
427427
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758=
428428
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs=
429+
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE=
430+
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8=
429431
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
430432
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
431433
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=

0 commit comments

Comments
 (0)