diff --git a/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_keystore_contents.go b/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_keystore_contents.go index b8a03f33c..9dc275e2d 100644 --- a/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_keystore_contents.go +++ b/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_keystore_contents.go @@ -37,10 +37,10 @@ type ElasticsearchKeystoreContents struct { AsFile *bool `tfsdk:"as_file"` } -func elasticsearchKeystoreContentsPayload(ctx context.Context, keystoreContentsTF types.Map, model *models.ElasticsearchClusterSettings, esStateObj *types.Object) (*models.ElasticsearchClusterSettings, diag.Diagnostics) { +func elasticsearchKeystoreContentsPayload(ctx context.Context, keystoreContentsTF types.Map, model *models.ElasticsearchClusterSettings, esState *ElasticsearchTF) (*models.ElasticsearchClusterSettings, diag.Diagnostics) { var diags diag.Diagnostics - if (keystoreContentsTF.IsNull() || len(keystoreContentsTF.Elements()) == 0) && esStateObj == nil { + if (keystoreContentsTF.IsNull() || len(keystoreContentsTF.Elements()) == 0) && esState == nil { return model, nil } @@ -69,13 +69,7 @@ func elasticsearchKeystoreContentsPayload(ctx context.Context, keystoreContentsT } // remove secrets that were in state but are removed from plan - if esStateObj != nil && !esStateObj.IsNull() { - var esState ElasticsearchTF - - if diags := tfsdk.ValueAs(ctx, esStateObj, &esState); diags.HasError() { - return nil, diags - } - + if esState != nil { if !esState.KeystoreContents.IsNull() { for k := range esState.KeystoreContents.Elements() { if _, ok := secrets[k]; !ok { diff --git a/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_payload.go b/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_payload.go index 9c569b9d2..2baa711ed 100644 --- a/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_payload.go +++ b/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_payload.go @@ -65,9 +65,17 @@ func ElasticsearchPayload(ctx context.Context, plan types.Object, state *types.O return nil, nil } + var esState *ElasticsearchTF + if state != nil { + esState, diags = objectToElasticsearch(ctx, *state) + if diags.HasError() { + return nil, diags + } + } + templatePayload := EnrichElasticsearchTemplate(payloadFromUpdate(updateResources), dtID, version, useNodeRoles) - payload, diags := es.payload(ctx, templatePayload, state) + payload, diags := es.payload(ctx, templatePayload, esState) if diags.HasError() { return nil, diags } @@ -123,7 +131,7 @@ func CheckAvailableMigration(ctx context.Context, plan types.Object, state types return false, nil } -func (es *ElasticsearchTF) payload(ctx context.Context, res *models.ElasticsearchPayload, state *types.Object) (*models.ElasticsearchPayload, diag.Diagnostics) { +func (es *ElasticsearchTF) payload(ctx context.Context, res *models.ElasticsearchPayload, state *ElasticsearchTF) (*models.ElasticsearchPayload, diag.Diagnostics) { var diags diag.Diagnostics if !es.RefId.IsNull() { @@ -160,11 +168,14 @@ func (es *ElasticsearchTF) payload(ctx context.Context, res *models.Elasticsearc res.Plan.AutoscalingEnabled = ec.Bool(es.Autoscale.ValueBool()) } - res.Settings, ds = elasticsearchTrustAccountPayload(ctx, es.TrustAccount, res.Settings) - diags.Append(ds...) + // Only add trust settings to update payload if trust has changed + if !es.TrustAccount.Equal(state.TrustAccount) || !es.TrustExternal.Equal(state.TrustExternal) { + res.Settings, ds = elasticsearchTrustAccountPayload(ctx, es.TrustAccount, res.Settings) + diags.Append(ds...) - res.Settings, ds = elasticsearchTrustExternalPayload(ctx, es.TrustExternal, res.Settings) - diags.Append(ds...) + res.Settings, ds = elasticsearchTrustExternalPayload(ctx, es.TrustExternal, res.Settings) + diags.Append(ds...) + } res.Settings, ds = elasticsearchKeystoreContentsPayload(ctx, es.KeystoreContents, res.Settings, state) diags.Append(ds...) diff --git a/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_payload_test.go b/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_payload_test.go index 2c99f44f7..524f93c2f 100644 --- a/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_payload_test.go +++ b/ec/ecresource/deploymentresource/elasticsearch/v2/elasticsearch_payload_test.go @@ -2575,6 +2575,127 @@ func Test_writeElasticsearch(t *testing.T) { }, }), }, + { + name: "don't put trust settings into the payload if they haven't changed", + args: args{ + esPlan: Elasticsearch{ + RefId: ec.String("main-elasticsearch"), + ResourceId: ec.String(mock.ValidClusterID), + Region: ec.String("some-region"), + TrustAccount: ElasticsearchTrustAccounts{ + { + AccountId: ec.String("id1"), + TrustAllowlist: []string{"a", "b"}, + }, + { + AccountId: ec.String("id2"), + TrustAll: ec.Bool(true), + }, + }, + TrustExternal: ElasticsearchTrustExternals{ + { + RelationshipId: ec.String("id3"), + TrustAll: ec.Bool(true), + }, + { + RelationshipId: ec.String("id4"), + TrustAllowlist: []string{"c", "d"}, + }, + }, + Strategy: ec.String("rolling_all"), + HotTier: &ElasticsearchTopology{ + id: "hot_content", + Size: ec.String("2g"), + ZoneCount: 1, + }, + }, + esState: &Elasticsearch{ + RefId: ec.String("main-elasticsearch"), + ResourceId: ec.String(mock.ValidClusterID), + Region: ec.String("some-region"), + TrustAccount: ElasticsearchTrustAccounts{ + { + AccountId: ec.String("id1"), + TrustAllowlist: []string{"a", "b"}, + }, + { + AccountId: ec.String("id2"), + TrustAll: ec.Bool(true), + }, + }, + TrustExternal: ElasticsearchTrustExternals{ + { + RelationshipId: ec.String("id3"), + TrustAll: ec.Bool(true), + }, + { + RelationshipId: ec.String("id4"), + TrustAllowlist: []string{"c", "d"}, + }, + }, + Strategy: ec.String("rolling_all"), + HotTier: &ElasticsearchTopology{ + id: "hot_content", + Size: ec.String("2g"), + ZoneCount: 1, + }, + }, + updatePayloads: testutil.UpdatePayloadsFromTemplate(t, "../../testdata/template-aws-io-optimized-v2.json"), + templateID: "aws-io-optimized-v2", + version: "7.7.0", + useNodeRoles: false, + }, + want: EnrichWithEmptyTopologies(tp770(), &models.ElasticsearchPayload{ + Region: ec.String("some-region"), + RefID: ec.String("main-elasticsearch"), + Settings: &models.ElasticsearchClusterSettings{ + DedicatedMastersThreshold: 6, + }, + Plan: &models.ElasticsearchClusterPlan{ + AutoscalingEnabled: ec.Bool(false), + Elasticsearch: &models.ElasticsearchConfiguration{ + Version: "7.7.0", + }, + DeploymentTemplate: &models.DeploymentTemplateReference{ + ID: ec.String("aws-io-optimized-v2"), + }, + Transient: &models.TransientElasticsearchPlanConfiguration{ + Strategy: &models.PlanStrategy{ + Rolling: &models.RollingStrategyConfig{GroupBy: "__all__"}, + }, + }, + ClusterTopology: []*models.ElasticsearchClusterTopologyElement{ + { + ID: "hot_content", + ZoneCount: 1, + InstanceConfigurationID: "aws.data.highio.i3", + Size: &models.TopologySize{ + Resource: ec.String("memory"), + Value: ec.Int32(2048), + }, + NodeType: &models.ElasticsearchNodeType{ + Data: ec.Bool(true), + Ingest: ec.Bool(true), + Master: ec.Bool(true), + }, + Elasticsearch: &models.ElasticsearchConfiguration{ + NodeAttributes: map[string]string{"data": "hot"}, + }, + TopologyElementControl: &models.TopologyElementControl{ + Min: &models.TopologySize{ + Resource: ec.String("memory"), + Value: ec.Int32(1024), + }, + }, + AutoscalingMax: &models.TopologySize{ + Value: ec.Int32(118784), + Resource: ec.String("memory"), + }, + }, + }, + }, + }), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {