mirror of https://github.com/databricks/cli.git
Return early in bundle destroy if no deployment exists (#1581)
## Changes This PR: 1. Moves the if mutator to the bundle package, to live with all-time greats such as `bundle.Seq` and `bundle.Defer`. Also adds unit tests. 2. `bundle destroy` now returns early if `root_path` does not exist. We do this by leveraging a `bundle.If` condition. ## Tests Unit tests and manually. Here's an example of what it'll look like once the bundle is destroyed. ``` ➜ bundle-playground git:(master) ✗ cli bundle destroy No active deployment found to destroy! ``` I would have added some e2e coverage for this as well, but the `cobraTestRunner.Run()` method does not seem to return stdout/stderr logs correctly. We can probably punt looking into it.
This commit is contained in:
parent
8b468b423f
commit
5bc5c3c26a
|
@ -1,36 +0,0 @@
|
|||
package mutator
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/databricks/cli/bundle"
|
||||
"github.com/databricks/cli/libs/diag"
|
||||
)
|
||||
|
||||
type ifMutator struct {
|
||||
condition func(*bundle.Bundle) bool
|
||||
onTrueMutator bundle.Mutator
|
||||
onFalseMutator bundle.Mutator
|
||||
}
|
||||
|
||||
func If(
|
||||
condition func(*bundle.Bundle) bool,
|
||||
onTrueMutator bundle.Mutator,
|
||||
onFalseMutator bundle.Mutator,
|
||||
) bundle.Mutator {
|
||||
return &ifMutator{
|
||||
condition, onTrueMutator, onFalseMutator,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ifMutator) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
|
||||
if m.condition(b) {
|
||||
return bundle.Apply(ctx, b, m.onTrueMutator)
|
||||
} else {
|
||||
return bundle.Apply(ctx, b, m.onFalseMutator)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ifMutator) Name() string {
|
||||
return "If"
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package bundle
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/databricks/cli/libs/diag"
|
||||
)
|
||||
|
||||
type ifMutator struct {
|
||||
condition func(context.Context, *Bundle) (bool, error)
|
||||
onTrueMutator Mutator
|
||||
onFalseMutator Mutator
|
||||
}
|
||||
|
||||
func If(
|
||||
condition func(context.Context, *Bundle) (bool, error),
|
||||
onTrueMutator Mutator,
|
||||
onFalseMutator Mutator,
|
||||
) Mutator {
|
||||
return &ifMutator{
|
||||
condition, onTrueMutator, onFalseMutator,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ifMutator) Apply(ctx context.Context, b *Bundle) diag.Diagnostics {
|
||||
v, err := m.condition(ctx, b)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
if v {
|
||||
return Apply(ctx, b, m.onTrueMutator)
|
||||
} else {
|
||||
return Apply(ctx, b, m.onFalseMutator)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ifMutator) Name() string {
|
||||
return "If"
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package bundle
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIfMutatorTrue(t *testing.T) {
|
||||
m1 := &testMutator{}
|
||||
m2 := &testMutator{}
|
||||
ifMutator := If(func(context.Context, *Bundle) (bool, error) {
|
||||
return true, nil
|
||||
}, m1, m2)
|
||||
|
||||
b := &Bundle{}
|
||||
diags := Apply(context.Background(), b, ifMutator)
|
||||
assert.NoError(t, diags.Error())
|
||||
|
||||
assert.Equal(t, 1, m1.applyCalled)
|
||||
assert.Equal(t, 0, m2.applyCalled)
|
||||
}
|
||||
|
||||
func TestIfMutatorFalse(t *testing.T) {
|
||||
m1 := &testMutator{}
|
||||
m2 := &testMutator{}
|
||||
ifMutator := If(func(context.Context, *Bundle) (bool, error) {
|
||||
return false, nil
|
||||
}, m1, m2)
|
||||
|
||||
b := &Bundle{}
|
||||
diags := Apply(context.Background(), b, ifMutator)
|
||||
assert.NoError(t, diags.Error())
|
||||
|
||||
assert.Equal(t, 0, m1.applyCalled)
|
||||
assert.Equal(t, 1, m2.applyCalled)
|
||||
}
|
||||
|
||||
func TestIfMutatorError(t *testing.T) {
|
||||
m1 := &testMutator{}
|
||||
m2 := &testMutator{}
|
||||
ifMutator := If(func(context.Context, *Bundle) (bool, error) {
|
||||
return true, assert.AnError
|
||||
}, m1, m2)
|
||||
|
||||
b := &Bundle{}
|
||||
diags := Apply(context.Background(), b, ifMutator)
|
||||
assert.Error(t, diags.Error())
|
||||
|
||||
assert.Equal(t, 0, m1.applyCalled)
|
||||
assert.Equal(t, 0, m2.applyCalled)
|
||||
}
|
|
@ -1,15 +1,33 @@
|
|||
package phases
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/databricks/cli/bundle"
|
||||
"github.com/databricks/cli/bundle/deploy/files"
|
||||
"github.com/databricks/cli/bundle/deploy/lock"
|
||||
"github.com/databricks/cli/bundle/deploy/terraform"
|
||||
"github.com/databricks/cli/libs/log"
|
||||
"github.com/databricks/databricks-sdk-go/apierr"
|
||||
)
|
||||
|
||||
func assertRootPathExists(ctx context.Context, b *bundle.Bundle) (bool, error) {
|
||||
w := b.WorkspaceClient()
|
||||
_, err := w.Workspace.GetStatusByPath(ctx, b.Config.Workspace.RootPath)
|
||||
|
||||
var aerr *apierr.APIError
|
||||
if errors.As(err, &aerr) && aerr.StatusCode == http.StatusNotFound {
|
||||
log.Infof(ctx, "Root path does not exist: %s", b.Config.Workspace.RootPath)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, err
|
||||
}
|
||||
|
||||
// The destroy phase deletes artifacts and resources.
|
||||
func Destroy() bundle.Mutator {
|
||||
|
||||
destroyMutator := bundle.Seq(
|
||||
lock.Acquire(),
|
||||
bundle.Defer(
|
||||
|
@ -29,6 +47,13 @@ func Destroy() bundle.Mutator {
|
|||
|
||||
return newPhase(
|
||||
"destroy",
|
||||
[]bundle.Mutator{destroyMutator},
|
||||
[]bundle.Mutator{
|
||||
// Only run deploy mutator if root path exists.
|
||||
bundle.If(
|
||||
assertRootPathExists,
|
||||
destroyMutator,
|
||||
bundle.LogString("No active deployment found to destroy!"),
|
||||
),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package python
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -63,9 +64,10 @@ dbutils.notebook.exit(s)
|
|||
// which installs uploaded wheels using %pip and then calling corresponding
|
||||
// entry point.
|
||||
func TransformWheelTask() bundle.Mutator {
|
||||
return mutator.If(
|
||||
func(b *bundle.Bundle) bool {
|
||||
return b.Config.Experimental != nil && b.Config.Experimental.PythonWheelWrapper
|
||||
return bundle.If(
|
||||
func(_ context.Context, b *bundle.Bundle) (bool, error) {
|
||||
res := b.Config.Experimental != nil && b.Config.Experimental.PythonWheelWrapper
|
||||
return res, nil
|
||||
},
|
||||
mutator.NewTrampoline(
|
||||
"python_wheel",
|
||||
|
|
Loading…
Reference in New Issue