Skip to content

Commit d79a4c2

Browse files
Fix deployment failing when app is in DELETING state (#4102)
Fixes: #4006 ## Changes Added a wait for apps in `DELETING` state to be fully deleted before deployment proceeds. ## Why Deployment fails when an app is in `DELETING` state because the app still exists but is being removed. This adds a pre-deployment check that polls and waits (up to 5 minutes) for apps to finish deleting.
1 parent c54498e commit d79a4c2

File tree

1 file changed

+34
-1
lines changed
  • bundle/direct/dresources

1 file changed

+34
-1
lines changed

bundle/direct/dresources/app.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package dresources
33
import (
44
"context"
55
"fmt"
6+
"time"
67

78
"github.com/databricks/cli/bundle/config/resources"
89
"github.com/databricks/cli/bundle/deployplan"
910
"github.com/databricks/cli/libs/log"
1011
"github.com/databricks/databricks-sdk-go"
12+
"github.com/databricks/databricks-sdk-go/apierr"
1113
"github.com/databricks/databricks-sdk-go/retries"
1214
"github.com/databricks/databricks-sdk-go/service/apps"
1315
)
@@ -61,7 +63,10 @@ func (r *ResourceApp) DoUpdate(ctx context.Context, id string, config *apps.App,
6163

6264
func (r *ResourceApp) DoDelete(ctx context.Context, id string) error {
6365
_, err := r.client.Apps.DeleteByName(ctx, id)
64-
return err
66+
if err != nil {
67+
return err
68+
}
69+
return r.waitForDeletion(ctx, id)
6570
}
6671

6772
func (*ResourceApp) FieldTriggers(_ bool) map[string]deployplan.ActionType {
@@ -74,6 +79,34 @@ func (r *ResourceApp) WaitAfterCreate(ctx context.Context, config *apps.App) (*a
7479
return r.waitForApp(ctx, r.client, config.Name)
7580
}
7681

82+
func (r *ResourceApp) waitForDeletion(ctx context.Context, name string) error {
83+
retrier := retries.New[struct{}](retries.WithTimeout(10*time.Minute), retries.WithRetryFunc(shouldRetry))
84+
_, err := retrier.Run(ctx, func(ctx context.Context) (*struct{}, error) {
85+
app, err := r.client.Apps.GetByName(ctx, name)
86+
if err != nil {
87+
if apierr.IsMissing(err) {
88+
return nil, nil
89+
}
90+
return nil, retries.Halt(err)
91+
}
92+
93+
if app.ComputeStatus == nil {
94+
return nil, retries.Continues("waiting for compute status")
95+
}
96+
97+
switch app.ComputeStatus.State {
98+
case apps.ComputeStateDeleting:
99+
return nil, retries.Continues("app is deleting")
100+
case apps.ComputeStateActive, apps.ComputeStateStopped, apps.ComputeStateError:
101+
err := fmt.Errorf("app %s was not deleted, current state: %s", name, app.ComputeStatus.State)
102+
return nil, retries.Halt(err)
103+
default:
104+
return nil, retries.Continues(fmt.Sprintf("app is in %s state", app.ComputeStatus.State))
105+
}
106+
})
107+
return err
108+
}
109+
77110
// waitForApp waits for the app to reach the target state. The target state is either ACTIVE or STOPPED.
78111
// Apps with no_compute set to true will reach the STOPPED state, otherwise they will reach the ACTIVE state.
79112
// We can't use the default waiter from SDK because it only waits on ACTIVE state but we need also STOPPED state.

0 commit comments

Comments
 (0)