Skip to content

Commit 1d1bc1f

Browse files
sivaram-mongodbsivaram-mongodbParthasarathyV
authored
feat: Update Maintenance-Window Resource (#1541)
Co-authored-by: sivaram-mongodb <sivaram@mongodb.com> Co-authored-by: ParthasarathyV <114770988+ParthasarathyV@users.noreply.github.com>
1 parent 5076d31 commit 1d1bc1f

11 files changed

Lines changed: 421 additions & 33 deletions

File tree

cfn-resources/maintenance-window/cmd/resource/config.go

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cfn-resources/maintenance-window/cmd/resource/model.go

Lines changed: 17 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cfn-resources/maintenance-window/cmd/resource/resource.go

Lines changed: 91 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727
"github.com/mongodb/mongodbatlas-cloudformation-resources/util/logger"
2828
progress_events "github.com/mongodb/mongodbatlas-cloudformation-resources/util/progressevent"
2929
"github.com/mongodb/mongodbatlas-cloudformation-resources/util/validator"
30-
admin20231115002 "go.mongodb.org/atlas-sdk/v20231115002/admin"
30+
"go.mongodb.org/atlas-sdk/v20250312012/admin"
3131
)
3232

3333
var RequiredFields = []string{constants.ProjectID}
@@ -56,15 +56,29 @@ func Create(req handler.Request, prevModel *Model, currentModel *Model) (handler
5656
return progress_events.GetFailedEventByCode("resource already exists", string(types.HandlerErrorCodeAlreadyExists)), nil
5757
}
5858

59+
// Handle Defer if requested
60+
if currentModel.Defer != nil && *currentModel.Defer {
61+
if pe := deferMaintenanceWindow(client, *currentModel.ProjectId); pe != nil {
62+
return *pe, nil
63+
}
64+
}
65+
5966
atlasModel := currentModel.toAtlasModel()
6067
startASP := false
6168
atlasModel.StartASAP = &startASP
6269

63-
_, resp, err := client.Atlas20231115002.MaintenanceWindowsApi.UpdateMaintenanceWindow(context.Background(), *currentModel.ProjectId, &atlasModel).Execute()
70+
resp, err := client.AtlasSDK.MaintenanceWindowsApi.UpdateMaintenanceWindow(context.Background(), *currentModel.ProjectId, &atlasModel).Execute()
6471
if err != nil {
6572
return progress_events.GetFailedEventByResponse(err.Error(), resp), nil
6673
}
6774

