diff --git a/.changelog/3500.txt b/.changelog/3500.txt new file mode 100644 index 0000000000..c36eb278e4 --- /dev/null +++ b/.changelog/3500.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +resource/mongodbatlas_cloud_backup_schedule: Changes `export` and `auto_export_enabled` to Optional only +``` diff --git a/docs/resources/cloud_backup_schedule.md b/docs/resources/cloud_backup_schedule.md index 8999b7064e..1fd7e289a0 100644 --- a/docs/resources/cloud_backup_schedule.md +++ b/docs/resources/cloud_backup_schedule.md @@ -228,12 +228,12 @@ resource "mongodbatlas_cloud_backup_schedule" "test" { * `policy_item_weekly` - (Optional) Weekly policy item. See [below](#policy_item_weekly) * `policy_item_monthly` - (Optional) Monthly policy item. See [below](#policy_item_monthly) * `policy_item_yearly` - (Optional) Yearly policy item. See [below](#policy_item_yearly) -* `auto_export_enabled` - Flag that indicates whether MongoDB Cloud automatically exports Cloud Backup Snapshots to the Export Bucket. Once enabled, it must be disabled by explicitly setting the value to `false`. Value can be one of the following: +* `auto_export_enabled` - (Optional) Flag that indicates whether MongoDB Cloud automatically exports Cloud Backup Snapshots to the Export Bucket. Value can be one of the following: * true - Enables automatic export of cloud backup snapshots to the Export Bucket. * false - Disables automatic export of cloud backup snapshots to the Export Bucket. (default) * `use_org_and_group_names_in_export_prefix` - Specify true to use organization and project names instead of organization and project UUIDs in the path for the metadata files that Atlas uploads to your bucket after it finishes exporting the snapshots. To learn more about the metadata files that Atlas uploads, see [Export Cloud Backup Snapshot](https://www.mongodb.com/docs/atlas/backup/cloud-backup/export/#std-label-cloud-provider-snapshot-export). * `copy_settings` - List that contains a document for each copy setting item in the desired backup policy. See [below](#copy_settings) -* `export` - Policy for automatically exporting Cloud Backup Snapshots. `auto_export_enabled` must be set to true when defining this attribute. See [below](#export) +* `export` - Policy for automatically exporting Cloud Backup Snapshots. See [below](#export) ### export * `export_bucket_id` - Unique identifier of the mongodbatlas_cloud_backup_snapshot_export_bucket export_bucket_id value. * `frequency_type` - Frequency associated with the export snapshot item: `weekly`, `monthly`, `yearly`, `daily` (requires reaching out to Customer Support) diff --git a/internal/service/cloudbackupschedule/resource_cloud_backup_schedule.go b/internal/service/cloudbackupschedule/resource_cloud_backup_schedule.go index d328501065..ee06914f0d 100644 --- a/internal/service/cloudbackupschedule/resource_cloud_backup_schedule.go +++ b/internal/service/cloudbackupschedule/resource_cloud_backup_schedule.go @@ -63,7 +63,6 @@ func Resource() *schema.Resource { "auto_export_enabled": { Type: schema.TypeBool, Optional: true, - Computed: true, }, "use_org_and_group_names_in_export_prefix": { Type: schema.TypeBool, @@ -116,7 +115,6 @@ func Resource() *schema.Resource { Type: schema.TypeList, MaxItems: 1, Optional: true, - Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "export_bucket_id": { @@ -436,14 +434,6 @@ func setSchemaFieldsExceptCopySettings(d *schema.ResourceData, backupPolicy *adm return diag.Errorf(errorSnapshotBackupScheduleSetting, "id_policy", clusterName, err) } - if err := d.Set("export", FlattenExport(backupPolicy)); err != nil { - return diag.Errorf(errorSnapshotBackupScheduleSetting, "export", clusterName, err) - } - - if err := d.Set("auto_export_enabled", backupPolicy.GetAutoExportEnabled()); err != nil { - return diag.Errorf(errorSnapshotBackupScheduleSetting, "auto_export_enabled", clusterName, err) - } - if err := d.Set("use_org_and_group_names_in_export_prefix", backupPolicy.GetUseOrgAndGroupNamesInExportPrefix()); err != nil { return diag.Errorf(errorSnapshotBackupScheduleSetting, "use_org_and_group_names_in_export_prefix", clusterName, err) } @@ -573,7 +563,7 @@ func cloudBackupScheduleCreateOrUpdate(ctx context.Context, connV220240530 *admi } if v, ok := d.GetOk("export"); ok { - req.Export = expandAutoExportPolicy(v.([]any), d) + req.Export = expandAutoExportPolicy(v.([]any)) } if d.HasChange("use_org_and_group_names_in_export_prefix") { @@ -700,16 +690,12 @@ func expandCopySettingOldSDK(tfMap map[string]any) *admin20240530.DiskBackupCopy return copySetting } -func expandAutoExportPolicy(items []any, d *schema.ResourceData) *admin.AutoExportPolicy { +func expandAutoExportPolicy(items []any) *admin.AutoExportPolicy { itemObj := items[0].(map[string]any) - - if autoExportEnabled := d.Get("auto_export_enabled"); autoExportEnabled != nil && autoExportEnabled.(bool) { - return &admin.AutoExportPolicy{ - ExportBucketId: conversion.StringPtr(itemObj["export_bucket_id"].(string)), - FrequencyType: conversion.StringPtr(itemObj["frequency_type"].(string)), - } + return &admin.AutoExportPolicy{ + ExportBucketId: conversion.StringPtr(itemObj["export_bucket_id"].(string)), + FrequencyType: conversion.StringPtr(itemObj["frequency_type"].(string)), } - return nil } func ExpandPolicyItems(items []any, frequencyType string) *[]admin.DiskBackupApiPolicyItem { diff --git a/internal/service/cloudbackupschedule/resource_cloud_backup_schedule_migration_test.go b/internal/service/cloudbackupschedule/resource_cloud_backup_schedule_migration_test.go index d5cef4cb6f..962d8176e8 100644 --- a/internal/service/cloudbackupschedule/resource_cloud_backup_schedule_migration_test.go +++ b/internal/service/cloudbackupschedule/resource_cloud_backup_schedule_migration_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/mig" @@ -127,3 +128,55 @@ func TestMigBackupRSCloudBackupSchedule_copySettings(t *testing.T) { }, }) } + +func TestMigBackupRSCloudBackupSchedule_export(t *testing.T) { + mig.SkipIfVersionBelow(t, "2.0.0") // in 2.0.0 we made auto_export_enabled and export fields optional only + var ( + clusterInfo = acc.GetClusterInfo(t, &acc.ClusterRequest{CloudBackup: true, ResourceDependencyName: "mongodbatlas_cloud_backup_snapshot_export_bucket.test"}) + policyName = acc.RandomName() + roleName = acc.RandomIAMRole() + bucketName = acc.RandomS3BucketName() + + configWithExport = configExportPolicies(&clusterInfo, policyName, roleName, bucketName, true, true) + configWithoutExport = configExportPolicies(&clusterInfo, policyName, roleName, bucketName, false, false) + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: mig.PreCheckBasicSleep(t), + CheckDestroy: checkDestroy, + Steps: []resource.TestStep{ + // Step 1: Apply config with export and auto_export_enabled (old provider) + { + ExternalProviders: mig.ExternalProvidersWithAWS(), + Config: configWithExport, + Check: resource.ComposeAggregateTestCheckFunc( + checkExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "cluster_name", clusterInfo.Name), + resource.TestCheckResourceAttr(resourceName, "auto_export_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "export.#", "1"), + ), + }, + // Step 2: Remove export and auto_export_enabled, expect empty plan (old provider) + { + ExternalProviders: mig.ExternalProvidersWithAWS(), + Config: configWithExport, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectEmptyPlan(), + }, + }, + }, + // Step 3: Apply config without export and auto_export_enabled (new provider) + { + ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, + Config: configWithoutExport, + Check: resource.ComposeAggregateTestCheckFunc( + checkExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "cluster_name", clusterInfo.Name), + resource.TestCheckResourceAttr(resourceName, "auto_export_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "export.#", "0"), + ), + }, + }, + }) +} diff --git a/internal/service/cloudbackupschedule/resource_cloud_backup_schedule_test.go b/internal/service/cloudbackupschedule/resource_cloud_backup_schedule_test.go index 610e7dc3ab..8c00759860 100644 --- a/internal/service/cloudbackupschedule/resource_cloud_backup_schedule_test.go +++ b/internal/service/cloudbackupschedule/resource_cloud_backup_schedule_test.go @@ -165,7 +165,7 @@ func TestAccBackupRSCloudBackupSchedule_export(t *testing.T) { Steps: []resource.TestStep{ { - Config: configExportPolicies(&clusterInfo, policyName, roleName, bucketName), + Config: configExportPolicies(&clusterInfo, policyName, roleName, bucketName, true, true), Check: resource.ComposeAggregateTestCheckFunc( checkExists(resourceName), resource.TestCheckResourceAttr(resourceName, "cluster_name", clusterInfo.Name), @@ -179,6 +179,15 @@ func TestAccBackupRSCloudBackupSchedule_export(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "policy_item_daily.0.retention_value", "4"), ), }, + { + Config: configExportPolicies(&clusterInfo, policyName, roleName, bucketName, false, false), + Check: resource.ComposeAggregateTestCheckFunc( + checkExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "cluster_name", clusterInfo.Name), + resource.TestCheckResourceAttr(resourceName, "auto_export_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "export.#", "0"), + ), + }, }, }) } @@ -934,12 +943,23 @@ func configAdvancedPolicies(info *acc.ClusterInfo, p *admin20240530.DiskBackupSn `, info.TerraformNameRef, info.ProjectID, p.GetReferenceHourOfDay(), p.GetReferenceMinuteOfHour(), p.GetRestoreWindowDays()) } -func configExportPolicies(info *acc.ClusterInfo, policyName, roleName, bucketName string) string { +func configExportPolicies(info *acc.ClusterInfo, policyName, roleName, bucketName string, includeAutoExport, includeExport bool) string { + autoExport := "" + export := "" + if includeAutoExport { + autoExport = "auto_export_enabled = true" + } + if includeExport { + export = `export { + export_bucket_id = mongodbatlas_cloud_backup_snapshot_export_bucket.test.export_bucket_id + frequency_type = "monthly" + }` + } return info.TerraformStr + fmt.Sprintf(` resource "mongodbatlas_cloud_backup_schedule" "schedule_test" { cluster_name = %[1]s project_id = %[2]q - auto_export_enabled = true + %[6]s reference_hour_of_day = 20 reference_minute_of_hour = "05" restore_window_days = 4 @@ -966,10 +986,7 @@ func configExportPolicies(info *acc.ClusterInfo, policyName, roleName, bucketNam retention_value = 4 } - export { - export_bucket_id = mongodbatlas_cloud_backup_snapshot_export_bucket.test.export_bucket_id - frequency_type = "monthly" - } + %[7]s } resource "aws_s3_bucket" "backup" { @@ -1040,7 +1057,7 @@ func configExportPolicies(info *acc.ClusterInfo, policyName, roleName, bucketNam } EOF } - `, info.TerraformNameRef, info.ProjectID, policyName, roleName, bucketName) + `, info.TerraformNameRef, info.ProjectID, policyName, roleName, bucketName, autoExport, export) } func importStateIDFunc(resourceName string) resource.ImportStateIdFunc {