Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions cmd/workspace/clusters/overrides.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package clusters

import (
"errors"
"strings"

"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/databricks-sdk-go/apierr"
"github.com/databricks/databricks-sdk-go/service/compute"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -93,8 +95,26 @@ func sparkVersionsOverride(sparkVersionsCmd *cobra.Command) {
`)
}

// startIdempotentOverride matches the generated help text: starting a cluster
// that is not TERMINATED is a no-op. The Clusters API returns INVALID_STATE
// (ErrInvalidState) for that case, which made scripts fail despite the docs.
func startIdempotentOverride(startCmd *cobra.Command, _ *compute.StartCluster) {
originalRunE := startCmd.RunE
startCmd.RunE = func(cmd *cobra.Command, args []string) error {
err := originalRunE(cmd, args)
if err == nil {
return nil
}
if errors.Is(err, apierr.ErrInvalidState) {
return nil
}
return err
}
}

func init() {
listOverrides = append(listOverrides, listOverride)
listNodeTypesOverrides = append(listNodeTypesOverrides, listNodeTypesOverride)
sparkVersionsOverrides = append(sparkVersionsOverrides, sparkVersionsOverride)
startOverrides = append(startOverrides, startIdempotentOverride)
}
60 changes: 60 additions & 0 deletions cmd/workspace/clusters/overrides_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package clusters

import (
"errors"
"testing"

"github.com/databricks/databricks-sdk-go/apierr"
"github.com/databricks/databricks-sdk-go/service/compute"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestStartIdempotentOverride(t *testing.T) {
t.Run("swallows INVALID_STATE from a non terminated cluster", func(t *testing.T) {
cmd := &cobra.Command{}
cmd.RunE = func(cmd *cobra.Command, args []string) error {
return apierr.ErrInvalidState
}

startIdempotentOverride(cmd, &compute.StartCluster{})
require.NoError(t, cmd.RunE(cmd, nil))
})

t.Run("swallows APIError with INVALID_STATE code", func(t *testing.T) {
cmd := &cobra.Command{}
cmd.RunE = func(cmd *cobra.Command, args []string) error {
return &apierr.APIError{
ErrorCode: "INVALID_STATE",
Message: "Cluster abc is in unexpected state Running.",
}
}

startIdempotentOverride(cmd, &compute.StartCluster{})
require.NoError(t, cmd.RunE(cmd, nil))
})

t.Run("preserves other errors", func(t *testing.T) {
cmd := &cobra.Command{}
want := errors.New("boom")
cmd.RunE = func(cmd *cobra.Command, args []string) error {
return want
}

startIdempotentOverride(cmd, &compute.StartCluster{})
err := cmd.RunE(cmd, nil)
require.Error(t, err)
assert.ErrorIs(t, err, want)
})

t.Run("passes success through", func(t *testing.T) {
cmd := &cobra.Command{}
cmd.RunE = func(cmd *cobra.Command, args []string) error {
return nil
}

startIdempotentOverride(cmd, &compute.StartCluster{})
require.NoError(t, cmd.RunE(cmd, nil))
})
}