75+
// Handle AutoDefer if requested
76+
if currentModel.AutoDefer != nil && *currentModel.AutoDefer {
77+
if pe := toggleAutoDefer(client, *currentModel.ProjectId); pe != nil {
78+
return *pe, nil
79+
}
80+
}
81+
6882
return handler.ProgressEvent{
6983
OperationStatus: handler.Success,
7084
ResourceModel: *currentModel,
@@ -92,7 +106,17 @@ func Read(req handler.Request, prevModel *Model, currentModel *Model) (handler.P
92106

93107
currentModel.AutoDeferOnceEnabled = maintenanceWindow.AutoDeferOnceEnabled
94108
currentModel.DayOfWeek = &maintenanceWindow.DayOfWeek
95-
currentModel.HourOfDay = &maintenanceWindow.HourOfDay
109+
currentModel.HourOfDay = maintenanceWindow.HourOfDay
110+
currentModel.StartASAP = maintenanceWindow.StartASAP
111+
currentModel.NumberOfDeferrals = maintenanceWindow.NumberOfDeferrals
112+
currentModel.TimeZoneId = maintenanceWindow.TimeZoneId
113+
114+
if maintenanceWindow.ProtectedHours != nil {
115+
currentModel.ProtectedHours = &ProtectedHours{
116+
StartHourOfDay: maintenanceWindow.ProtectedHours.StartHourOfDay,
117+
EndHourOfDay: maintenanceWindow.ProtectedHours.EndHourOfDay,
118+
}
119+
}
96120

97121
return handler.ProgressEvent{
98122
OperationStatus: handler.Success,
@@ -120,15 +144,35 @@ func Update(req handler.Request, prevModel *Model, currentModel *Model) (handler
120144
return *handlerError, nil
121145
}
122146

147+
// Handle Defer if changed
148+
if currentModel.Defer != nil && *currentModel.Defer {
149+
if prevModel == nil || prevModel.Defer == nil || !*prevModel.Defer {
150+
if pe := deferMaintenanceWindow(client, *currentModel.ProjectId); pe != nil {
151+
return *pe, nil
152+
}
153+
}
154+
}
155+
123156
atlasModel := currentModel.toAtlasModel()
124157
startASP := false
125158
atlasModel.StartASAP = &startASP
126159

127-
_, resp, err := client.Atlas20231115002.MaintenanceWindowsApi.UpdateMaintenanceWindow(context.Background(), *currentModel.ProjectId, &atlasModel).Execute()
160+
resp, err := client.AtlasSDK.MaintenanceWindowsApi.UpdateMaintenanceWindow(context.Background(), *currentModel.ProjectId, &atlasModel).Execute()
128161
if err != nil {
129162
return progress_events.GetFailedEventByResponse(err.Error(), resp), nil
130163
}
131164

165+
// Handle AutoDefer if changed
166+
if prevModel != nil {
167+
prevAutoDefer := prevModel.AutoDefer != nil && *prevModel.AutoDefer
168+
currAutoDefer := currentModel.AutoDefer != nil && *currentModel.AutoDefer
169+
if prevAutoDefer != currAutoDefer {
170+
if pe := toggleAutoDefer(client, *currentModel.ProjectId); pe != nil {
171+
return *pe, nil
172+
}
173+
}
174+
}
175+
132176
return handler.ProgressEvent{
133177
OperationStatus: handler.Success,
134178
ResourceModel: currentModel,
@@ -154,7 +198,7 @@ func Delete(req handler.Request, prevModel *Model, currentModel *Model) (handler
154198
return *handlerError, nil
155199
}
156200

157-
resp, err := client.Atlas20231115002.MaintenanceWindowsApi.ResetMaintenanceWindow(context.Background(), *currentModel.ProjectId).Execute()
201+
resp, err := client.AtlasSDK.MaintenanceWindowsApi.ResetMaintenanceWindow(context.Background(), *currentModel.ProjectId).Execute()
158202
if err != nil {
159203
return progress_events.GetFailedEventByResponse(err.Error(), resp), nil
160204
}
@@ -169,17 +213,28 @@ func List(req handler.Request, prevModel *Model, currentModel *Model) (handler.P
169213
return handler.ProgressEvent{}, errors.New("not implemented: List")
170214
}
171215

172-
func (m Model) toAtlasModel() admin20231115002.GroupMaintenanceWindow {
173-
return admin20231115002.GroupMaintenanceWindow{
216+
func (m Model) toAtlasModel() admin.GroupMaintenanceWindow {
217+
return admin.GroupMaintenanceWindow{
174218
DayOfWeek: *m.DayOfWeek,
175-
HourOfDay: *m.HourOfDay,
219+
HourOfDay: m.HourOfDay,
176220
StartASAP: m.StartASAP,
177221
AutoDeferOnceEnabled: m.AutoDeferOnceEnabled,
222+
ProtectedHours: m.toProtectedHours(),
178223
}
179224
}
180225

181-
func get(client *util.MongoDBClient, currentModel Model) (*admin20231115002.GroupMaintenanceWindow, *handler.ProgressEvent) {
182-
maintenanceWindow, resp, err := client.Atlas20231115002.MaintenanceWindowsApi.GetMaintenanceWindow(context.Background(), *currentModel.ProjectId).Execute()
226+
func (m Model) toProtectedHours() *admin.ProtectedHours {
227+
if m.ProtectedHours == nil {
228+
return nil
229+
}
230+
return &admin.ProtectedHours{
231+
StartHourOfDay: m.ProtectedHours.StartHourOfDay,
232+
EndHourOfDay: m.ProtectedHours.EndHourOfDay,
233+
}
234+
}
235+
236+
func get(client *util.MongoDBClient, currentModel Model) (*admin.GroupMaintenanceWindow, *handler.ProgressEvent) {
237+
maintenanceWindow, resp, err := client.AtlasSDK.MaintenanceWindowsApi.GetMaintenanceWindow(context.Background(), *currentModel.ProjectId).Execute()
183238
if err != nil {
184239
_, _ = logger.Warnf("Read - error: %+v", err)
185240
ev := progress_events.GetFailedEventByResponse(err.Error(), resp)
@@ -195,6 +250,30 @@ func get(client *util.MongoDBClient, currentModel Model) (*admin20231115002.Grou
195250
return maintenanceWindow, nil
196251
}
197252

198-
func isResponseEmpty(maintenanceWindow *admin20231115002.GroupMaintenanceWindow) bool {
199-
return maintenanceWindow != nil && maintenanceWindow.DayOfWeek == 0
253+
func isResponseEmpty(maintenanceWindow *admin.GroupMaintenanceWindow) bool {
254+
return maintenanceWindow != nil && maintenanceWindow.GetDayOfWeek() == 0
255+
}
256+
257+
func deferMaintenanceWindow(client *util.MongoDBClient, projectID string) *handler.ProgressEvent {
258+
_, err := client.AtlasSDK.MaintenanceWindowsApi.DeferMaintenanceWindow(context.Background(), projectID).Execute()
259+
if err != nil {
260+
return &handler.ProgressEvent{
261+
OperationStatus: handler.Failed,
262+
Message: err.Error(),
263+
HandlerErrorCode: "GeneralServiceException",
264+
}
265+
}
266+
return nil
267+
}
268+
269+
func toggleAutoDefer(client *util.MongoDBClient, projectID string) *handler.ProgressEvent {
270+
_, err := client.AtlasSDK.MaintenanceWindowsApi.ToggleMaintenanceAutoDefer(context.Background(), projectID).Execute()
271+
if err != nil {
272+
return &handler.ProgressEvent{
273+
OperationStatus: handler.Failed,
274+
Message: err.Error(),
275+
HandlerErrorCode: "GeneralServiceException",
276+
}
277+
}
278+
return nil
200279
}

cfn-resources/maintenance-window/docs/README.md

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ To declare this entity in your AWS CloudFormation template, use the following sy
1717
"<a href="#dayofweek" title="DayOfWeek">DayOfWeek</a>" : <i>Integer</i>,
1818
"<a href="#projectid" title="ProjectId">ProjectId</a>" : <i>String</i>,
1919
"<a href="#hourofday" title="HourOfDay">HourOfDay</a>" : <i>Integer</i>,
20-
"<a href="#startasap" title="StartASAP">StartASAP</a>" : <i>Boolean</i>
20+
"<a href="#defer" title="Defer">Defer</a>" : <i>Boolean</i>,
21+
"<a href="#autodefer" title="AutoDefer">AutoDefer</a>" : <i>Boolean</i>,
22+
"<a href="#protectedhours" title="ProtectedHours">ProtectedHours</a>" : <i><a href="protectedhours.md">ProtectedHours</a></i>
2123
}
2224
}
2325
</pre>
@@ -32,7 +34,9 @@ Properties:
3234
<a href="#dayofweek" title="DayOfWeek">DayOfWeek</a>: <i>Integer</i>
3335
<a href="#projectid" title="ProjectId">ProjectId</a>: <i>String</i>
3436
<a href="#hourofday" title="HourOfDay">HourOfDay</a>: <i>Integer</i>
35-
<a href="#startasap" title="StartASAP">StartASAP</a>: <i>Boolean</i>
37+
<a href="#defer" title="Defer">Defer</a>: <i>Boolean</i>
38+
<a href="#autodefer" title="AutoDefer">AutoDefer</a>: <i>Boolean</i>
39+
<a href="#protectedhours" title="ProtectedHours">ProtectedHours</a>: <i><a href="protectedhours.md">ProtectedHours</a></i>
3640
</pre>
3741

3842
## Properties
@@ -72,7 +76,7 @@ One-based integer that represents the day of the week that the maintenance windo
7276
| `7` | Saturday |
7377

7478

75-
_Required_: No
79+
_Required_: Yes
7680

7781
_Type_: Integer
7882

@@ -82,7 +86,7 @@ _Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormati
8286

8387
Unique 24-hexadecimal digit string that identifies your project.
8488

85-
_Required_: No
89+
_Required_: Yes
8690

8791
_Type_: String
8892

@@ -104,13 +108,53 @@ _Type_: Integer
104108

105109
_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)
106110

107-
#### StartASAP
111+
#### Defer
108112

109-
Flag that indicates whether MongoDB Cloud starts the maintenance window immediately upon receiving this request. To start the maintenance window immediately for your project, MongoDB Cloud must have maintenance scheduled and you must set a maintenance window. This flag resets to `false` after MongoDB Cloud completes maintenance.
113+
Flag that indicates whether to defer the maintenance window. When set to true, the next scheduled maintenance will be deferred.
110114

111115
_Required_: No
112116

113117
_Type_: Boolean
114118

115119
_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)
116120

121+
#### AutoDefer
122+
123+
Flag that indicates whether MongoDB Cloud should automatically defer maintenance windows for one week when they occur during the defined maintenance window.
124+
125+
_Required_: No
126+
127+
_Type_: Boolean
128+
129+
_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)
130+
131+
#### ProtectedHours
132+
133+
Protected hours during which MongoDB Cloud cannot start maintenance.
134+
135+
_Required_: No
136+
137+
_Type_: <a href="protectedhours.md">ProtectedHours</a>
138+
139+
_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)
140+
141+
## Return Values
142+
143+
### Fn::GetAtt
144+
145+
The `Fn::GetAtt` intrinsic function returns a value for a specified attribute of this type. The following are the available attributes and sample return values.
146+
147+
For more information about using the `Fn::GetAtt` intrinsic function, see [Fn::GetAtt](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html).
148+
149+
#### StartASAP
150+
151+
Flag that indicates whether MongoDB Cloud starts the maintenance window immediately upon receiving this request. To start the maintenance window immediately for your project, MongoDB Cloud must have maintenance scheduled and you must set a maintenance window. This flag resets to `false` after MongoDB Cloud completes maintenance.
152+
153+
#### NumberOfDeferrals
154+
155+
Number of times this project has deferred the maintenance window.
156+
157+
#### TimeZoneId
158+
159+
Time zone ID that identifies the timezone for the maintenance window.
160+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# MongoDB::Atlas::MaintenanceWindow ProtectedHours
2+
3+
Protected hours during which MongoDB Cloud cannot start maintenance.
4+
5+
## Syntax
6+
7+
To declare this entity in your AWS CloudFormation template, use the following syntax:
8+
9+
### JSON
10+
11+
<pre>
12+
{
13+
"<a href="#starthourofday" title="StartHourOfDay">StartHourOfDay</a>" : <i>Integer</i>,
14+
"<a href="#endhourofday" title="EndHourOfDay">EndHourOfDay</a>" : <i>Integer</i>
15+
}
16+
</pre>
17+
18+
### YAML
19+
20+
<pre>
21+
<a href="#starthourofday" title="StartHourOfDay">StartHourOfDay</a>: <i>Integer</i>
22+
<a href="#endhourofday" title="EndHourOfDay">EndHourOfDay</a>: <i>Integer</i>
23+
</pre>
24+
25+
## Properties
26+
27+
#### StartHourOfDay
28+
29+
Hour of the day when protected hours start (0-23).
30+
31+
_Required_: No
32+
33+
_Type_: Integer
34+
35+
_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)
36+
37+
#### EndHourOfDay
38+
39+
Hour of the day when protected hours end (0-23).
40+
41+
_Required_: No
42+
43+
_Type_: Integer
44+
45+
_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)
46+

0 commit comments

Comments
 (0)