4
4
"fmt"
5
5
"log"
6
6
"net/http"
7
+ "net/url"
7
8
"strings"
8
9
"time"
9
10
@@ -201,23 +202,19 @@ func resourcePagerDutyTeamMembershipDelete(d *schema.ResourceData, meta interfac
201
202
return err
202
203
}
203
204
204
- log .Printf ("[DEBUG] Removing user: %s from team: %s" , userID , teamID )
205
-
206
- // Extract Escalation Policies associated to the team for which the userID is
207
- // a rule target.
208
- epsAssociatedToTeamAndUser , err := extractEPsAssociatedToTeamAndUser (client , teamID , userID )
209
- if err != nil {
210
- return err
211
- }
212
-
213
- epsDissociatedFromTeam , err := dissociateEPsFromTeam (client , teamID , epsAssociatedToTeamAndUser )
214
- if err != nil {
215
- return err
216
- }
217
-
218
- // Retrying to give other resources (such as escalation policies) to delete
205
+ var isFoundErrRemovingUserFromTeam bool
219
206
retryErr := retry .Retry (2 * time .Minute , func () * retry.RetryError {
220
207
if _ , err := client .Teams .RemoveUser (teamID , userID ); err != nil {
208
+ if isErrCode (err , 400 ) && strings .Contains (err .Error (), "User cannot be removed as they belong to an escalation policy on this team" ) {
209
+ if ! isFoundErrRemovingUserFromTeam {
210
+ // Giving some time for the escalation policies to be removed during destroy operations.
211
+ time .Sleep (2 * time .Second )
212
+ isFoundErrRemovingUserFromTeam = true
213
+ return retry .RetryableError (err )
214
+ }
215
+
216
+ return retry .NonRetryableError (err )
217
+ }
221
218
if isErrCode (err , 400 ) {
222
219
return retry .RetryableError (err )
223
220
}
@@ -226,25 +223,57 @@ func resourcePagerDutyTeamMembershipDelete(d *schema.ResourceData, meta interfac
226
223
}
227
224
return nil
228
225
})
226
+ if retryErr != nil && isFoundErrRemovingUserFromTeam {
227
+ // Extract Escalation Policies associated to the team for which the userID is
228
+ // a rule target.
229
+ epsAssociatedToUser , err := extractEPsAssociatedToTeamAndUser (client , teamID , userID )
230
+ if err != nil {
231
+ return fmt .Errorf ("%v; %w" , retryErr , err )
232
+ }
233
+
234
+ if len (epsAssociatedToUser ) > 0 {
235
+ pdURLData , err := url .Parse (epsAssociatedToUser [0 ])
236
+ if err != nil {
237
+ return fmt .Errorf ("%v; %w" , retryErr , err )
238
+ }
239
+
240
+ accountSubdomain := strings .Split (pdURLData .Hostname (), "." )[0 ]
241
+ var formatEPsList = func (eps []string ) string {
242
+ var formated []string
243
+ for _ , ep := range eps {
244
+ formated = append (formated , fmt .Sprintf ("\t * %s" , ep ))
245
+ }
246
+ return strings .Join (formated , "\n " )
247
+ }
248
+
249
+ return fmt .Errorf (`User %[1]q can't be removed from Team %[2]q as they belong to an Escalation Policy on this team.
250
+ Please take only one of the following remediation measures in order to unblock the Team Membership removal:
251
+ 1. Remove the user from the following Escalation Policies:
252
+ %[4]s
253
+ 2. Remove the Escalation Policies from the Team https://%[3]s.pagerduty.com/teams/%[2]s
254
+
255
+ After completing one of the above given remediation options come back to continue with the destruction of Team Membership.` ,
256
+ userID ,
257
+ teamID ,
258
+ accountSubdomain ,
259
+ formatEPsList (epsAssociatedToUser ),
260
+ )
261
+ }
262
+ }
229
263
if retryErr != nil {
230
264
time .Sleep (2 * time .Second )
231
265
return retryErr
232
266
}
233
267
234
268
d .SetId ("" )
235
269
236
- err = associateEPsBackToTeam (client , teamID , epsDissociatedFromTeam )
237
- if err != nil {
238
- return err
239
- }
240
-
241
270
return nil
242
271
}
243
272
244
273
func buildEPsIdsList (l []* pagerduty.EscalationPolicy ) []string {
245
274
eps := []string {}
246
275
for _ , o := range l {
247
- eps = append (eps , o .ID )
276
+ eps = append (eps , o .HTMLURL )
248
277
}
249
278
return unique (eps )
250
279
}
@@ -288,59 +317,6 @@ func extractEPsAssociatedToTeamAndUser(c *pagerduty.Client, teamID, userID strin
288
317
return epsAssociatedToTeamAndUser , nil
289
318
}
290
319
291
- func dissociateEPsFromTeam (c * pagerduty.Client , teamID string , eps []string ) ([]string , error ) {
292
- epsDissociatedFromTeam := []string {}
293
- for _ , ep := range eps {
294
- retryErr := retry .Retry (2 * time .Minute , func () * retry.RetryError {
295
- _ , err := c .Teams .RemoveEscalationPolicy (teamID , ep )
296
- if err != nil && ! isErrCode (err , 404 ) {
297
- time .Sleep (2 * time .Second )
298
- return retry .RetryableError (err )
299
- }
300
- if err != nil && isErrCode (err , 404 ) {
301
- return retry .NonRetryableError (err )
302
- }
303
- return nil
304
- })
305
- if retryErr != nil {
306
- if ! isErrCode (retryErr , 404 ) {
307
- return nil , fmt .Errorf ("%w; Error while trying to dissociate Team %q from Escalation Policy %q" , retryErr , teamID , ep )
308
- } else {
309
- // Skip Escaltion Policies not found. This happens when a destroy
310
- // operation is requested and Escalation Policy is destroyed first.
311
- continue
312
- }
313
- }
314
- epsDissociatedFromTeam = append (epsDissociatedFromTeam , ep )
315
- log .Printf ("[DEBUG] EscalationPolicy %s removed from team %s" , ep , teamID )
316
- }
317
- return epsDissociatedFromTeam , nil
318
- }
319
-
320
- func associateEPsBackToTeam (c * pagerduty.Client , teamID string , eps []string ) error {
321
- for _ , ep := range eps {
322
- retryErr := retry .Retry (2 * time .Minute , func () * retry.RetryError {
323
- _ , err := c .Teams .AddEscalationPolicy (teamID , ep )
324
- if err != nil && ! isErrCode (err , 404 ) {
325
- time .Sleep (2 * time .Second )
326
- return retry .RetryableError (err )
327
- }
328
- return nil
329
- })
330
- if retryErr != nil {
331
- if ! isErrCode (retryErr , 404 ) {
332
- return fmt .Errorf ("%w; Error while trying to associate back team %q to Escalation Policy %q. Resource succesfully deleted, but some team association couldn't be completed, so you need to run \" terraform plan -refresh-only\" and again \" terraform apply/destroy\" in order to remediate the drift" , retryErr , teamID , ep )
333
- } else {
334
- // Skip Escaltion Policies not found. This happens when a destroy
335
- // operation is requested and Escalation Policy is destroyed first.
336
- continue
337
- }
338
- }
339
- log .Printf ("[DEBUG] EscalationPolicy %s added to team %s" , ep , teamID )
340
- }
341
- return nil
342
- }
343
-
344
320
func isTeamMember (user * pagerduty.User , teamID string ) bool {
345
321
var found bool
346
322
0 commit comments