Skip to content

Commit 31b9c3d

Browse files
authored
Fix app deletion in case of asynchronous service bindings (#547)
* Poll for app deletion in bluegreen strategy * Retry app deletion
1 parent c1cb31f commit 31b9c3d

File tree

2 files changed

+49
-46
lines changed

2 files changed

+49
-46
lines changed

cloudfoundry/managers/v3appdeployers/bluegreen_strategy_v3.go

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"io/ioutil"
77
"log"
8+
"regexp"
89
"time"
910

1011
"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
@@ -137,8 +138,7 @@ func (s BlueGreen) Deploy(appDeploy AppDeploy) (AppDeployResponse, error) {
137138
},
138139
{
139140
Forward: func(ctx Context) (Context, error) {
140-
_, _, err := s.client.DeleteApplication(appDeploy.App.GUID)
141-
return ctx, err
141+
return ctx, SafeAppDeletion(*s.client, appDeploy.App.GUID, 5)
142142
},
143143
},
144144
}
@@ -293,41 +293,7 @@ func (s BlueGreen) Restage(appDeploy AppDeploy) (AppDeployResponse, error) {
293293
},
294294
{
295295
Forward: func(ctx Context) (Context, error) {
296-
appResp := ctx["app_response"].(AppDeployResponse)
297-
298-
// Action code
299-
jobURL, _, err := s.client.DeleteApplication(appDeploy.App.GUID)
300-
if err != nil {
301-
return ctx, err
302-
}
303-
304-
err = common.PollingWithTimeout(func() (bool, error) {
305-
job, _, err := s.client.GetJob(jobURL)
306-
if err != nil {
307-
return true, err
308-
}
309-
310-
// Stop polling and return error if job failed
311-
if job.State == constantV3.JobFailed {
312-
return true, fmt.Errorf(
313-
"Venerable app deletion failed, reason: %+v",
314-
job.Errors(),
315-
)
316-
}
317-
318-
if job.State == constantV3.JobComplete {
319-
return true, nil
320-
}
321-
322-
return false, nil
323-
}, 5*time.Second, 1*time.Minute)
324-
325-
if err != nil {
326-
return ctx, err
327-
}
328-
329-
ctx["app_response"] = appResp
330-
return ctx, nil
296+
return ctx, SafeAppDeletion(*s.client, appDeploy.App.GUID, 5)
331297
},
332298
},
333299
}
@@ -470,3 +436,48 @@ func isAppStopped(clientV3 *ccv3.Client, appGUID string) (bool, error) {
470436
// All instances stopped
471437
return true, err
472438
}
439+
440+
func SafeAppDeletion(client ccv3.Client, appGuid string, remainingAttempts int) error {
441+
// start deletion job
442+
jobURL, _, err := client.DeleteApplication(appGuid)
443+
if err != nil {
444+
return err
445+
}
446+
447+
// poll completion
448+
err = common.PollingWithTimeout(func() (bool, error) {
449+
job, _, err := client.GetJob(jobURL)
450+
if err != nil {
451+
return true, err
452+
}
453+
454+
if job.State == constantV3.JobFailed {
455+
return true, fmt.Errorf(
456+
"App deletion failed, reason: %+v",
457+
job.Errors(),
458+
)
459+
}
460+
461+
if job.State == constantV3.JobComplete {
462+
return true, nil
463+
}
464+
465+
return false, nil
466+
}, 5*time.Second, 1*time.Minute)
467+
468+
// error handling
469+
if err != nil {
470+
// https://github.com/cloudfoundry/cloud_controller_ng/issues/3589 -> Delete app when bound to service fails with async service brokers -> Retry that
471+
specialError, _ := regexp.MatchString("An operation for the service binding between app .* and service instance .* is in progress.", err.Error())
472+
if specialError {
473+
if remainingAttempts > 0 {
474+
time.Sleep(5 * time.Second)
475+
return SafeAppDeletion(client, appGuid, remainingAttempts-1)
476+
}
477+
return fmt.Errorf("Retries for app deletion exhausted: %+v", err)
478+
}
479+
return err
480+
}
481+
482+
return nil
483+
}

cloudfoundry/resource_cf_app.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -746,14 +746,6 @@ func resourceAppDelete(ctx context.Context, d *schema.ResourceData, meta interfa
746746
return diag.FromErr(err)
747747
}
748748

749-
jobURL, _, err := session.ClientV3.DeleteApplication(appGUID)
750-
if err != nil && !IsErrNotFound(err) {
751-
return diag.FromErr(err)
752-
}
753-
754-
err = PollAsyncJob(PollingConfig{
755-
Session: session,
756-
JobURL: jobURL,
757-
})
749+
err = v3appdeployers.SafeAppDeletion(*session.ClientV3, appGUID, 5)
758750
return diag.FromErr(err)
759751
}

0 commit comments

Comments
 (0)