diff --git a/internal/service/advancedcluster/data_source_advanced_cluster.go b/internal/service/advancedcluster/data_source_advanced_cluster.go index 38b15521a4..ae9b08be3b 100644 --- a/internal/service/advancedcluster/data_source_advanced_cluster.go +++ b/internal/service/advancedcluster/data_source_advanced_cluster.go @@ -5,8 +5,12 @@ import ( "fmt" "net/http" + admin20231115 "go.mongodb.org/atlas-sdk/v20231115014/admin" + "go.mongodb.org/atlas-sdk/v20240530001/admin" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "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/config" @@ -20,6 +24,10 @@ func DataSource() *schema.Resource { Type: schema.TypeString, Required: true, }, + "use_replication_spec_per_shard": { + Type: schema.TypeBool, + Optional: true, + }, "advanced_configuration": SchemaAdvancedConfigDS(), "backup_enabled": { Type: schema.TypeBool, @@ -108,6 +116,14 @@ func DataSource() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "zone_id": { + Type: schema.TypeString, + Computed: true, + }, + "external_id": { + Type: schema.TypeString, + Computed: true, + }, "num_shards": { Type: schema.TypeInt, Computed: true, @@ -235,22 +251,95 @@ func DataSource() *schema.Resource { func dataSourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { connV2 := meta.(*config.MongoDBClient).AtlasV2 + connLatest := meta.(*config.MongoDBClient).AtlasV2Preview + projectID := d.Get("project_id").(string) clusterName := d.Get("name").(string) + useReplicationSpecPerShard := false + var replicationSpecs []map[string]any + var clusterID string - cluster, resp, err := connV2.ClustersApi.GetCluster(ctx, projectID, clusterName).Execute() - if err != nil { - if resp != nil && resp.StatusCode == http.StatusNotFound { - return nil + if v, ok := d.GetOk("use_replication_spec_per_shard"); ok { + useReplicationSpecPerShard = v.(bool) + } + + if !useReplicationSpecPerShard { + clusterDescOld, resp, err := connV2.ClustersApi.GetCluster(ctx, projectID, clusterName).Execute() + if err != nil { + if resp != nil { + if resp.StatusCode == http.StatusNotFound { + return nil + } + if admin20231115.IsErrorCode(err, "ASYMMETRIC_SHARD_UNSUPPORTED") { + return diag.FromErr(fmt.Errorf("please add `use_replication_spec_per_shard = true` to your data source configuration to enable asymmetric shard support. Refer to documentation for more details. %s", err)) + } + } + return diag.FromErr(fmt.Errorf(errorRead, clusterName, err)) + } + + clusterID = clusterDescOld.GetId() + + if err := d.Set("disk_size_gb", clusterDescOld.GetDiskSizeGB()); err != nil { + return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "disk_size_gb", clusterName, err)) + } + + replicationSpecs, err = FlattenAdvancedReplicationSpecsOldSDK(ctx, clusterDescOld.GetReplicationSpecs(), clusterDescOld.GetDiskSizeGB(), d.Get("replication_specs").([]any), d, connLatest) + if err != nil { + return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "replication_specs", clusterName, err)) + } + + diags := setCommonSchemaFields(d, convertClusterDescToLatestExcludeRepSpecs(clusterDescOld)) + if diags.HasError() { + return diags + } + } else { + clusterDescLatest, resp, err := connLatest.ClustersApi.GetCluster(ctx, projectID, clusterName).Execute() + if err != nil { + if resp != nil && resp.StatusCode == http.StatusNotFound { + return nil + } + return diag.FromErr(fmt.Errorf(errorRead, clusterName, err)) + } + + clusterID = clusterDescLatest.GetId() + + replicationSpecs, err = flattenAdvancedReplicationSpecsDS(ctx, clusterDescLatest.GetReplicationSpecs(), d, connLatest) + if err != nil { + return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "replication_specs", clusterName, err)) + } + + diags := setCommonSchemaFields(d, clusterDescLatest) + if diags.HasError() { + return diags } - return diag.FromErr(fmt.Errorf(errorRead, clusterName, err)) } + if err := d.Set("replication_specs", replicationSpecs); err != nil { + return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "replication_specs", clusterName, err)) + } + + // TODO: update to use connLatest to call below API + processArgs, _, err := connV2.ClustersApi.GetClusterAdvancedConfiguration(ctx, projectID, clusterName).Execute() + if err != nil { + return diag.FromErr(fmt.Errorf(ErrorAdvancedConfRead, clusterName, err)) + } + + if err := d.Set("advanced_configuration", flattenProcessArgs(processArgs)); err != nil { + return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "advanced_configuration", clusterName, err)) + } + + d.SetId(clusterID) + return nil +} + +func setCommonSchemaFields(d *schema.ResourceData, cluster *admin.ClusterDescription20240710) diag.Diagnostics { + clusterName := *cluster.Name + if err := d.Set("backup_enabled", cluster.GetBackupEnabled()); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "backup_enabled", clusterName, err)) } - if err := d.Set("bi_connector_config", flattenBiConnectorConfig(cluster.GetBiConnector())); err != nil { + if err := d.Set("bi_connector_config", flattenBiConnectorConfig(cluster.BiConnector)); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "bi_connector_config", clusterName, err)) } @@ -258,7 +347,7 @@ func dataSourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag. return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "cluster_type", clusterName, err)) } - if err := d.Set("connection_strings", flattenConnectionStrings(cluster.GetConnectionStrings())); err != nil { + if err := d.Set("connection_strings", flattenConnectionStrings(*cluster.ConnectionStrings)); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "connection_strings", clusterName, err)) } @@ -266,19 +355,15 @@ func dataSourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag. return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "create_date", clusterName, err)) } - if err := d.Set("disk_size_gb", cluster.GetDiskSizeGB()); err != nil { - return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "disk_size_gb", clusterName, err)) - } - if err := d.Set("encryption_at_rest_provider", cluster.GetEncryptionAtRestProvider()); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "encryption_at_rest_provider", clusterName, err)) } - if err := d.Set("labels", flattenLabels(cluster.GetLabels())); err != nil { + if err := d.Set("labels", flattenLabels(*cluster.Labels)); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "labels", clusterName, err)) } - if err := d.Set("tags", conversion.FlattenTags(cluster.GetTags())); err != nil { + if err := d.Set("tags", flattenTags(cluster.Tags)); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "tags", clusterName, err)) } @@ -302,15 +387,6 @@ func dataSourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag. return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "pit_enabled", clusterName, err)) } - replicationSpecs, err := FlattenAdvancedReplicationSpecs(ctx, cluster.GetReplicationSpecs(), d.Get("replication_specs").([]any), d, connV2) - if err != nil { - return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "replication_specs", clusterName, err)) - } - - if err := d.Set("replication_specs", replicationSpecs); err != nil { - return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "replication_specs", clusterName, err)) - } - if err := d.Set("root_cert_type", cluster.GetRootCertType()); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "state_name", clusterName, err)) } @@ -328,15 +404,5 @@ func dataSourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag. return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "global_cluster_self_managed_sharding", clusterName, err)) } - processArgs, _, err := connV2.ClustersApi.GetClusterAdvancedConfiguration(ctx, projectID, clusterName).Execute() - if err != nil { - return diag.FromErr(fmt.Errorf(ErrorAdvancedConfRead, clusterName, err)) - } - - if err := d.Set("advanced_configuration", flattenProcessArgs(processArgs)); err != nil { - return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "advanced_configuration", clusterName, err)) - } - - d.SetId(cluster.GetId()) return nil } diff --git a/internal/service/advancedcluster/data_source_advanced_clusters.go b/internal/service/advancedcluster/data_source_advanced_clusters.go index 867b0b5cdd..6a33cc3402 100644 --- a/internal/service/advancedcluster/data_source_advanced_clusters.go +++ b/internal/service/advancedcluster/data_source_advanced_clusters.go @@ -6,13 +6,16 @@ import ( "log" "net/http" + admin20231115 "go.mongodb.org/atlas-sdk/v20231115014/admin" + "go.mongodb.org/atlas-sdk/v20240530001/admin" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "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/config" - "go.mongodb.org/atlas-sdk/v20231115014/admin" ) func PluralDataSource() *schema.Resource { @@ -246,6 +249,7 @@ func PluralDataSource() *schema.Resource { func dataSourcePluralRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { connV2 := meta.(*config.MongoDBClient).AtlasV2 + connLatest := meta.(*config.MongoDBClient).AtlasV2Preview projectID := d.Get("project_id").(string) d.SetId(id.UniqueId()) @@ -256,14 +260,14 @@ func dataSourcePluralRead(ctx context.Context, d *schema.ResourceData, meta any) } return diag.FromErr(fmt.Errorf("error reading advanced cluster list for project(%s): %s", projectID, err)) } - if err := d.Set("results", flattenAdvancedClusters(ctx, connV2, list.GetResults(), d)); err != nil { + if err := d.Set("results", flattenAdvancedClusters(ctx, connV2, connLatest, list.GetResults(), d)); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "results", d.Id(), err)) } return nil } -func flattenAdvancedClusters(ctx context.Context, connV2 *admin.APIClient, clusters []admin.AdvancedClusterDescription, d *schema.ResourceData) []map[string]any { +func flattenAdvancedClusters(ctx context.Context, connV2 *admin20231115.APIClient, connLatest *admin.APIClient, clusters []admin20231115.AdvancedClusterDescription, d *schema.ResourceData) []map[string]any { results := make([]map[string]any, 0, len(clusters)) for i := range clusters { cluster := &clusters[i] @@ -271,7 +275,7 @@ func flattenAdvancedClusters(ctx context.Context, connV2 *admin.APIClient, clust if err != nil { log.Printf("[WARN] Error setting `advanced_configuration` for the cluster(%s): %s", cluster.GetId(), err) } - replicationSpecs, err := FlattenAdvancedReplicationSpecs(ctx, cluster.GetReplicationSpecs(), nil, d, connV2) + replicationSpecs, err := FlattenAdvancedReplicationSpecsOldSDK(ctx, cluster.GetReplicationSpecs(), cluster.GetDiskSizeGB(), nil, d, connLatest) if err != nil { log.Printf("[WARN] Error setting `replication_specs` for the cluster(%s): %s", cluster.GetId(), err) } @@ -279,13 +283,13 @@ func flattenAdvancedClusters(ctx context.Context, connV2 *admin.APIClient, clust result := map[string]any{ "advanced_configuration": flattenProcessArgs(processArgs), "backup_enabled": cluster.GetBackupEnabled(), - "bi_connector_config": flattenBiConnectorConfig(cluster.GetBiConnector()), + "bi_connector_config": flattenBiConnectorConfig(convertBiConnectToLatest(cluster.BiConnector)), "cluster_type": cluster.GetClusterType(), "create_date": conversion.TimePtrToStringPtr(cluster.CreateDate), - "connection_strings": flattenConnectionStrings(cluster.GetConnectionStrings()), + "connection_strings": flattenConnectionStrings(*convertConnectionStringToLatest(cluster.ConnectionStrings)), "disk_size_gb": cluster.GetDiskSizeGB(), "encryption_at_rest_provider": cluster.GetEncryptionAtRestProvider(), - "labels": flattenLabels(cluster.GetLabels()), + "labels": flattenLabels(*convertLabelsToLatest(cluster.Labels)), "tags": conversion.FlattenTags(cluster.GetTags()), "mongo_db_major_version": cluster.GetMongoDBMajorVersion(), "mongo_db_version": cluster.GetMongoDBVersion(), diff --git a/internal/service/advancedcluster/model_advanced_cluster.go b/internal/service/advancedcluster/model_advanced_cluster.go index 48de83f807..e7f208a1ea 100644 --- a/internal/service/advancedcluster/model_advanced_cluster.go +++ b/internal/service/advancedcluster/model_advanced_cluster.go @@ -9,14 +9,16 @@ import ( "slices" "strings" + admin20231115 "go.mongodb.org/atlas-sdk/v20231115014/admin" + "go.mongodb.org/atlas-sdk/v20240530001/admin" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/spf13/cast" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/constant" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" - "github.com/spf13/cast" - admin20231115 "go.mongodb.org/atlas-sdk/v20231115014/admin" - "go.mongodb.org/atlas-sdk/v20240530001/admin" ) var ( @@ -340,7 +342,7 @@ func FormatMongoDBMajorVersion(val any) string { return fmt.Sprintf("%.1f", cast.ToFloat32(val)) } -func flattenLabels(l []admin20231115.ComponentLabel) []map[string]string { +func flattenLabels(l []admin.ComponentLabel) []map[string]string { labels := make([]map[string]string, 0, len(l)) for _, item := range l { if item.GetKey() == ignoreLabel { @@ -354,7 +356,19 @@ func flattenLabels(l []admin20231115.ComponentLabel) []map[string]string { return labels } -func flattenConnectionStrings(str admin20231115.ClusterConnectionStrings) []map[string]any { +func flattenTags(tags *[]admin.ResourceTag) []map[string]string { + tagSlice := *tags + ret := make([]map[string]string, len(tagSlice)) + for i, tag := range tagSlice { + ret[i] = map[string]string{ + "key": tag.GetKey(), + "value": tag.GetValue(), + } + } + return ret +} + +func flattenConnectionStrings(str admin.ClusterConnectionStrings) []map[string]any { return []map[string]any{ { "standard": str.GetStandard(), @@ -366,7 +380,7 @@ func flattenConnectionStrings(str admin20231115.ClusterConnectionStrings) []map[ } } -func flattenPrivateEndpoint(privateEndpoints []admin20231115.ClusterDescriptionConnectionStringsPrivateEndpoint) []map[string]any { +func flattenPrivateEndpoint(privateEndpoints []admin.ClusterDescriptionConnectionStringsPrivateEndpoint) []map[string]any { endpoints := make([]map[string]any, 0, len(privateEndpoints)) for _, endpoint := range privateEndpoints { endpoints = append(endpoints, map[string]any{ @@ -380,7 +394,7 @@ func flattenPrivateEndpoint(privateEndpoints []admin20231115.ClusterDescriptionC return endpoints } -func flattenEndpoints(listEndpoints []admin20231115.ClusterDescriptionConnectionStringsPrivateEndpointEndpoint) []map[string]any { +func flattenEndpoints(listEndpoints []admin.ClusterDescriptionConnectionStringsPrivateEndpointEndpoint) []map[string]any { endpoints := make([]map[string]any, 0, len(listEndpoints)) for _, endpoint := range listEndpoints { endpoints = append(endpoints, map[string]any{ @@ -392,7 +406,7 @@ func flattenEndpoints(listEndpoints []admin20231115.ClusterDescriptionConnection return endpoints } -func flattenBiConnectorConfig(biConnector admin20231115.BiConnector) []map[string]any { +func flattenBiConnectorConfig(biConnector *admin.BiConnector) []map[string]any { return []map[string]any{ { "enabled": biConnector.GetEnabled(), @@ -435,8 +449,8 @@ func flattenProcessArgs(p *admin20231115.ClusterDescriptionProcessArgs) []map[st } } -func FlattenAdvancedReplicationSpecs(ctx context.Context, apiObjects []admin20231115.ReplicationSpec, tfMapObjects []any, - d *schema.ResourceData, connV2 *admin20231115.APIClient) ([]map[string]any, error) { +func FlattenAdvancedReplicationSpecsOldSDK(ctx context.Context, apiObjects []admin20231115.ReplicationSpec, rootDiskSizeGB float64, tfMapObjects []any, + d *schema.ResourceData, connV2 *admin.APIClient) ([]map[string]any, error) { if len(apiObjects) == 0 { return nil, nil } @@ -456,7 +470,7 @@ func FlattenAdvancedReplicationSpecs(ctx context.Context, apiObjects []admin2023 continue } - advancedReplicationSpec, err := flattenAdvancedReplicationSpec(ctx, &apiObjects[j], tfMapObject, d, connV2) + advancedReplicationSpec, err := flattenAdvancedReplicationSpecOldSDK(ctx, &apiObjects[j], rootDiskSizeGB, tfMapObject, d, connV2) if err != nil { return nil, err @@ -480,7 +494,7 @@ func FlattenAdvancedReplicationSpecs(ctx context.Context, apiObjects []admin2023 } j := slices.IndexFunc(wasAPIObjectUsed, func(isUsed bool) bool { return !isUsed }) - advancedReplicationSpec, err := flattenAdvancedReplicationSpec(ctx, &apiObjects[j], tfMapObject, d, connV2) + advancedReplicationSpec, err := flattenAdvancedReplicationSpecOldSDK(ctx, &apiObjects[j], rootDiskSizeGB, tfMapObject, d, connV2) if err != nil { return nil, err @@ -497,8 +511,8 @@ func doesAdvancedReplicationSpecMatchAPI(tfObject map[string]any, apiObject *adm return tfObject["id"] == apiObject.GetId() || (tfObject["id"] == nil && tfObject["zone_name"] == apiObject.GetZoneName()) } -func flattenAdvancedReplicationSpec(ctx context.Context, apiObject *admin20231115.ReplicationSpec, tfMapObject map[string]any, - d *schema.ResourceData, connV2 *admin20231115.APIClient) (map[string]any, error) { +func flattenAdvancedReplicationSpecOldSDK(ctx context.Context, apiObject *admin20231115.ReplicationSpec, rootDiskSizeGB float64, tfMapObject map[string]any, + d *schema.ResourceData, connV2 *admin.APIClient) (map[string]any, error) { if apiObject == nil { return nil, nil } @@ -507,14 +521,14 @@ func flattenAdvancedReplicationSpec(ctx context.Context, apiObject *admin2023111 tfMap["num_shards"] = apiObject.GetNumShards() tfMap["id"] = apiObject.GetId() if tfMapObject != nil { - object, containerIDs, err := flattenAdvancedReplicationSpecRegionConfigs(ctx, apiObject.GetRegionConfigs(), tfMapObject["region_configs"].([]any), d, connV2) + object, containerIDs, err := flattenAdvancedReplicationSpecRegionConfigs(ctx, *convertRegionConfigSliceToLatest(apiObject.RegionConfigs, rootDiskSizeGB), tfMapObject["region_configs"].([]any), d, connV2) if err != nil { return nil, err } tfMap["region_configs"] = object tfMap["container_id"] = containerIDs } else { - object, containerIDs, err := flattenAdvancedReplicationSpecRegionConfigs(ctx, apiObject.GetRegionConfigs(), nil, d, connV2) + object, containerIDs, err := flattenAdvancedReplicationSpecRegionConfigs(ctx, *convertRegionConfigSliceToLatest(apiObject.RegionConfigs, rootDiskSizeGB), nil, d, connV2) if err != nil { return nil, err } @@ -526,8 +540,8 @@ func flattenAdvancedReplicationSpec(ctx context.Context, apiObject *admin2023111 return tfMap, nil } -func flattenAdvancedReplicationSpecRegionConfigs(ctx context.Context, apiObjects []admin20231115.CloudRegionConfig, tfMapObjects []any, - d *schema.ResourceData, connV2 *admin20231115.APIClient) (tfResult []map[string]any, containersIDs map[string]string, err error) { +func flattenAdvancedReplicationSpecRegionConfigs(ctx context.Context, apiObjects []admin.CloudRegionConfig, tfMapObjects []any, + d *schema.ResourceData, connV2 *admin.APIClient) (tfResult []map[string]any, containersIDs map[string]string, err error) { if len(apiObjects) == 0 { return nil, nil, nil } @@ -545,7 +559,7 @@ func flattenAdvancedReplicationSpecRegionConfigs(ctx context.Context, apiObjects } if apiObject.GetProviderName() != "TENANT" { - params := &admin20231115.ListPeeringContainerByCloudProviderApiParams{ + params := &admin.ListPeeringContainerByCloudProviderApiParams{ GroupId: d.Get("project_id").(string), ProviderName: apiObject.ProviderName, } @@ -562,7 +576,7 @@ func flattenAdvancedReplicationSpecRegionConfigs(ctx context.Context, apiObjects return tfList, containerIDs, nil } -func flattenAdvancedReplicationSpecRegionConfig(apiObject *admin20231115.CloudRegionConfig, tfMapObject map[string]any) map[string]any { +func flattenAdvancedReplicationSpecRegionConfig(apiObject *admin.CloudRegionConfig, tfMapObject map[string]any) map[string]any { if apiObject == nil { return nil } @@ -600,15 +614,16 @@ func flattenAdvancedReplicationSpecRegionConfig(apiObject *admin20231115.CloudRe return tfMap } -func hwSpecToDedicatedHwSpec(apiObject *admin20231115.HardwareSpec) *admin20231115.DedicatedHardwareSpec { +func hwSpecToDedicatedHwSpec(apiObject *admin.HardwareSpec) *admin.DedicatedHardwareSpec { if apiObject == nil { return nil } - return &admin20231115.DedicatedHardwareSpec{ + return &admin.DedicatedHardwareSpec{ NodeCount: apiObject.NodeCount, DiskIOPS: apiObject.DiskIOPS, EbsVolumeType: apiObject.EbsVolumeType, InstanceSize: apiObject.InstanceSize, + DiskSizeGB: apiObject.DiskSizeGB, } } @@ -625,7 +640,7 @@ func dedicatedHwSpecToHwSpec(apiObject *admin.DedicatedHardwareSpec) *admin.Hard } } -func flattenAdvancedReplicationSpecRegionConfigSpec(apiObject *admin20231115.DedicatedHardwareSpec, providerName string, tfMapObjects []any) []map[string]any { +func flattenAdvancedReplicationSpecRegionConfigSpec(apiObject *admin.DedicatedHardwareSpec, providerName string, tfMapObjects []any) []map[string]any { if apiObject == nil { return nil } @@ -644,6 +659,9 @@ func flattenAdvancedReplicationSpecRegionConfigSpec(apiObject *admin20231115.Ded tfMap["ebs_volume_type"] = apiObject.GetEbsVolumeType() } } + if _, ok := tfMapObject["disk_size_gb"]; ok { + tfMap["disk_size_gb"] = apiObject.GetDiskSizeGB() + } if _, ok := tfMapObject["node_count"]; ok { tfMap["node_count"] = apiObject.GetNodeCount() } @@ -652,6 +670,7 @@ func flattenAdvancedReplicationSpecRegionConfigSpec(apiObject *admin20231115.Ded tfList = append(tfList, tfMap) } } else { + tfMap["disk_size_gb"] = apiObject.GetDiskSizeGB() tfMap["disk_iops"] = apiObject.GetDiskIOPS() tfMap["ebs_volume_type"] = apiObject.GetEbsVolumeType() tfMap["node_count"] = apiObject.GetNodeCount() @@ -661,7 +680,7 @@ func flattenAdvancedReplicationSpecRegionConfigSpec(apiObject *admin20231115.Ded return tfList } -func flattenAdvancedReplicationSpecAutoScaling(apiObject *admin20231115.AdvancedAutoScalingSettings) []map[string]any { +func flattenAdvancedReplicationSpecAutoScaling(apiObject *admin.AdvancedAutoScalingSettings) []map[string]any { if apiObject == nil { return nil } @@ -680,7 +699,7 @@ func flattenAdvancedReplicationSpecAutoScaling(apiObject *admin20231115.Advanced return tfList } -func getAdvancedClusterContainerID(containers []admin20231115.CloudProviderContainer, cluster *admin20231115.CloudRegionConfig) string { +func getAdvancedClusterContainerID(containers []admin.CloudProviderContainer, cluster *admin.CloudRegionConfig) string { if len(containers) == 0 { return "" } @@ -933,3 +952,50 @@ func expandRegionConfigAutoScaling(tfList []any) *admin.AdvancedAutoScalingSetti } return &settings } + +func flattenAdvancedReplicationSpecsDS(ctx context.Context, apiRepSpecs []admin.ReplicationSpec20240710, d *schema.ResourceData, connV2 *admin.APIClient) ([]map[string]any, error) { + if len(apiRepSpecs) == 0 { + return nil, nil + } + + tfList := make([]map[string]any, len(apiRepSpecs)) + + for i, apiRepSpec := range apiRepSpecs { + tfReplicationSpec, err := flattenAdvancedReplicationSpec(ctx, &apiRepSpec, nil, d, connV2) + if err != nil { + return nil, err + } + tfList[i] = tfReplicationSpec + } + return tfList, nil +} + +func flattenAdvancedReplicationSpec(ctx context.Context, apiObject *admin.ReplicationSpec20240710, tfMapObject map[string]any, + d *schema.ResourceData, connV2 *admin.APIClient) (map[string]any, error) { + if apiObject == nil { + return nil, nil + } + + tfMap := map[string]any{} + tfMap["id"] = apiObject.GetId() + tfMap["external_id"] = apiObject.GetId() + if tfMapObject != nil { + object, containerIDs, err := flattenAdvancedReplicationSpecRegionConfigs(ctx, apiObject.GetRegionConfigs(), tfMapObject["region_configs"].([]any), d, connV2) + if err != nil { + return nil, err + } + tfMap["region_configs"] = object + tfMap["container_id"] = containerIDs + } else { + object, containerIDs, err := flattenAdvancedReplicationSpecRegionConfigs(ctx, apiObject.GetRegionConfigs(), nil, d, connV2) + if err != nil { + return nil, err + } + tfMap["region_configs"] = object + tfMap["container_id"] = containerIDs + } + tfMap["zone_name"] = apiObject.GetZoneName() + tfMap["zone_id"] = apiObject.GetZoneId() + + return tfMap, nil +} diff --git a/internal/service/advancedcluster/model_advanced_cluster_test.go b/internal/service/advancedcluster/model_advanced_cluster_test.go index a63e0e648b..556419372e 100644 --- a/internal/service/advancedcluster/model_advanced_cluster_test.go +++ b/internal/service/advancedcluster/model_advanced_cluster_test.go @@ -6,14 +6,18 @@ import ( "net/http" "testing" + "go.mongodb.org/atlas-sdk/v20231115014/admin" + "go.mongodb.org/atlas-sdk/v20231115014/mockadmin" + adminLatest "go.mongodb.org/atlas-sdk/v20240530001/admin" + mockAdminLatest "go.mongodb.org/atlas-sdk/v20240530001/mockadmin" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" - "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/advancedcluster" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "go.mongodb.org/atlas-sdk/v20231115014/admin" - "go.mongodb.org/atlas-sdk/v20231115014/mockadmin" + + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/advancedcluster" ) var ( @@ -122,18 +126,18 @@ func TestFlattenReplicationSpecs(t *testing.T) { } for name, tc := range testCases { t.Run(name, func(t *testing.T) { - peeringAPI := mockadmin.NetworkPeeringApi{} + peeringAPI := mockAdminLatest.NetworkPeeringApi{} - peeringAPI.EXPECT().ListPeeringContainerByCloudProviderWithParams(mock.Anything, mock.Anything).Return(admin.ListPeeringContainerByCloudProviderApiRequest{ApiService: &peeringAPI}) - containerResult := []admin.CloudProviderContainer{{Id: conversion.StringPtr("c1"), RegionName: ®ionName, ProviderName: &providerName}} - peeringAPI.EXPECT().ListPeeringContainerByCloudProviderExecute(mock.Anything).Return(&admin.PaginatedCloudProviderContainer{Results: &containerResult}, nil, nil) + peeringAPI.EXPECT().ListPeeringContainerByCloudProviderWithParams(mock.Anything, mock.Anything).Return(adminLatest.ListPeeringContainerByCloudProviderApiRequest{ApiService: &peeringAPI}) + containerResult := []adminLatest.CloudProviderContainer{{Id: conversion.StringPtr("c1"), RegionName: ®ionName, ProviderName: &providerName}} + peeringAPI.EXPECT().ListPeeringContainerByCloudProviderExecute(mock.Anything).Return(&adminLatest.PaginatedCloudProviderContainer{Results: &containerResult}, nil, nil) - client := &admin.APIClient{ + client := &adminLatest.APIClient{ NetworkPeeringApi: &peeringAPI, } resourceData := schema.TestResourceDataRaw(t, testSchema, map[string]any{"project_id": "p1"}) - tfOutputSpecs, err := advancedcluster.FlattenAdvancedReplicationSpecs(context.Background(), tc.adminSpecs, tc.tfInputSpecs, resourceData, client) + tfOutputSpecs, err := advancedcluster.FlattenAdvancedReplicationSpecsOldSDK(context.Background(), tc.adminSpecs, 0, tc.tfInputSpecs, resourceData, client) require.NoError(t, err) assert.Len(t, tfOutputSpecs, tc.expectedLen) diff --git a/internal/service/advancedcluster/model_sdk_version_conversion.go b/internal/service/advancedcluster/model_sdk_version_conversion.go index 355da41876..e6cc345d38 100644 --- a/internal/service/advancedcluster/model_sdk_version_conversion.go +++ b/internal/service/advancedcluster/model_sdk_version_conversion.go @@ -1,9 +1,10 @@ package advancedcluster import ( - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" admin20231115 "go.mongodb.org/atlas-sdk/v20231115014/admin" "go.mongodb.org/atlas-sdk/v20240530001/admin" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" ) // Conversions from one SDK model version to another are used to avoid duplicating our flatten/expand conversion functions. @@ -36,6 +37,74 @@ func convertBiConnectToOldSDK(biconnector *admin.BiConnector) *admin20231115.BiC } } +func convertBiConnectToLatest(biconnector *admin20231115.BiConnector) *admin.BiConnector { + return &admin.BiConnector{ + Enabled: biconnector.Enabled, + ReadPreference: biconnector.ReadPreference, + } +} + +func convertConnectionStringToLatest(connStrings *admin20231115.ClusterConnectionStrings) *admin.ClusterConnectionStrings { + return &admin.ClusterConnectionStrings{ + AwsPrivateLink: connStrings.AwsPrivateLink, + AwsPrivateLinkSrv: connStrings.AwsPrivateLinkSrv, + Private: connStrings.Private, + PrivateEndpoint: convertPrivateEndpointToLatest(connStrings.PrivateEndpoint), + PrivateSrv: connStrings.PrivateSrv, + Standard: connStrings.Standard, + StandardSrv: connStrings.StandardSrv, + } +} + +func convertPrivateEndpointToLatest(privateEndpoints *[]admin20231115.ClusterDescriptionConnectionStringsPrivateEndpoint) *[]admin.ClusterDescriptionConnectionStringsPrivateEndpoint { + if privateEndpoints == nil { + return nil + } + peSlice := *privateEndpoints + results := make([]admin.ClusterDescriptionConnectionStringsPrivateEndpoint, len(peSlice)) + for i := range len(peSlice) { + pe := peSlice[i] + results[i] = admin.ClusterDescriptionConnectionStringsPrivateEndpoint{ + ConnectionString: pe.ConnectionString, + Endpoints: convertEndpointsToLatest(pe.Endpoints), + SrvConnectionString: pe.SrvConnectionString, + SrvShardOptimizedConnectionString: pe.SrvShardOptimizedConnectionString, + Type: pe.Type, + } + } + return &results +} + +func convertEndpointsToLatest(privateEndpoints *[]admin20231115.ClusterDescriptionConnectionStringsPrivateEndpointEndpoint) *[]admin.ClusterDescriptionConnectionStringsPrivateEndpointEndpoint { + if privateEndpoints == nil { + return nil + } + peSlice := *privateEndpoints + results := make([]admin.ClusterDescriptionConnectionStringsPrivateEndpointEndpoint, len(peSlice)) + for i := range len(peSlice) { + pe := peSlice[i] + results[i] = admin.ClusterDescriptionConnectionStringsPrivateEndpointEndpoint{ + EndpointId: pe.EndpointId, + ProviderName: pe.ProviderName, + Region: pe.Region, + } + } + return &results +} + +func convertLabelsToLatest(labels *[]admin20231115.ComponentLabel) *[]admin.ComponentLabel { + labelSlice := *labels + results := make([]admin.ComponentLabel, len(labelSlice)) + for i := range len(labelSlice) { + label := labelSlice[i] + results[i] = admin.ComponentLabel{ + Key: label.Key, + Value: label.Value, + } + } + return &results +} + func convertLabelSliceToOldSDK(slice []admin.ComponentLabel, err diag.Diagnostics) ([]admin20231115.ComponentLabel, diag.Diagnostics) { if err != nil { return nil, err @@ -128,3 +197,110 @@ func convertDedicatedHardwareSpecToOldSDK(spec *admin.DedicatedHardwareSpec) *ad InstanceSize: spec.InstanceSize, } } + +func convertDedicatedHwSpecToLatest(spec *admin20231115.DedicatedHardwareSpec, rootDiskSizeGB float64) *admin.DedicatedHardwareSpec { + if spec == nil { + return nil + } + return &admin.DedicatedHardwareSpec{ + NodeCount: spec.NodeCount, + DiskIOPS: spec.DiskIOPS, + EbsVolumeType: spec.EbsVolumeType, + InstanceSize: spec.InstanceSize, + DiskSizeGB: &rootDiskSizeGB, + } +} + +func convertAdvancedAutoScalingSettingsToLatest(settings *admin20231115.AdvancedAutoScalingSettings) *admin.AdvancedAutoScalingSettings { + if settings == nil { + return nil + } + return &admin.AdvancedAutoScalingSettings{ + Compute: convertAdvancedComputeAutoScalingToLatest(settings.Compute), + DiskGB: convertDiskGBAutoScalingToLatest(settings.DiskGB), + } +} + +func convertAdvancedComputeAutoScalingToLatest(settings *admin20231115.AdvancedComputeAutoScaling) *admin.AdvancedComputeAutoScaling { + if settings == nil { + return nil + } + return &admin.AdvancedComputeAutoScaling{ + Enabled: settings.Enabled, + MaxInstanceSize: settings.MaxInstanceSize, + MinInstanceSize: settings.MinInstanceSize, + ScaleDownEnabled: settings.ScaleDownEnabled, + } +} + +func convertDiskGBAutoScalingToLatest(settings *admin20231115.DiskGBAutoScaling) *admin.DiskGBAutoScaling { + if settings == nil { + return nil + } + return &admin.DiskGBAutoScaling{ + Enabled: settings.Enabled, + } +} + +func convertHardwareSpecToLatest(hwspec *admin20231115.HardwareSpec, rootDiskSizeGB float64) *admin.HardwareSpec { + if hwspec == nil { + return nil + } + return &admin.HardwareSpec{ + DiskIOPS: hwspec.DiskIOPS, + EbsVolumeType: hwspec.EbsVolumeType, + InstanceSize: hwspec.InstanceSize, + NodeCount: hwspec.NodeCount, + DiskSizeGB: &rootDiskSizeGB, + } +} + +func convertRegionConfigSliceToLatest(slice *[]admin20231115.CloudRegionConfig, rootDiskSizeGB float64) *[]admin.CloudRegionConfig { + if slice == nil { + return nil + } + cloudRegionSlice := *slice + results := make([]admin.CloudRegionConfig, len(cloudRegionSlice)) + for i := range len(cloudRegionSlice) { + cloudRegion := cloudRegionSlice[i] + results[i] = admin.CloudRegionConfig{ + ElectableSpecs: convertHardwareSpecToLatest(cloudRegion.ElectableSpecs, rootDiskSizeGB), + Priority: cloudRegion.Priority, + ProviderName: cloudRegion.ProviderName, + RegionName: cloudRegion.RegionName, + AnalyticsAutoScaling: convertAdvancedAutoScalingSettingsToLatest(cloudRegion.AnalyticsAutoScaling), + AnalyticsSpecs: convertDedicatedHwSpecToLatest(cloudRegion.AnalyticsSpecs, rootDiskSizeGB), + AutoScaling: convertAdvancedAutoScalingSettingsToLatest(cloudRegion.AutoScaling), + ReadOnlySpecs: convertDedicatedHwSpecToLatest(cloudRegion.ReadOnlySpecs, rootDiskSizeGB), + BackingProviderName: cloudRegion.BackingProviderName, + } + } + return &results +} + +func convertClusterDescToLatestExcludeRepSpecs(oldClusterDesc *admin20231115.AdvancedClusterDescription) *admin.ClusterDescription20240710 { + return &admin.ClusterDescription20240710{ + BackupEnabled: oldClusterDesc.BackupEnabled, + AcceptDataRisksAndForceReplicaSetReconfig: oldClusterDesc.AcceptDataRisksAndForceReplicaSetReconfig, + ClusterType: oldClusterDesc.ClusterType, + CreateDate: oldClusterDesc.CreateDate, + DiskWarmingMode: oldClusterDesc.DiskWarmingMode, + EncryptionAtRestProvider: oldClusterDesc.EncryptionAtRestProvider, + GlobalClusterSelfManagedSharding: oldClusterDesc.GlobalClusterSelfManagedSharding, + GroupId: oldClusterDesc.GroupId, + Id: oldClusterDesc.Id, + MongoDBMajorVersion: oldClusterDesc.MongoDBMajorVersion, + MongoDBVersion: oldClusterDesc.MongoDBVersion, + Name: oldClusterDesc.Name, + Paused: oldClusterDesc.Paused, + PitEnabled: oldClusterDesc.PitEnabled, + RootCertType: oldClusterDesc.RootCertType, + StateName: oldClusterDesc.StateName, + TerminationProtectionEnabled: oldClusterDesc.TerminationProtectionEnabled, + VersionReleaseSystem: oldClusterDesc.VersionReleaseSystem, + Tags: convertTagsToLatest(oldClusterDesc.Tags), + BiConnector: convertBiConnectToLatest(oldClusterDesc.BiConnector), + ConnectionStrings: convertConnectionStringToLatest(oldClusterDesc.ConnectionStrings), + Labels: convertLabelsToLatest(oldClusterDesc.Labels), + } +} diff --git a/internal/service/advancedcluster/resource_advanced_cluster.go b/internal/service/advancedcluster/resource_advanced_cluster.go index 7249367a05..c342b41065 100644 --- a/internal/service/advancedcluster/resource_advanced_cluster.go +++ b/internal/service/advancedcluster/resource_advanced_cluster.go @@ -12,17 +12,19 @@ import ( "strings" "time" + admin20231115 "go.mongodb.org/atlas-sdk/v20231115014/admin" + "go.mongodb.org/atlas-sdk/v20240530001/admin" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/spf13/cast" + "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/common/validate" "github.com/mongodb/terraform-provider-mongodbatlas/internal/config" - "github.com/spf13/cast" - admin20231115 "go.mongodb.org/atlas-sdk/v20231115014/admin" - "go.mongodb.org/atlas-sdk/v20240530001/admin" ) const ( @@ -339,6 +341,11 @@ func schemaSpecs() *schema.Schema { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "disk_size_gb": { + Type: schema.TypeFloat, + Optional: true, + Computed: true, + }, "disk_iops": { Type: schema.TypeInt, Optional: true, @@ -484,6 +491,7 @@ func CreateStateChangeConfig(ctx context.Context, connV2 *admin20231115.APIClien func resourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { connV2 := meta.(*config.MongoDBClient).AtlasV2 + connPreview := meta.(*config.MongoDBClient).AtlasV2Preview ids := conversion.DecodeStateID(d.Id()) projectID := ids["project_id"] clusterName := ids["cluster_name"] @@ -505,7 +513,7 @@ func resourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Di return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "backup_enabled", clusterName, err)) } - if err := d.Set("bi_connector_config", flattenBiConnectorConfig(cluster.GetBiConnector())); err != nil { + if err := d.Set("bi_connector_config", flattenBiConnectorConfig(convertBiConnectToLatest(cluster.BiConnector))); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "bi_connector_config", clusterName, err)) } @@ -513,7 +521,7 @@ func resourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Di return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "cluster_type", clusterName, err)) } - if err := d.Set("connection_strings", flattenConnectionStrings(cluster.GetConnectionStrings())); err != nil { + if err := d.Set("connection_strings", flattenConnectionStrings(*convertConnectionStringToLatest(cluster.ConnectionStrings))); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "connection_strings", clusterName, err)) } @@ -529,7 +537,7 @@ func resourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Di return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "encryption_at_rest_provider", clusterName, err)) } - if err := d.Set("labels", flattenLabels(cluster.GetLabels())); err != nil { + if err := d.Set("labels", flattenLabels(*convertLabelsToLatest(cluster.Labels))); err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "labels", clusterName, err)) } @@ -557,7 +565,7 @@ func resourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Di return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "pit_enabled", clusterName, err)) } - replicationSpecs, err := FlattenAdvancedReplicationSpecs(ctx, cluster.GetReplicationSpecs(), d.Get("replication_specs").([]any), d, connV2) + replicationSpecs, err := FlattenAdvancedReplicationSpecsOldSDK(ctx, cluster.GetReplicationSpecs(), cluster.GetDiskSizeGB(), d.Get("replication_specs").([]any), d, connPreview) if err != nil { return diag.FromErr(fmt.Errorf(ErrorClusterAdvancedSetting, "replication_specs", clusterName, err)) }