diff --git a/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule.go b/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule.go index d4b1a8e71a..f3876b00bf 100644 --- a/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule.go +++ b/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule.go @@ -280,13 +280,27 @@ func resourceMongoDBAtlasCloudBackupSchedule() *schema.Resource { } func resourceMongoDBAtlasCloudBackupScheduleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics conn := meta.(*MongoDBClient).Atlas projectID := d.Get("project_id").(string) clusterName := d.Get("cluster_name").(string) - err := cloudBackupScheduleCreateOrUpdate(ctx, conn, d, projectID, clusterName) - if err != nil { - return diag.Errorf(errorSnapshotBackupScheduleCreate, err) + // When a new cluster is created with the backup feature enabled, + // MongoDB Atlas automatically generates a default backup policy for that cluster. + // As a result, we need to first delete the default policies to avoid having + // the infrastructure differs from the TF configuration file. + if _, _, err := conn.CloudProviderSnapshotBackupPolicies.Delete(ctx, projectID, clusterName); err != nil { + diagWarning := diag.Diagnostic{ + Severity: diag.Warning, + Summary: "Error deleting default backup schedule", + Detail: fmt.Sprintf("error deleting default MongoDB Cloud Backup Schedule (%s): %s", clusterName, err), + } + diags = append(diags, diagWarning) + } + + if err := cloudBackupScheduleCreateOrUpdate(ctx, conn, d, projectID, clusterName); err != nil { + diags = append(diags, diag.Errorf(errorSnapshotBackupScheduleCreate, err)...) + return diags } d.SetId(encodeStateID(map[string]string{ @@ -440,23 +454,6 @@ func resourceMongoDBAtlasCloudBackupScheduleImportState(ctx context.Context, d * } func cloudBackupScheduleCreateOrUpdate(ctx context.Context, conn *matlas.Client, d *schema.ResourceData, projectID, clusterName string) error { - _, policyMonthlyOK := d.GetOk("policy_item_monthly") - _, policyWeeklyOK := d.GetOk("policy_item_weekly") - _, policyDailyOK := d.GetOk("policy_item_daily") - _, policyhourlyOK := d.GetOk("policy_item_hourly") - - // When a new cluster is created with the backup feature enabled, - // MongoDB Atlas automatically generates a default backup policy for that cluster. - // However, in the scenario where the user hasn't provided a backup policy, - // we want to make sure that the default backup policy is removed first. - // This is to avoid having the infrastructure differs from the TF configuration file. - if !policyMonthlyOK && !policyWeeklyOK && !policyDailyOK && !policyhourlyOK { - _, _, err := conn.CloudProviderSnapshotBackupPolicies.Delete(ctx, projectID, clusterName) - if err != nil { - log.Printf("error deleting MongoDB Cloud Backup Schedule (%s): %s", clusterName, err) - } - } - // Get policies items resp, _, err := conn.CloudProviderSnapshotBackupPolicies.Get(ctx, projectID, clusterName) if err != nil { @@ -477,6 +474,7 @@ func cloudBackupScheduleCreateOrUpdate(ctx context.Context, conn *matlas.Client, if v, ok := d.GetOk("policy_item_hourly"); ok { item := v.([]interface{}) itemObj := item[0].(map[string]interface{}) + policyItem.ID = policyItemID(itemObj) policyItem.FrequencyType = snapshotScheduleHourly policyItem.RetentionUnit = itemObj["retention_unit"].(string) policyItem.FrequencyInterval = itemObj["frequency_interval"].(int) @@ -486,6 +484,7 @@ func cloudBackupScheduleCreateOrUpdate(ctx context.Context, conn *matlas.Client, if v, ok := d.GetOk("policy_item_daily"); ok { item := v.([]interface{}) itemObj := item[0].(map[string]interface{}) + policyItem.ID = policyItemID(itemObj) policyItem.FrequencyType = snapshotScheduleDaily policyItem.RetentionUnit = itemObj["retention_unit"].(string) policyItem.FrequencyInterval = itemObj["frequency_interval"].(int) @@ -496,6 +495,7 @@ func cloudBackupScheduleCreateOrUpdate(ctx context.Context, conn *matlas.Client, items := v.([]interface{}) for _, s := range items { itemObj := s.(map[string]interface{}) + policyItem.ID = policyItemID(itemObj) policyItem.FrequencyType = snapshotScheduleWeekly policyItem.RetentionUnit = itemObj["retention_unit"].(string) policyItem.FrequencyInterval = itemObj["frequency_interval"].(int) @@ -507,6 +507,7 @@ func cloudBackupScheduleCreateOrUpdate(ctx context.Context, conn *matlas.Client, items := v.([]interface{}) for _, s := range items { itemObj := s.(map[string]interface{}) + policyItem.ID = policyItemID(itemObj) policyItem.FrequencyType = snapshotScheduleMonthly policyItem.RetentionUnit = itemObj["retention_unit"].(string) policyItem.FrequencyInterval = itemObj["frequency_interval"].(int) @@ -641,3 +642,15 @@ func expandCopySettings(tfList []interface{}) []matlas.CopySetting { } return copySettings } + +func policyItemID(policyState map[string]interface{}) string { + // if the policyItem has the ID field, this is the update operation + // we return the ID that was stored in the TF state + if val, ok := policyState["id"]; ok { + if id, ok := val.(string); ok { + return id + } + } + + return "" +} diff --git a/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule_test.go b/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule_test.go index 53e9c0d250..6475ff0899 100644 --- a/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule_test.go +++ b/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule_test.go @@ -68,15 +68,19 @@ func TestAccBackupRSCloudBackupSchedule_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "policy_item_daily.#", "1"), resource.TestCheckResourceAttr(resourceName, "policy_item_weekly.#", "1"), resource.TestCheckResourceAttr(resourceName, "policy_item_monthly.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "policy_item_hourly.0.id"), resource.TestCheckResourceAttr(resourceName, "policy_item_hourly.0.frequency_interval", "2"), resource.TestCheckResourceAttr(resourceName, "policy_item_hourly.0.retention_unit", "days"), resource.TestCheckResourceAttr(resourceName, "policy_item_hourly.0.retention_value", "1"), + resource.TestCheckResourceAttrSet(resourceName, "policy_item_daily.0.id"), resource.TestCheckResourceAttr(resourceName, "policy_item_daily.0.frequency_interval", "1"), resource.TestCheckResourceAttr(resourceName, "policy_item_daily.0.retention_unit", "days"), resource.TestCheckResourceAttr(resourceName, "policy_item_daily.0.retention_value", "4"), + resource.TestCheckResourceAttrSet(resourceName, "policy_item_weekly.0.id"), resource.TestCheckResourceAttr(resourceName, "policy_item_weekly.0.frequency_interval", "4"), resource.TestCheckResourceAttr(resourceName, "policy_item_weekly.0.retention_unit", "weeks"), resource.TestCheckResourceAttr(resourceName, "policy_item_weekly.0.retention_value", "2"), + resource.TestCheckResourceAttrSet(resourceName, "policy_item_monthly.0.id"), resource.TestCheckResourceAttr(resourceName, "policy_item_monthly.0.frequency_interval", "5"), resource.TestCheckResourceAttr(resourceName, "policy_item_monthly.0.retention_unit", "months"), resource.TestCheckResourceAttr(resourceName, "policy_item_monthly.0.retention_value", "3"), @@ -103,15 +107,19 @@ func TestAccBackupRSCloudBackupSchedule_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "policy_item_daily.#", "1"), resource.TestCheckResourceAttr(resourceName, "policy_item_weekly.#", "2"), resource.TestCheckResourceAttr(resourceName, "policy_item_monthly.#", "2"), + resource.TestCheckResourceAttrSet(resourceName, "policy_item_hourly.0.id"), resource.TestCheckResourceAttr(resourceName, "policy_item_hourly.0.frequency_interval", "2"), resource.TestCheckResourceAttr(resourceName, "policy_item_hourly.0.retention_unit", "days"), resource.TestCheckResourceAttr(resourceName, "policy_item_hourly.0.retention_value", "1"), + resource.TestCheckResourceAttrSet(resourceName, "policy_item_daily.0.id"), resource.TestCheckResourceAttr(resourceName, "policy_item_daily.0.frequency_interval", "1"), resource.TestCheckResourceAttr(resourceName, "policy_item_daily.0.retention_unit", "days"), resource.TestCheckResourceAttr(resourceName, "policy_item_daily.0.retention_value", "4"), + resource.TestCheckResourceAttrSet(resourceName, "policy_item_weekly.0.id"), resource.TestCheckResourceAttr(resourceName, "policy_item_weekly.0.frequency_interval", "4"), resource.TestCheckResourceAttr(resourceName, "policy_item_weekly.0.retention_unit", "weeks"), resource.TestCheckResourceAttr(resourceName, "policy_item_weekly.0.retention_value", "2"), + resource.TestCheckResourceAttrSet(resourceName, "policy_item_monthly.0.id"), resource.TestCheckResourceAttr(resourceName, "policy_item_monthly.0.frequency_interval", "5"), resource.TestCheckResourceAttr(resourceName, "policy_item_monthly.0.retention_unit", "months"), resource.TestCheckResourceAttr(resourceName, "policy_item_monthly.0.retention_value", "3"),