Skip to content

Commit 276eb28

Browse files
fix: Avoid error in organization delete operation if done just after creation (#1542)
1 parent 164b3b5 commit 276eb28

2 files changed

Lines changed: 49 additions & 12 deletions

File tree

cfn-resources/organization/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/organization/cmd/resource/resource.go

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,33 @@ func Delete(req handler.Request, prevModel *Model, currentModel *Model) (handler
221221
return handleError(response, constants.DELETE, err)
222222
}
223223

224+
currentModel.IsDeleted = util.Pointer(false)
225+
226+
responseMsg, progressEvent := runDelete(ctx, conn, currentModel)
227+
if responseMsg.Error != nil {
228+
// Retry once on transient server error, waiting 20 seconds before retrying request
229+
// This covers case of contract tests which create and delete an org within seconds, encountering an error while deleting the org
230+
if responseMsg.Response != nil && responseMsg.Response.StatusCode == http.StatusInternalServerError {
231+
_, _ = logger.Warnf("Transient server error while deleting organization, retrying in 20 seconds")
232+
time.Sleep(20 * time.Second)
233+
responseMsg, progressEvent = runDelete(ctx, conn, currentModel)
234+
}
235+
}
236+
if progressEvent != nil {
237+
return *progressEvent, nil
238+
}
239+
if responseMsg.Error != nil {
240+
return handleError(responseMsg.Response, constants.DELETE, responseMsg.Error)
241+
}
242+
243+
return handler.ProgressEvent{
244+
OperationStatus: handler.Success,
245+
Message: DeleteCompleted,
246+
ResourceModel: nil}, nil
247+
}
248+
249+
// Encapsulate the delete+wait logic so the same flow can be used on retry.
250+
func runDelete(ctx context.Context, conn *admin.APIClient, currentModel *Model) (*DeleteResponse, *handler.ProgressEvent) {
224251
deleteRequest := conn.OrganizationsApi.DeleteOrg(ctx, *currentModel.OrgId)
225252

226253
// Since the Delete API is synchronous and takes more than 1 minute most of the time,
@@ -234,31 +261,22 @@ func Delete(req handler.Request, prevModel *Model, currentModel *Model) (handler
234261
responseChan <- DeleteResponse{Error: err, Response: response}
235262
}()
236263

237-
currentModel.IsDeleted = util.Pointer(false)
238264
select {
239265
case responseMsg := <-responseChan:
240-
if responseMsg.Error != nil {
241-
return handleError(responseMsg.Response, constants.DELETE, responseMsg.Error)
242-
}
243-
266+
return &responseMsg, nil
244267
case <-time.After(30 * time.Second):
245268
// If the Delete is not completed in the above time,
246269
// we return a progress event with inProgress status and callback context
247-
return handler.ProgressEvent{
270+
return nil, &handler.ProgressEvent{
248271
OperationStatus: handler.InProgress,
249272
Message: DeleteInProgress,
250273
ResourceModel: currentModel,
251274
CallbackDelaySeconds: CallBackSeconds,
252275
CallbackContext: map[string]interface{}{
253276
constants.StateName: DeletingState,
254277
},
255-
}, nil
278+
}
256279
}
257-
258-
return handler.ProgressEvent{
259-
OperationStatus: handler.Success,
260-
Message: DeleteCompleted,
261-
ResourceModel: nil}, nil
262280
}
263281

264282
func deleteCallback(ctx context.Context, conn *admin.APIClient, currentModel *Model) (handler.ProgressEvent, error) {

0 commit comments

Comments
 (0)