Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Never load authentication configuration from bundle for sync command #889

Merged
merged 4 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
39 changes: 11 additions & 28 deletions cmd/root/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ func MustAccountClient(cmd *cobra.Command, args []string) error {
}
}

noPrompt, ok := cmd.Context().Value(noPromptKey).(bool)
allowPrompt := !hasProfileFlag && (!ok || !noPrompt)
allowPrompt := !hasProfileFlag && !shouldSkipPrompt(cmd.Context())
a, err := accountClientOrPrompt(cmd.Context(), cfg, allowPrompt)
if err != nil {
return err
Expand All @@ -103,21 +102,6 @@ func MustAccountClient(cmd *cobra.Command, args []string) error {
return nil
}

type noPrompt int

var noPromptKey noPrompt

// NoPrompt allows to skip prompt for profile configuration in MustWorkspaceClient.
//
// When calling MustWorkspaceClient we want to be able to customise if to show prompt or not.
// Since we can't change function interface, in the code we only have an access to `cmd“ object.
// Command struct does not have any state flag which indicates that it's being called in completion mode and
// thus the Context object seems to be the only viable option for us to configure prompt behaviour based on
// the context it's executed from.
func NoPrompt(ctx context.Context) context.Context {
return context.WithValue(ctx, noPromptKey, true)
}

// Helper function to create a workspace client or prompt once if the given configuration is not valid.
func workspaceClientOrPrompt(ctx context.Context, cfg *config.Config, allowPrompt bool) (*databricks.WorkspaceClient, error) {
w, err := databricks.NewWorkspaceClient((*databricks.Config)(cfg))
Expand Down Expand Up @@ -162,19 +146,18 @@ func MustWorkspaceClient(cmd *cobra.Command, args []string) error {
cfg.Profile = profile
}

// try configuring a bundle
err := TryConfigureBundle(cmd, args)
if err != nil {
return err
}

// and load the config from there
currentBundle := bundle.GetOrNil(cmd.Context())
if currentBundle != nil {
cfg = currentBundle.WorkspaceClient().Config
// Try to load a bundle configuration if we're allowed to by the caller (see `./auth_options.go`).
if !shouldSkipLoadBundle(cmd.Context()) {
err := TryConfigureBundle(cmd, args)
if err != nil {
return err
}
if b := bundle.GetOrNil(cmd.Context()); b != nil {
cfg = b.WorkspaceClient().Config
}
}

allowPrompt := !hasProfileFlag
allowPrompt := !hasProfileFlag && !shouldSkipPrompt(cmd.Context())
w, err := workspaceClientOrPrompt(cmd.Context(), cfg, allowPrompt)
if err != nil {
return err
Expand Down
45 changes: 45 additions & 0 deletions cmd/root/auth_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package root

import (
"context"
)

type skipPrompt int

var skipPromptKey skipPrompt

// SkipPrompt allows to skip prompt for profile configuration in MustWorkspaceClient.
//
// When calling MustWorkspaceClient we want to be able to customise if to show prompt or not.
// Since we can't change function interface, in the code we only have an access to `cmd` object.
// Command struct does not have any state flag which indicates that it's being called in completion mode and
// thus the Context object seems to be the only viable option for us to configure prompt behaviour based on
// the context it's executed from.
func SkipPrompt(ctx context.Context) context.Context {
return context.WithValue(ctx, skipPromptKey, true)
}

// shouldSkipPrompt returns whether or not [SkipPrompt] has been set on the specified context.
func shouldSkipPrompt(ctx context.Context) bool {
skipPrompt, ok := ctx.Value(skipPromptKey).(bool)
return ok && skipPrompt
}

type skipLoadBundle int

var skipLoadBundleKey skipLoadBundle

// SkipLoadBundle instructs [MustWorkspaceClient] to never try and load a bundle for configuration options.
//
// This is used for the sync command, where we need to ensure that a bundle configuration never taints
// the authentication setup as prepared in the environment (by our VS Code extension).
// Once the VS Code extension fully builds on bundles, we can remove this check again.
func SkipLoadBundle(ctx context.Context) context.Context {
return context.WithValue(ctx, skipLoadBundleKey, true)
}

// shouldSkipLoadBundle returns whether or not [SkipLoadBundle] has been set on the specified context.
func shouldSkipLoadBundle(ctx context.Context) bool {
skipLoadBundle, ok := ctx.Value(skipLoadBundleKey).(bool)
return ok && skipLoadBundle
}
24 changes: 24 additions & 0 deletions cmd/root/auth_options_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package root

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
)

func TestSkipPrompt(t *testing.T) {
ctx := context.Background()
assert.False(t, shouldSkipPrompt(ctx))

ctx = SkipPrompt(ctx)
assert.True(t, shouldSkipPrompt(ctx))
}

func TestSkipLoadBundle(t *testing.T) {
ctx := context.Background()
assert.False(t, shouldSkipLoadBundle(ctx))

ctx = SkipLoadBundle(ctx)
assert.True(t, shouldSkipLoadBundle(ctx))
}
13 changes: 9 additions & 4 deletions cmd/sync/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,13 @@ func New() *cobra.Command {
cmd.Flags().BoolVar(&f.watch, "watch", false, "watch local file system for changes")
cmd.Flags().Var(&f.output, "output", "type of output format")

cmd.PreRunE = root.MustWorkspaceClient
// Wrapper for [root.MustWorkspaceClient] that disables loading authentication configuration from a bundle.
mustWorkspaceClient := func(cmd *cobra.Command, args []string) error {
cmd.SetContext(root.SkipLoadBundle(cmd.Context()))
return root.MustWorkspaceClient(cmd, args)
}

cmd.PreRunE = mustWorkspaceClient
cmd.RunE = func(cmd *cobra.Command, args []string) error {
var opts *sync.SyncOptions
var err error
Expand Down Expand Up @@ -149,10 +155,9 @@ func New() *cobra.Command {
}

cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
ctx := cmd.Context()
cmd.SetContext(root.NoPrompt(ctx))
cmd.SetContext(root.SkipPrompt(cmd.Context()))

err := root.MustWorkspaceClient(cmd, args)
err := mustWorkspaceClient(cmd, args)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
Expand Down