From 5831f929e52fb7c9755c56e19c6b8dfec19df010 Mon Sep 17 00:00:00 2001 From: Espen Albert Date: Mon, 16 Dec 2024 21:56:48 +0000 Subject: [PATCH] feat: Support isSchemaUpgrade to handle legacy to new schema --- internal/common/conversion/error_framework.go | 12 +++++++++ .../service/advancedclustertpf/resource.go | 20 +++++++++++--- .../resource_compatibility_reuse.go | 26 +++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/internal/common/conversion/error_framework.go b/internal/common/conversion/error_framework.go index 5586456cdf..dde00c5cbf 100644 --- a/internal/common/conversion/error_framework.go +++ b/internal/common/conversion/error_framework.go @@ -4,6 +4,8 @@ import ( "encoding/json" "github.com/hashicorp/terraform-plugin-framework/diag" + + legacyDiag "github.com/hashicorp/terraform-plugin-sdk/v2/diag" ) type ErrBody interface { @@ -32,3 +34,13 @@ func AddJSONBodyErrorToDiagnostics(msgPrefix string, err error, diags *diag.Diag errorJSON := string(errorBytes) diags.AddError(msgPrefix, errorJSON) } + +func AddLegacyDiags(diags *diag.Diagnostics, legacyDiags legacyDiag.Diagnostics) { + for _, diag := range legacyDiags { + if diag.Severity == legacyDiag.Error { + diags.AddError(diag.Summary, diag.Detail) + } else { + diags.AddWarning(diag.Summary, diag.Detail) + } + } +} diff --git a/internal/service/advancedclustertpf/resource.go b/internal/service/advancedclustertpf/resource.go index 71b9cc5db2..5168408298 100644 --- a/internal/service/advancedclustertpf/resource.go +++ b/internal/service/advancedclustertpf/resource.go @@ -102,12 +102,15 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou if diags.HasError() { return } - if usingLegacySchema(ctx, plan.ReplicationSpecs, diags) && !usingLegacySchema(ctx, state.ReplicationSpecs, diags) { + stateUsingLegacy := usingLegacySchema(ctx, state.ReplicationSpecs, diags) + planUsingLegacy := usingLegacySchema(ctx, plan.ReplicationSpecs, diags) + if planUsingLegacy && !stateUsingLegacy { diags.AddError("error operation not permitted, nums_shards from 1 -> > 1", fmt.Sprintf("cannot increase num_shards to > 1 under the current configuration. New shards can be defined by adding new replication spec objects; %s", DeprecationOldSchemaAction)) return } - stateReq := normalizeFromTFModel(ctx, &state, diags, false) - planReq := normalizeFromTFModel(ctx, &plan, diags, false) + isSchemaUpgrade := stateUsingLegacy && !planUsingLegacy + stateReq := normalizeFromTFModel(ctx, &state, diags, isSchemaUpgrade) + planReq := normalizeFromTFModel(ctx, &plan, diags, isSchemaUpgrade) if diags.HasError() { return } @@ -115,7 +118,8 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou IgnoreInStatePrefix: []string{"regionConfigs"}, IncludeInStateSuffix: []string{"diskIOPS"}, } - if findNumShardsUpdates(ctx, &state, &plan, diags) != nil { + if isSchemaUpgrade || findNumShardsUpdates(ctx, &state, &plan, diags) != nil { + // isSchemaUpgrade will have no changes by default after flattening; therefore, force update the replicationSpecs // `num_shards` updates is only in the legacy ClusterDescription; therefore, force update the replicationSpecs patchOptions.ForceUpdateAttr = append(patchOptions.ForceUpdateAttr, "replicationSpecs") } @@ -130,6 +134,14 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou if upgradeRequest != nil { clusterResp = r.applyTenantUpgrade(ctx, &plan, upgradeRequest, diags) } else { + if isSchemaUpgrade { + specs, localDiags := populateIDValuesUsingNewAPI(ctx, plan.ProjectID.ValueString(), plan.Name.ValueString(), r.Client.AtlasV2.ClustersApi, patchReq.ReplicationSpecs) + conversion.AddLegacyDiags(diags, localDiags) + if diags.HasError() { + return + } + patchReq.ReplicationSpecs = specs + } clusterResp = r.applyClusterChanges(ctx, diags, &state, &plan, patchReq) } if diags.HasError() { diff --git a/internal/service/advancedclustertpf/resource_compatibility_reuse.go b/internal/service/advancedclustertpf/resource_compatibility_reuse.go index 2ad6877b2f..41cc60c862 100644 --- a/internal/service/advancedclustertpf/resource_compatibility_reuse.go +++ b/internal/service/advancedclustertpf/resource_compatibility_reuse.go @@ -6,8 +6,10 @@ import ( "strconv" "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/constant" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/advancedcluster" "github.com/spf13/cast" admin20240530 "go.mongodb.org/atlas-sdk/v20240530005/admin" "go.mongodb.org/atlas-sdk/v20241113003/admin" @@ -168,3 +170,27 @@ func convertDedicatedHardwareSpecToOldSDK(spec *admin.DedicatedHardwareSpec20240 InstanceSize: spec.InstanceSize, } } + +// copied from advancedcluster/resource_update_logic.go +func populateIDValuesUsingNewAPI(ctx context.Context, projectID, clusterName string, connV2ClusterAPI admin.ClustersApi, replicationSpecs *[]admin.ReplicationSpec20240805) (*[]admin.ReplicationSpec20240805, diag.Diagnostics) { + if replicationSpecs == nil || len(*replicationSpecs) == 0 { + return replicationSpecs, nil + } + cluster, _, err := connV2ClusterAPI.GetCluster(ctx, projectID, clusterName).Execute() + if err != nil { + return nil, diag.FromErr(fmt.Errorf(errorRead, clusterName, err)) + } + + zoneToReplicationSpecsIDs := groupIDsByZone(cluster.GetReplicationSpecs()) + result := advancedcluster.AddIDsToReplicationSpecs(*replicationSpecs, zoneToReplicationSpecsIDs) + return &result, nil +} + +// copied from advancedcluster/resource_update_logic.go +func groupIDsByZone(specs []admin.ReplicationSpec20240805) map[string][]string { + result := make(map[string][]string) + for _, spec := range specs { + result[spec.GetZoneName()] = append(result[spec.GetZoneName()], spec.GetId()) + } + return result +}