Skip to content

Commit a7e5f68

Browse files
authored
feat: Long-running operation improvements for mongodbatlas_online_archive resource (#3542)
* implement delete_on_create_timeout * renames * fix * use v2 in delete * date criteria * config
1 parent 4697bcf commit a7e5f68

File tree

6 files changed

+73
-21
lines changed

6 files changed

+73
-21
lines changed

.changelog/3542.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
resource/mongodbatlas_online_archive: Adds `delete_on_create_timeout` attribute to indicate whether to delete the resource if its creation times out
3+
```

docs/resources/online_archive.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ resource "mongodbatlas_online_archive" "test" {
117117
* `paused` - (Optional) State of the online archive. This is required for pausing an active online archive or resuming a paused online archive. If the collection has another active online archive, the resume request fails.
118118
* `sync_creation` - (Optional) Flag that indicates whether the provider will wait for the state of the online archive to reach `IDLE` or `ACTIVE` when creating an online archive. Defaults to `false`.
119119
* `timeouts`- (Optional) The duration of time to wait for Online Archive to be created. The timeout value is defined by a signed sequence of decimal numbers with a time unit suffix such as: `1h45m`, `300s`, `10m`, etc. The valid time units are: `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. The default timeout for Online Archive create is `3h`. Learn more about timeouts [here](https://www.terraform.io/plugin/sdkv2/resources/retries-and-customizable-timeouts).
120+
* `delete_on_create_timeout`- (Optional) Flag that indicates whether to delete the resource if creation times out. Default is `true`. When Terraform apply fails, it returns immediately without waiting for cleanup to complete. If you suspect a transient error, wait before retrying to allow resource deletion to finish.
120121

121122
### Criteria
122123

internal/service/onlinearchive/resource_online_archive.go renamed to internal/service/onlinearchive/resource.go

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
1313
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1414
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
15+
"github.com/mongodb/terraform-provider-mongodbatlas/internal/common/cleanup"
1516
"github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion"
1617
"github.com/mongodb/terraform-provider-mongodbatlas/internal/common/validate"
1718
"github.com/mongodb/terraform-provider-mongodbatlas/internal/config"
@@ -22,15 +23,16 @@ const (
2223
errorOnlineArchivesCreate = "error creating MongoDB Atlas Online Archive:: %s"
2324
errorOnlineArchivesDelete = "error deleting MongoDB Atlas Online Archive: %s archive_id (%s)"
2425
scheduleTypeDefault = "DEFAULT"
26+
oneMinute = 1 * time.Minute
2527
)
2628

2729
func Resource() *schema.Resource {
2830
return &schema.Resource{
29-
Schema: resourceSchema(),
30-
CreateContext: resourceCreate,
31-
ReadContext: resourceRead,
32-
DeleteContext: resourceDelete,
33-
UpdateContext: resourceUpdate,
31+
Schema: resourceSchema(),
32+
CreateWithoutTimeout: resourceCreate,
33+
ReadWithoutTimeout: resourceRead,
34+
UpdateWithoutTimeout: resourceUpdate,
35+
DeleteWithoutTimeout: resourceDelete,
3436
Importer: &schema.ResourceImporter{
3537
StateContext: resourceImport,
3638
},
@@ -210,6 +212,11 @@ func resourceSchema() map[string]*schema.Schema {
210212
Type: schema.TypeString,
211213
Computed: true,
212214
},
215+
"delete_on_create_timeout": { // Don't use Default: true to avoid unplanned changes when upgrading from previous versions.
216+
Type: schema.TypeBool,
217+
Optional: true,
218+
Description: "Flag that indicates whether to delete the resource if creation times out. Default is true.",
219+
},
213220
"sync_creation": {
214221
Type: schema.TypeBool,
215222
Optional: true,
@@ -243,15 +250,23 @@ func resourceCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.
243250
Pending: []string{"PENDING", "ARCHIVING", "PAUSING", "PAUSED", "ORPHANED", "REPEATING"},
244251
Target: []string{"IDLE", "ACTIVE"},
245252
Refresh: resourceOnlineRefreshFunc(ctx, projectID, clusterName, archiveID, connV2),
246-
Timeout: d.Timeout(schema.TimeoutCreate) - time.Minute, // When using a CRUD function with a timeout, any StateChangeConf timeouts must be configured below that duration to avoid returning the SDK context: deadline exceeded error instead of the retry logic error.
247-
MinTimeout: 1 * time.Minute,
248-
Delay: 3 * time.Minute,
253+
Timeout: d.Timeout(schema.TimeoutCreate) - oneMinute, // When using a CRUD function with a timeout, any StateChangeConf timeouts must be configured below that duration to avoid returning the SDK context: deadline exceeded error instead of the retry logic error.
254+
MinTimeout: oneMinute,
255+
Delay: oneMinute,
249256
}
250257

251258
// Wait, catching any errors
252-
_, err := stateConf.WaitForStateContext(ctx)
253-
if err != nil {
254-
return diag.FromErr(fmt.Errorf("error updating the online archive status %s for cluster %s", clusterName, archiveID))
259+
_, errWait := stateConf.WaitForStateContext(ctx)
260+
deleteOnCreateTimeout := true // default value when not set
261+
if v, ok := d.GetOkExists("delete_on_create_timeout"); ok {
262+
deleteOnCreateTimeout = v.(bool)
263+
}
264+
errWait = cleanup.HandleCreateTimeout(deleteOnCreateTimeout, errWait, func(ctxCleanup context.Context) error {
265+
_, errCleanup := connV2.OnlineArchiveApi.DeleteOnlineArchive(ctxCleanup, projectID, archiveID, clusterName).Execute()
266+
return errCleanup
267+
})
268+
if errWait != nil {
269+
return diag.FromErr(fmt.Errorf("error updating the online archive status %s for cluster %s: %s", clusterName, archiveID, errWait))
255270
}
256271
}
257272

@@ -314,21 +329,21 @@ func resourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Di
314329
}
315330

316331
func resourceDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
317-
conn := meta.(*config.MongoDBClient).Atlas
332+
connV2 := meta.(*config.MongoDBClient).AtlasV2
318333
ids := conversion.DecodeStateID(d.Id())
319-
atlasID := ids["archive_id"]
334+
archiveID := ids["archive_id"]
320335
projectID := ids["project_id"]
321336
clusterName := ids["cluster_name"]
322337

323-
_, err := conn.OnlineArchives.Delete(ctx, projectID, clusterName, atlasID)
338+
_, err := connV2.OnlineArchiveApi.DeleteOnlineArchive(ctx, projectID, archiveID, clusterName).Execute()
324339

325340
if err != nil {
326341
alreadyDeleted := strings.Contains(err.Error(), "404") && !d.IsNewResource()
327342
if alreadyDeleted {
328343
return nil
329344
}
330345

331-
return diag.FromErr(fmt.Errorf(errorOnlineArchivesDelete, err, atlasID))
346+
return diag.FromErr(fmt.Errorf(errorOnlineArchivesDelete, err, archiveID))
332347
}
333348
return nil
334349
}

internal/service/onlinearchive/resource_online_archive_migration_test.go renamed to internal/service/onlinearchive/resource_migration_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func TestMigBackupRSOnlineArchiveWithNoChangeBetweenVersions(t *testing.T) {
2222
if mig.IsProviderVersionAtLeast("1.12.2") {
2323
deleteExpirationDays = 7
2424
}
25-
config := configWithDailySchedule(clusterTerraformStr, clusterResourceName, 1, deleteExpirationDays)
25+
config := configWithDailySchedule(clusterTerraformStr, clusterResourceName, 1, deleteExpirationDays, false)
2626

2727
resource.ParallelTest(t, resource.TestCase{
2828
PreCheck: mig.PreCheckBasicSleep(t),

internal/service/onlinearchive/resource_online_archive_test.go renamed to internal/service/onlinearchive/resource_test.go

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestAccBackupRSOnlineArchive(t *testing.T) {
4242
Check: acc.PopulateWithSampleDataTestCheck(projectID, clusterName),
4343
},
4444
{
45-
Config: configWithDailySchedule(clusterTerraformStr, clusterResourceName, 1, 7),
45+
Config: configWithDailySchedule(clusterTerraformStr, clusterResourceName, 1, 7, false),
4646
Check: resource.ComposeAggregateTestCheckFunc(
4747
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
4848
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
@@ -58,7 +58,7 @@ func TestAccBackupRSOnlineArchive(t *testing.T) {
5858
),
5959
},
6060
{
61-
Config: configWithDailySchedule(clusterTerraformStr, clusterResourceName, 2, 8),
61+
Config: configWithDailySchedule(clusterTerraformStr, clusterResourceName, 2, 8, false),
6262
Check: resource.ComposeAggregateTestCheckFunc(
6363
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
6464
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
@@ -146,7 +146,7 @@ func TestAccBackupRSOnlineArchiveBasic(t *testing.T) {
146146
),
147147
},
148148
{
149-
Config: configWithDailySchedule(clusterTerraformStr, clusterResourceName, 1, 1),
149+
Config: configWithDailySchedule(clusterTerraformStr, clusterResourceName, 1, 1, false),
150150
Check: resource.ComposeAggregateTestCheckFunc(
151151
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
152152
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
@@ -229,7 +229,7 @@ func TestAccBackupRSOnlineArchiveInvalidProcessRegion(t *testing.T) {
229229
})
230230
}
231231

232-
func configWithDailySchedule(clusterTerraformStr, clusterResourceName string, startHour, deleteExpirationDays int) string {
232+
func configWithDailySchedule(clusterTerraformStr, clusterResourceName string, startHour, deleteExpirationDays int, deleteOnTimeout bool) string {
233233
var dataExpirationRuleBlock string
234234
if deleteExpirationDays > 0 {
235235
dataExpirationRuleBlock = fmt.Sprintf(`
@@ -238,6 +238,15 @@ func configWithDailySchedule(clusterTerraformStr, clusterResourceName string, st
238238
}
239239
`, deleteExpirationDays)
240240
}
241+
deleteOnCreateTimeoutStr := ""
242+
if deleteOnTimeout {
243+
deleteOnCreateTimeoutStr = `
244+
delete_on_create_timeout = true
245+
timeouts {
246+
create = "1s"
247+
}
248+
`
249+
}
241250

242251
return fmt.Sprintf(`
243252
%[1]s
@@ -281,6 +290,8 @@ func configWithDailySchedule(clusterTerraformStr, clusterResourceName string, st
281290
}
282291
283292
sync_creation = true
293+
294+
%[5]s
284295
}
285296
286297
data "mongodbatlas_online_archive" "read_archive" {
@@ -293,7 +304,7 @@ func configWithDailySchedule(clusterTerraformStr, clusterResourceName string, st
293304
project_id = mongodbatlas_online_archive.users_archive.project_id
294305
cluster_name = mongodbatlas_online_archive.users_archive.cluster_name
295306
}
296-
`, clusterTerraformStr, startHour, dataExpirationRuleBlock, clusterResourceName)
307+
`, clusterTerraformStr, startHour, dataExpirationRuleBlock, clusterResourceName, deleteOnCreateTimeoutStr)
297308
}
298309

299310
func configWithoutSchedule(clusterTerraformStr, clusterResourceName string) string {
@@ -512,3 +523,25 @@ func testAccBackupRSOnlineArchiveConfigWithMonthlySchedule(clusterTerraformStr,
512523
}
513524
`, clusterTerraformStr, startHour, clusterResourceName)
514525
}
526+
527+
func TestAccOnlineArchive_deleteOnCreateTimeout(t *testing.T) {
528+
var (
529+
clusterInfo = acc.GetClusterInfo(t, clusterRequest())
530+
)
531+
532+
resource.ParallelTest(t, resource.TestCase{
533+
PreCheck: acc.PreCheckBasicSleep(t, &clusterInfo, "", ""),
534+
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories,
535+
CheckDestroy: acc.CheckDestroyCluster,
536+
Steps: []resource.TestStep{
537+
{
538+
Config: clusterInfo.TerraformStr,
539+
Check: acc.PopulateWithSampleDataTestCheck(clusterInfo.ProjectID, clusterInfo.Name),
540+
},
541+
{
542+
Config: configWithDailySchedule(clusterInfo.TerraformStr, clusterInfo.ResourceName, 1, 7, true),
543+
ExpectError: regexp.MustCompile("will run cleanup because delete_on_create_timeout is true"),
544+
},
545+
},
546+
})
547+
}

0 commit comments

Comments
 (0)