2022-09-05 18:25:54 +00:00
|
|
|
package configure
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2023-06-15 12:50:19 +00:00
|
|
|
"github.com/databricks/cli/libs/cmdio"
|
|
|
|
"github.com/databricks/cli/libs/databrickscfg"
|
2023-11-23 19:56:48 +00:00
|
|
|
"github.com/databricks/cli/libs/databrickscfg/cfgpickers"
|
|
|
|
"github.com/databricks/databricks-sdk-go"
|
2023-06-15 12:50:19 +00:00
|
|
|
"github.com/databricks/databricks-sdk-go/config"
|
2022-09-05 18:25:54 +00:00
|
|
|
"github.com/spf13/cobra"
|
|
|
|
)
|
|
|
|
|
2023-11-23 19:56:48 +00:00
|
|
|
func configureInteractive(cmd *cobra.Command, flags *configureFlags, cfg *config.Config) error {
|
|
|
|
ctx := cmd.Context()
|
2022-09-05 18:25:54 +00:00
|
|
|
|
2023-06-15 12:50:19 +00:00
|
|
|
// Ask user to specify the host if not already set.
|
|
|
|
if cfg.Host == "" {
|
|
|
|
prompt := cmdio.Prompt(ctx)
|
2023-11-23 19:56:48 +00:00
|
|
|
prompt.Label = "Databricks host"
|
2023-06-15 12:50:19 +00:00
|
|
|
prompt.Default = "https://"
|
|
|
|
prompt.AllowEdit = true
|
|
|
|
prompt.Validate = validateHost
|
|
|
|
out, err := prompt.Run()
|
2022-09-06 14:37:58 +00:00
|
|
|
if err != nil {
|
2023-06-15 12:50:19 +00:00
|
|
|
return err
|
2022-09-06 14:37:58 +00:00
|
|
|
}
|
2023-06-15 12:50:19 +00:00
|
|
|
cfg.Host = out
|
|
|
|
}
|
2022-09-06 14:37:58 +00:00
|
|
|
|
2023-06-15 12:50:19 +00:00
|
|
|
// Ask user to specify the token is not already set.
|
|
|
|
if cfg.Token == "" {
|
|
|
|
prompt := cmdio.Prompt(ctx)
|
2023-11-23 19:56:48 +00:00
|
|
|
prompt.Label = "Personal access token"
|
2023-06-15 12:50:19 +00:00
|
|
|
prompt.Mask = '*'
|
|
|
|
out, err := prompt.Run()
|
2022-09-05 18:25:54 +00:00
|
|
|
if err != nil {
|
2023-06-15 12:50:19 +00:00
|
|
|
return err
|
2022-09-05 18:25:54 +00:00
|
|
|
}
|
2023-06-15 12:50:19 +00:00
|
|
|
cfg.Token = out
|
|
|
|
}
|
2022-09-05 18:25:54 +00:00
|
|
|
|
2023-11-23 19:56:48 +00:00
|
|
|
// Ask user to specify a cluster if not already set.
|
|
|
|
if flags.ConfigureCluster && cfg.ClusterID == "" {
|
2023-11-30 09:51:52 +00:00
|
|
|
// Create workspace client with configuration without the profile name set.
|
|
|
|
w, err := databricks.NewWorkspaceClient(&databricks.Config{
|
|
|
|
Host: cfg.Host,
|
|
|
|
Token: cfg.Token,
|
|
|
|
})
|
2023-11-23 19:56:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-11-30 09:59:11 +00:00
|
|
|
clusterID, err := cfgpickers.AskForCluster(cmd.Context(), w, cfgpickers.WithoutSystemClusters())
|
2023-11-23 19:56:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
cfg.ClusterID = clusterID
|
|
|
|
}
|
|
|
|
|
2023-06-15 12:50:19 +00:00
|
|
|
return nil
|
|
|
|
}
|
2022-09-05 18:25:54 +00:00
|
|
|
|
2023-11-23 19:56:48 +00:00
|
|
|
func configureNonInteractive(cmd *cobra.Command, flags *configureFlags, cfg *config.Config) error {
|
2023-06-15 12:50:19 +00:00
|
|
|
if cfg.Host == "" {
|
|
|
|
return fmt.Errorf("host must be set in non-interactive mode")
|
|
|
|
}
|
|
|
|
|
2023-11-23 19:56:48 +00:00
|
|
|
// Check presence of cluster ID before reading token to fail fast.
|
|
|
|
if flags.ConfigureCluster && cfg.ClusterID == "" {
|
|
|
|
return fmt.Errorf("cluster ID must be set in non-interactive mode")
|
|
|
|
}
|
|
|
|
|
2023-06-15 12:50:19 +00:00
|
|
|
// Read token from stdin if not already set.
|
|
|
|
if cfg.Token == "" {
|
|
|
|
_, err := fmt.Fscanf(cmd.InOrStdin(), "%s\n", &cfg.Token)
|
2022-09-05 18:25:54 +00:00
|
|
|
if err != nil {
|
2023-06-15 12:50:19 +00:00
|
|
|
return err
|
2022-09-05 18:25:54 +00:00
|
|
|
}
|
2023-06-15 12:50:19 +00:00
|
|
|
}
|
2022-09-05 18:25:54 +00:00
|
|
|
|
2023-06-15 12:50:19 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-07-27 10:03:08 +00:00
|
|
|
func newConfigureCommand() *cobra.Command {
|
|
|
|
cmd := &cobra.Command{
|
|
|
|
Use: "configure",
|
|
|
|
Short: "Configure authentication",
|
|
|
|
Long: `Configure authentication.
|
2023-06-15 12:50:19 +00:00
|
|
|
|
2023-11-23 19:56:48 +00:00
|
|
|
This command adds a profile to your ~/.databrickscfg file.
|
|
|
|
You can write to a different file by setting the DATABRICKS_CONFIG_FILE environment variable.
|
2023-06-15 12:50:19 +00:00
|
|
|
|
2023-11-23 19:56:48 +00:00
|
|
|
If this command is invoked in non-interactive mode, it will read the token from stdin.
|
|
|
|
The host must be specified with the --host flag or the DATABRICKS_HOST environment variable.
|
2023-07-27 10:03:08 +00:00
|
|
|
`,
|
|
|
|
}
|
|
|
|
|
2023-11-23 19:56:48 +00:00
|
|
|
var flags configureFlags
|
|
|
|
flags.Register(cmd)
|
2023-07-27 10:03:08 +00:00
|
|
|
|
|
|
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
2023-06-15 12:50:19 +00:00
|
|
|
var cfg config.Config
|
|
|
|
|
|
|
|
// Load environment variables, possibly the DEFAULT profile.
|
|
|
|
err := config.ConfigAttributes.Configure(&cfg)
|
2022-09-05 18:25:54 +00:00
|
|
|
if err != nil {
|
2023-06-15 12:50:19 +00:00
|
|
|
return fmt.Errorf("unable to instantiate configuration from environment variables: %w", err)
|
2022-09-05 18:25:54 +00:00
|
|
|
}
|
2022-09-06 14:37:58 +00:00
|
|
|
|
2023-11-23 19:56:48 +00:00
|
|
|
// Populate configuration from flags (if set).
|
|
|
|
if flags.Host != "" {
|
|
|
|
cfg.Host = flags.Host
|
|
|
|
}
|
|
|
|
if flags.Profile != "" {
|
|
|
|
cfg.Profile = flags.Profile
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that the host is valid (if set).
|
|
|
|
if cfg.Host != "" {
|
|
|
|
err = validateHost(cfg.Host)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-15 12:50:19 +00:00
|
|
|
ctx := cmd.Context()
|
2023-11-23 19:56:48 +00:00
|
|
|
if cmdio.IsInTTY(ctx) && cmdio.IsOutTTY(ctx) {
|
|
|
|
err = configureInteractive(cmd, &flags, &cfg)
|
2023-06-15 12:50:19 +00:00
|
|
|
} else {
|
2023-11-23 19:56:48 +00:00
|
|
|
err = configureNonInteractive(cmd, &flags, &cfg)
|
2022-09-05 18:25:54 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
2023-06-15 12:50:19 +00:00
|
|
|
return err
|
2022-09-05 18:25:54 +00:00
|
|
|
}
|
|
|
|
|
2023-06-15 12:50:19 +00:00
|
|
|
// Clear the Databricks CLI path in token mode.
|
|
|
|
// This is relevant for OAuth only.
|
|
|
|
cfg.DatabricksCliPath = ""
|
|
|
|
|
|
|
|
// Save profile to config file.
|
2023-11-10 14:03:57 +00:00
|
|
|
return databrickscfg.SaveToProfile(ctx, &config.Config{
|
2024-06-24 10:56:49 +00:00
|
|
|
Profile: cfg.Profile,
|
|
|
|
Host: cfg.Host,
|
|
|
|
Token: cfg.Token,
|
|
|
|
ClusterID: cfg.ClusterID,
|
|
|
|
ConfigFile: cfg.ConfigFile,
|
2023-11-10 14:03:57 +00:00
|
|
|
})
|
2023-07-27 10:03:08 +00:00
|
|
|
}
|
2022-09-05 18:25:54 +00:00
|
|
|
|
2023-07-27 10:03:08 +00:00
|
|
|
return cmd
|
|
|
|
}
|
2023-06-15 12:50:19 +00:00
|
|
|
|
2023-07-27 10:03:08 +00:00
|
|
|
func New() *cobra.Command {
|
|
|
|
return newConfigureCommand()
|
2022-09-05 18:25:54 +00:00
|
|
|
}
|