From 677926b78b34c95f65d7d12cd8688a21d020eaaf Mon Sep 17 00:00:00 2001 From: shreyas-goenka <88374338+shreyas-goenka@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:28:01 +0100 Subject: [PATCH] Fix panic when bundle auth resolution fails (#1002) ## Changes CLI would panic if an invalid bundle auth is setup when running CLI commands. This PR removes the panic and shows the error message directly instead. ## Tests The CWD is a bundle with: ``` workspace: profile: DEFAULT ``` Before: ``` shreyas.goenka@THW32HFW6T bundle-playground % cli clusters list panic: resolve: /Users/shreyas.goenka/.databrickscfg has no DEFAULT profile configured. Config: profile=DEFAULT goroutine 1 [running]: ``` After: ``` shreyas.goenka@THW32HFW6T bundle-playground % cli clusters list Error: cannot resolve bundle auth configuration: resolve: /Users/shreyas.goenka/.databrickscfg has no DEFAULT profile configured. Config: profile=DEFAULT ``` ``` shreyas.goenka@THW32HFW6T bundle-playground % DATABRICKS_CONFIG_FILE=/dev/null cli bundle deploy Error: cannot resolve bundle auth configuration: resolve: /dev/null has no DEFAULT profile configured. Config: profile=DEFAULT, config_file=/dev/null. Env: DATABRICKS_CONFIG_FILE ``` --- bundle/bundle.go | 10 +++++++- .../mutator/initialize_workspace_client.go | 25 +++++++++++++++++++ bundle/phases/initialize.go | 1 + cmd/root/auth.go | 6 ++++- cmd/root/bundle_test.go | 4 +-- 5 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 bundle/config/mutator/initialize_workspace_client.go diff --git a/bundle/bundle.go b/bundle/bundle.go index b4f5ee10..ef22d9a8 100644 --- a/bundle/bundle.go +++ b/bundle/bundle.go @@ -121,10 +121,18 @@ func TryLoad(ctx context.Context) (*Bundle, error) { return Load(ctx, root) } +func (b *Bundle) InitializeWorkspaceClient() (*databricks.WorkspaceClient, error) { + client, err := b.Config.Workspace.Client() + if err != nil { + return nil, fmt.Errorf("cannot resolve bundle auth configuration: %w", err) + } + return client, nil +} + func (b *Bundle) WorkspaceClient() *databricks.WorkspaceClient { b.clientOnce.Do(func() { var err error - b.client, err = b.Config.Workspace.Client() + b.client, err = b.InitializeWorkspaceClient() if err != nil { panic(err) } diff --git a/bundle/config/mutator/initialize_workspace_client.go b/bundle/config/mutator/initialize_workspace_client.go new file mode 100644 index 00000000..afc38d4d --- /dev/null +++ b/bundle/config/mutator/initialize_workspace_client.go @@ -0,0 +1,25 @@ +package mutator + +import ( + "context" + + "github.com/databricks/cli/bundle" +) + +type initializeWorkspaceClient struct{} + +func InitializeWorkspaceClient() bundle.Mutator { + return &initializeWorkspaceClient{} +} + +func (m *initializeWorkspaceClient) Name() string { + return "InitializeWorkspaceClient" +} + +// Apply initializes the workspace client for the bundle. We do this here so +// downstream calls to b.WorkspaceClient() do not panic if there's an error in the +// auth configuration. +func (m *initializeWorkspaceClient) Apply(_ context.Context, b *bundle.Bundle) error { + _, err := b.InitializeWorkspaceClient() + return err +} diff --git a/bundle/phases/initialize.go b/bundle/phases/initialize.go index fb9e7b24..6d84b0e1 100644 --- a/bundle/phases/initialize.go +++ b/bundle/phases/initialize.go @@ -19,6 +19,7 @@ func Initialize() bundle.Mutator { return newPhase( "initialize", []bundle.Mutator{ + mutator.InitializeWorkspaceClient(), mutator.PopulateCurrentUser(), mutator.SetRunAs(), mutator.DefineDefaultWorkspaceRoot(), diff --git a/cmd/root/auth.go b/cmd/root/auth.go index 99e91043..33f80e1f 100644 --- a/cmd/root/auth.go +++ b/cmd/root/auth.go @@ -152,7 +152,11 @@ func MustWorkspaceClient(cmd *cobra.Command, args []string) error { return err } if b := bundle.GetOrNil(cmd.Context()); b != nil { - cfg = b.WorkspaceClient().Config + client, err := b.InitializeWorkspaceClient() + if err != nil { + return err + } + cfg = client.Config } } diff --git a/cmd/root/bundle_test.go b/cmd/root/bundle_test.go index d7bae2d1..a3dec491 100644 --- a/cmd/root/bundle_test.go +++ b/cmd/root/bundle_test.go @@ -95,7 +95,7 @@ func TestBundleConfigureWithMismatchedProfile(t *testing.T) { cmd.Flag("profile").Value.Set("PROFILE-1") b := setup(t, cmd, "https://x.com") - assert.PanicsWithError(t, "config host mismatch: profile uses host https://a.com, but CLI configured to use https://x.com", func() { + assert.PanicsWithError(t, "cannot resolve bundle auth configuration: config host mismatch: profile uses host https://a.com, but CLI configured to use https://x.com", func() { b.WorkspaceClient() }) } @@ -118,7 +118,7 @@ func TestBundleConfigureWithMismatchedProfileEnvVariable(t *testing.T) { cmd := emptyCommand(t) b := setup(t, cmd, "https://x.com") - assert.PanicsWithError(t, "config host mismatch: profile uses host https://a.com, but CLI configured to use https://x.com", func() { + assert.PanicsWithError(t, "cannot resolve bundle auth configuration: config host mismatch: profile uses host https://a.com, but CLI configured to use https://x.com", func() { b.WorkspaceClient() }) }