Prompt for account profile only for account-level command execution instead of during `databricks labs install` flow (#1128)

## Changes

There's a lot of end-user friction for projects that require
account-level commands. This is mainly related to the fact that, as of
January 2024, workspace administrators do not necessarily have access to
call account-level APIs. Ongoing discussions exist on how to implement
this on a platform level best.

A temporary workaround is creating a dummy ~/.databrickscfg profile with
the `account_id` field, though it doesn't remove the end-user friction.
Hence, we don't require an account profile during installation (anymore)
and just prompt it when the context requires it. This also means that we
always prompt for account-level commands unless users specify a
`--profile` flag.

## Tests
- `go run main.go labs install ucx`, don't see an account profile prompt
- `go run main.go labs ucx sync-workspace-info`, to see a profile prompt
and have a valid auth passed
- `go run main.go labs ucx sync-workspace-info --debug --profile
profile-name` to get a concrete profile passed
This commit is contained in:
Serge Smertin 2024-01-22 18:35:13 +01:00 committed by GitHub
parent 261f13f42c
commit deb7e67ad5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 5 deletions

View File

@ -18,6 +18,7 @@ import (
"github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/log"
"github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go"
"github.com/databricks/databricks-sdk-go/config" "github.com/databricks/databricks-sdk-go/config"
"github.com/databricks/databricks-sdk-go/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -231,6 +232,8 @@ func (e *Entrypoint) validLogin(cmd *cobra.Command) (*config.Config, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
ctx := cmd.Context()
logger.Debugf(ctx, "Resolved login: %s", config.ConfigAttributes.DebugString(cfg))
// merge ~/.databrickscfg and ~/.databricks/labs/x/config/login.json when // merge ~/.databrickscfg and ~/.databricks/labs/x/config/login.json when
// it comes to project-specific configuration // it comes to project-specific configuration
if e.NeedsCluster() && cfg.ClusterID == "" { if e.NeedsCluster() && cfg.ClusterID == "" {
@ -239,8 +242,35 @@ func (e *Entrypoint) validLogin(cmd *cobra.Command) (*config.Config, error) {
if e.NeedsWarehouse() && cfg.WarehouseID == "" { if e.NeedsWarehouse() && cfg.WarehouseID == "" {
cfg.WarehouseID = lc.WarehouseID cfg.WarehouseID = lc.WarehouseID
} }
// there's a lot of end-user friction for projects, that require account-level commands.
// this is mainly related to the fact, that, as of January 2024, workspace administrators
// do not necessarily have access to call account-level APIs. There are ongoing discussions
// on how to best implement this on a platform level.
//
// Current temporary workaround is creating dummy ~/.databrickscfg profile with `account_id`
// field, though it doesn't really remove the end-user friction, hence we don't require
// an account profile during installation (anymore) and just prompt for it, when context
// does require it. This also means that we always prompt for account-level commands, unless
// users specify a `--profile` flag.
isACC := cfg.IsAccountClient() isACC := cfg.IsAccountClient()
if e.IsAccountLevel && !isACC { if e.IsAccountLevel && cfg.Profile == "" {
if !cmdio.IsPromptSupported(ctx) {
return nil, config.ErrCannotConfigureAuth
}
replaceCfg, err := e.envAwareConfig(ctx)
if err != nil {
return nil, fmt.Errorf("replace config: %w", err)
}
err = lc.askAccountProfile(ctx, replaceCfg)
if err != nil {
return nil, fmt.Errorf("account: %w", err)
}
err = replaceCfg.EnsureResolved()
if err != nil {
return nil, fmt.Errorf("resolve: %w", err)
}
return replaceCfg, nil
} else if e.IsAccountLevel && !isACC {
return nil, databricks.ErrNotAccountClient return nil, databricks.ErrNotAccountClient
} }
if e.NeedsCluster() && !isACC && cfg.ClusterID == "" { if e.NeedsCluster() && !isACC && cfg.ClusterID == "" {

View File

@ -178,10 +178,6 @@ func (i *installer) login(ctx context.Context) (*databricks.WorkspaceClient, err
if err != nil { if err != nil {
return nil, fmt.Errorf("ask for workspace: %w", err) return nil, fmt.Errorf("ask for workspace: %w", err)
} }
err = lc.askAccountProfile(ctx, cfg)
if err != nil {
return nil, fmt.Errorf("ask for account: %w", err)
}
err = lc.save(ctx) err = lc.save(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("save: %w", err) return nil, fmt.Errorf("save: %w", err)

View File

@ -103,6 +103,7 @@ func (lc *loginConfig) askAccountProfile(ctx context.Context, cfg *config.Config
return ErrNotInTTY return ErrNotInTTY
} }
lc.AccountProfile, err = root.AskForAccountProfile(ctx) lc.AccountProfile, err = root.AskForAccountProfile(ctx)
cfg.Profile = lc.AccountProfile
return return
} }