Skip to content

Commit 74db56a

Browse files
INTMDB-935: HELP: mongodbatlas_online_archive schedule parameter update causing crashing in terraform apply (#1320)
1 parent 561e402 commit 74db56a

File tree

4 files changed

+290
-23
lines changed

4 files changed

+290
-23
lines changed

mongodbatlas/resource_mongodbatlas_online_archive.go

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
const (
2121
errorOnlineArchivesCreate = "error creating MongoDB Atlas Online Archive:: %s"
2222
errorOnlineArchivesDelete = "error deleting MongoDB Atlas Online Archive: %s archive_id (%s)"
23+
scheduleTypeDefault = "DEFAULT"
2324
)
2425

2526
func resourceMongoDBAtlasOnlineArchive() *schema.Resource {
@@ -106,27 +107,23 @@ func getMongoDBAtlasOnlineArchiveSchema() map[string]*schema.Schema {
106107
"type": {
107108
Type: schema.TypeString,
108109
Required: true,
109-
ValidateFunc: validation.StringInSlice([]string{"DAILY", "MONTHLY", "WEEKLY", "DEFAULT"}, false),
110+
ValidateFunc: validation.StringInSlice([]string{"DAILY", "MONTHLY", "WEEKLY"}, false),
110111
},
111112
"end_hour": {
112113
Type: schema.TypeInt,
113114
Optional: true,
114-
Computed: true,
115115
},
116116
"end_minute": {
117117
Type: schema.TypeInt,
118118
Optional: true,
119-
Computed: true,
120119
},
121120
"start_hour": {
122121
Type: schema.TypeInt,
123122
Optional: true,
124-
Computed: true,
125123
},
126124
"start_minute": {
127125
Type: schema.TypeInt,
128126
Optional: true,
129-
Computed: true,
130127
},
131128
"day_of_month": {
132129
Type: schema.TypeInt,
@@ -450,14 +447,19 @@ func fromOnlineArchiveToMap(in *matlas.OnlineArchive) map[string]interface{} {
450447
"query": in.Criteria.Query,
451448
}
452449

453-
schedule := map[string]interface{}{
454-
"type": in.Schedule.Type,
455-
"day_of_month": in.Schedule.DayOfMonth,
456-
"day_of_week": in.Schedule.DayOfWeek,
457-
"end_hour": in.Schedule.EndHour,
458-
"end_minute": in.Schedule.EndMinute,
459-
"start_hour": in.Schedule.StartHour,
460-
"start_minute": in.Schedule.StartMinute,
450+
var schedule map[string]interface{}
451+
// When schedule is not provided in CREATE/UPDATE the GET returns Schedule.Type = DEFAULT
452+
// In this case, we don't want to update the schema as there is no SCHEDULE
453+
if in.Schedule != nil && in.Schedule.Type != scheduleTypeDefault {
454+
schedule = map[string]interface{}{
455+
"type": in.Schedule.Type,
456+
"day_of_month": in.Schedule.DayOfMonth,
457+
"day_of_week": in.Schedule.DayOfWeek,
458+
"end_hour": in.Schedule.EndHour,
459+
"end_minute": in.Schedule.EndMinute,
460+
"start_hour": in.Schedule.StartHour,
461+
"start_minute": in.Schedule.StartMinute,
462+
}
461463
}
462464

463465
// note: criteria is a conditional field, not required when type is equal to CUSTOM
@@ -480,7 +482,10 @@ func fromOnlineArchiveToMap(in *matlas.OnlineArchive) map[string]interface{} {
480482
}
481483

482484
schemaVals["criteria"] = []interface{}{criteria}
483-
schemaVals["schedule"] = []interface{}{schedule}
485+
486+
if schedule != nil {
487+
schemaVals["schedule"] = []interface{}{schedule}
488+
}
484489

485490
// partitions fields
486491
if len(in.PartitionFields) == 0 {
@@ -544,10 +549,29 @@ func mapCriteria(d *schema.ResourceData) *matlas.OnlineArchiveCriteria {
544549
}
545550

546551
func mapSchedule(d *schema.ResourceData) *matlas.OnlineArchiveSchedule {
547-
scheduleTFConfigList := d.Get("schedule").([]interface{})
548-
scheduleTFConfig := scheduleTFConfigList[0].(map[string]interface{})
549-
552+
// We have to provide schedule.type="DEFAULT" when the schedule block is not provided or removed
550553
scheduleInput := &matlas.OnlineArchiveSchedule{
554+
Type: scheduleTypeDefault,
555+
}
556+
557+
scheduleTFConfigInterface := d.Get("schedule")
558+
if scheduleTFConfigInterface == nil {
559+
return scheduleInput
560+
}
561+
562+
scheduleTFConfigList, ok := scheduleTFConfigInterface.([]interface{})
563+
if !ok {
564+
return scheduleInput
565+
}
566+
567+
if len(scheduleTFConfigList) == 0 {
568+
return &matlas.OnlineArchiveSchedule{
569+
Type: scheduleTypeDefault,
570+
}
571+
}
572+
573+
scheduleTFConfig := scheduleTFConfigList[0].(map[string]interface{})
574+
scheduleInput = &matlas.OnlineArchiveSchedule{
551575
Type: scheduleTFConfig["type"].(string),
552576
}
553577

mongodbatlas/resource_mongodbatlas_online_archive_test.go

Lines changed: 247 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func TestAccBackupRSOnlineArchive(t *testing.T) {
2424
name = fmt.Sprintf("test-acc-%s", acctest.RandString(10))
2525
)
2626

27-
resource.Test(t, resource.TestCase{
27+
resource.ParallelTest(t, resource.TestCase{
2828
PreCheck: func() { testAccPreCheckBasic(t) },
2929
ProviderFactories: testAccProviderFactories,
3030
CheckDestroy: testAccCheckMongoDBAtlasClusterDestroy,
@@ -38,7 +38,103 @@ func TestAccBackupRSOnlineArchive(t *testing.T) {
3838
),
3939
},
4040
{
41-
Config: testAccBackupRSOnlineArchiveConfig(orgID, projectName, name),
41+
Config: testAccBackupRSOnlineArchiveConfigWithDailySchedule(orgID, projectName, name, 1),
42+
Check: resource.ComposeTestCheckFunc(
43+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
44+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
45+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "collection_type"),
46+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.type"),
47+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.end_hour"),
48+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.end_minute"),
49+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.start_hour"),
50+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.start_minute"),
51+
),
52+
},
53+
{
54+
Config: testAccBackupRSOnlineArchiveConfigWithDailySchedule(orgID, projectName, name, 2),
55+
Check: resource.ComposeTestCheckFunc(
56+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
57+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
58+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "collection_type"),
59+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.type"),
60+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.end_hour"),
61+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.end_minute"),
62+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.start_hour"),
63+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.start_minute"),
64+
),
65+
},
66+
{
67+
Config: testAccBackupRSOnlineArchiveConfigWithWeeklySchedule(orgID, projectName, name, 2),
68+
Check: resource.ComposeTestCheckFunc(
69+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
70+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
71+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "collection_type"),
72+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.type"),
73+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.end_hour"),
74+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.end_minute"),
75+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.start_hour"),
76+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.start_minute"),
77+
),
78+
},
79+
{
80+
Config: testAccBackupRSOnlineArchiveConfigWithMonthlySchedule(orgID, projectName, name, 2),
81+
Check: resource.ComposeTestCheckFunc(
82+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
83+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
84+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "collection_type"),
85+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.type"),
86+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.end_hour"),
87+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.end_minute"),
88+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.start_hour"),
89+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "schedule.0.start_minute"),
90+
),
91+
},
92+
{
93+
Config: testAccBackupRSOnlineArchiveConfigWithoutSchedule(orgID, projectName, name),
94+
Check: resource.ComposeTestCheckFunc(
95+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
96+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
97+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "collection_type"),
98+
resource.TestCheckNoResourceAttr(onlineArchiveResourceName, "schedule.#"),
99+
),
100+
},
101+
},
102+
})
103+
}
104+
105+
func TestAccBackupRSOnlineArchiveBasic(t *testing.T) {
106+
var (
107+
cluster matlas.Cluster
108+
resourceName = "mongodbatlas_cluster.online_archive_test"
109+
onlineArchiveResourceName = "mongodbatlas_online_archive.users_archive"
110+
orgID = os.Getenv("MONGODB_ATLAS_ORG_ID")
111+
projectName = acctest.RandomWithPrefix("test-acc")
112+
name = fmt.Sprintf("test-acc-%s", acctest.RandString(10))
113+
)
114+
115+
resource.ParallelTest(t, resource.TestCase{
116+
PreCheck: func() { testAccPreCheckBasic(t) },
117+
ProviderFactories: testAccProviderFactories,
118+
CheckDestroy: testAccCheckMongoDBAtlasClusterDestroy,
119+
Steps: []resource.TestStep{
120+
{
121+
// We need this step to pupulate the cluster with Sample Data
122+
// The online archive won't work if the cluster does not have data
123+
Config: testAccBackupRSOnlineArchiveConfigFirstStep(orgID, projectName, name),
124+
Check: resource.ComposeTestCheckFunc(
125+
populateWithSampleData(resourceName, &cluster),
126+
),
127+
},
128+
{
129+
Config: testAccBackupRSOnlineArchiveConfigWithoutSchedule(orgID, projectName, name),
130+
Check: resource.ComposeTestCheckFunc(
131+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
132+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
133+
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "collection_type"),
134+
),
135+
},
136+
{
137+
Config: testAccBackupRSOnlineArchiveConfigWithDailySchedule(orgID, projectName, name, 1),
42138
Check: resource.ComposeTestCheckFunc(
43139
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "state"),
44140
resource.TestCheckResourceAttrSet(onlineArchiveResourceName, "archive_id"),
@@ -112,7 +208,7 @@ func populateWithSampleData(resourceName string, cluster *matlas.Cluster) resour
112208
}
113209
}
114210

115-
func testAccBackupRSOnlineArchiveConfig(orgID, projectName, clusterName string) string {
211+
func testAccBackupRSOnlineArchiveConfigWithDailySchedule(orgID, projectName, clusterName string, startHour int) string {
116212
return fmt.Sprintf(`
117213
%s
118214
resource "mongodbatlas_online_archive" "users_archive" {
@@ -133,7 +229,7 @@ func testAccBackupRSOnlineArchiveConfig(orgID, projectName, clusterName string)
133229
type = "DAILY"
134230
end_hour = 1
135231
end_minute = 1
136-
start_hour = 1
232+
start_hour = %d
137233
start_minute = 1
138234
}
139235
@@ -156,6 +252,49 @@ func testAccBackupRSOnlineArchiveConfig(orgID, projectName, clusterName string)
156252
archive_id = mongodbatlas_online_archive.users_archive.archive_id
157253
}
158254
255+
data "mongodbatlas_online_archives" "all" {
256+
project_id = mongodbatlas_online_archive.users_archive.project_id
257+
cluster_name = mongodbatlas_online_archive.users_archive.cluster_name
258+
}
259+
`, testAccBackupRSOnlineArchiveConfigFirstStep(orgID, projectName, clusterName), startHour)
260+
}
261+
262+
func testAccBackupRSOnlineArchiveConfigWithoutSchedule(orgID, projectName, clusterName string) string {
263+
return fmt.Sprintf(`
264+
%s
265+
resource "mongodbatlas_online_archive" "users_archive" {
266+
project_id = mongodbatlas_cluster.online_archive_test.project_id
267+
cluster_name = mongodbatlas_cluster.online_archive_test.name
268+
coll_name = "listingsAndReviews"
269+
collection_type = "STANDARD"
270+
db_name = "sample_airbnb"
271+
272+
criteria {
273+
type = "DATE"
274+
date_field = "last_review"
275+
date_format = "ISODATE"
276+
expire_after_days = 2
277+
}
278+
279+
partition_fields {
280+
field_name = "maximum_nights"
281+
order = 0
282+
}
283+
284+
partition_fields {
285+
field_name = "name"
286+
order = 1
287+
}
288+
289+
sync_creation = true
290+
}
291+
292+
data "mongodbatlas_online_archive" "read_archive" {
293+
project_id = mongodbatlas_online_archive.users_archive.project_id
294+
cluster_name = mongodbatlas_online_archive.users_archive.cluster_name
295+
archive_id = mongodbatlas_online_archive.users_archive.archive_id
296+
}
297+
159298
data "mongodbatlas_online_archives" "all" {
160299
project_id = mongodbatlas_online_archive.users_archive.project_id
161300
cluster_name = mongodbatlas_online_archive.users_archive.cluster_name
@@ -205,3 +344,107 @@ func testAccBackupRSOnlineArchiveConfigFirstStep(orgID, projectName, clusterName
205344
206345
`, orgID, projectName, clusterName)
207346
}
347+
348+
func testAccBackupRSOnlineArchiveConfigWithWeeklySchedule(orgID, projectName, clusterName string, startHour int) string {
349+
return fmt.Sprintf(`
350+
%s
351+
resource "mongodbatlas_online_archive" "users_archive" {
352+
project_id = mongodbatlas_cluster.online_archive_test.project_id
353+
cluster_name = mongodbatlas_cluster.online_archive_test.name
354+
coll_name = "listingsAndReviews"
355+
collection_type = "STANDARD"
356+
db_name = "sample_airbnb"
357+
358+
criteria {
359+
type = "DATE"
360+
date_field = "last_review"
361+
date_format = "ISODATE"
362+
expire_after_days = 2
363+
}
364+
365+
schedule {
366+
type = "WEEKLY"
367+
day_of_week = 1
368+
end_hour = 1
369+
end_minute = 1
370+
start_hour = %d
371+
start_minute = 1
372+
}
373+
374+
partition_fields {
375+
field_name = "maximum_nights"
376+
order = 0
377+
}
378+
379+
partition_fields {
380+
field_name = "name"
381+
order = 1
382+
}
383+
384+
sync_creation = true
385+
}
386+
387+
data "mongodbatlas_online_archive" "read_archive" {
388+
project_id = mongodbatlas_online_archive.users_archive.project_id
389+
cluster_name = mongodbatlas_online_archive.users_archive.cluster_name
390+
archive_id = mongodbatlas_online_archive.users_archive.archive_id
391+
}
392+
393+
data "mongodbatlas_online_archives" "all" {
394+
project_id = mongodbatlas_online_archive.users_archive.project_id
395+
cluster_name = mongodbatlas_online_archive.users_archive.cluster_name
396+
}
397+
`, testAccBackupRSOnlineArchiveConfigFirstStep(orgID, projectName, clusterName), startHour)
398+
}
399+
400+
func testAccBackupRSOnlineArchiveConfigWithMonthlySchedule(orgID, projectName, clusterName string, startHour int) string {
401+
return fmt.Sprintf(`
402+
%s
403+
resource "mongodbatlas_online_archive" "users_archive" {
404+
project_id = mongodbatlas_cluster.online_archive_test.project_id
405+
cluster_name = mongodbatlas_cluster.online_archive_test.name
406+
coll_name = "listingsAndReviews"
407+
collection_type = "STANDARD"
408+
db_name = "sample_airbnb"
409+
410+
criteria {
411+
type = "DATE"
412+
date_field = "last_review"
413+
date_format = "ISODATE"
414+
expire_after_days = 2
415+
}
416+
417+
schedule {
418+
type = "MONTHLY"
419+
day_of_month = 1
420+
end_hour = 1
421+
end_minute = 1
422+
start_hour = %d
423+
start_minute = 1
424+
}
425+
426+
partition_fields {
427+
field_name = "maximum_nights"
428+
order = 0
429+
}
430+
431+
partition_fields {
432+
field_name = "name"
433+
order = 1
434+
}
435+
436+
sync_creation = true
437+
}
438+
439+
data "mongodbatlas_online_archive" "read_archive" {
440+
project_id = mongodbatlas_online_archive.users_archive.project_id
441+
cluster_name = mongodbatlas_online_archive.users_archive.cluster_name
442+
archive_id = mongodbatlas_online_archive.users_archive.archive_id
443+
}
444+
445+
data "mongodbatlas_online_archives" "all" {
446+
project_id = mongodbatlas_online_archive.users_archive.project_id
447+
cluster_name = mongodbatlas_online_archive.users_archive.cluster_name
448+
}
449+
`, testAccBackupRSOnlineArchiveConfigFirstStep(orgID, projectName, clusterName), startHour)
450+
}

0 commit comments

Comments
 (0)