mirror of https://github.com/databricks/cli.git
Remove dependency on global state for remaining commands (#613)
## Changes This removes the remaining dependency on global state and unblocks work to parallelize integration tests. As is, we can already uncomment an integration test that had to be skipped because of other tests tainting global state. This is no longer an issue. Also see #595 and #606. ## Tests * Unit and integration tests pass. * Manually confirmed the help output is the same.
This commit is contained in:
parent
ed972f7ae0
commit
bee7a16cb0
|
@ -5,7 +5,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/databricks/cli/cmd/root"
|
|
||||||
"github.com/databricks/cli/libs/cmdio"
|
"github.com/databricks/cli/libs/cmdio"
|
||||||
"github.com/databricks/cli/libs/flags"
|
"github.com/databricks/cli/libs/flags"
|
||||||
"github.com/databricks/databricks-sdk-go/client"
|
"github.com/databricks/databricks-sdk-go/client"
|
||||||
|
@ -13,9 +12,22 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var apiCmd = &cobra.Command{
|
func New() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "api",
|
Use: "api",
|
||||||
Short: "Perform Databricks API call",
|
Short: "Perform Databricks API call",
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(
|
||||||
|
makeCommand(http.MethodGet),
|
||||||
|
makeCommand(http.MethodHead),
|
||||||
|
makeCommand(http.MethodPost),
|
||||||
|
makeCommand(http.MethodPut),
|
||||||
|
makeCommand(http.MethodPatch),
|
||||||
|
makeCommand(http.MethodDelete),
|
||||||
|
)
|
||||||
|
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCommand(method string) *cobra.Command {
|
func makeCommand(method string) *cobra.Command {
|
||||||
|
@ -59,15 +71,3 @@ func makeCommand(method string) *cobra.Command {
|
||||||
command.Flags().Var(&payload, "json", `either inline JSON string or @path/to/file.json with request body`)
|
command.Flags().Var(&payload, "json", `either inline JSON string or @path/to/file.json with request body`)
|
||||||
return command
|
return command
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
apiCmd.AddCommand(
|
|
||||||
makeCommand(http.MethodGet),
|
|
||||||
makeCommand(http.MethodHead),
|
|
||||||
makeCommand(http.MethodPost),
|
|
||||||
makeCommand(http.MethodPut),
|
|
||||||
makeCommand(http.MethodPatch),
|
|
||||||
makeCommand(http.MethodDelete),
|
|
||||||
)
|
|
||||||
root.RootCmd.AddCommand(apiCmd)
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,18 +3,27 @@ package auth
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/databricks/cli/cmd/root"
|
|
||||||
"github.com/databricks/cli/libs/auth"
|
"github.com/databricks/cli/libs/auth"
|
||||||
"github.com/databricks/cli/libs/cmdio"
|
"github.com/databricks/cli/libs/cmdio"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var authCmd = &cobra.Command{
|
func New() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "auth",
|
Use: "auth",
|
||||||
Short: "Authentication related commands",
|
Short: "Authentication related commands",
|
||||||
}
|
}
|
||||||
|
|
||||||
var persistentAuth auth.PersistentAuth
|
var perisistentAuth auth.PersistentAuth
|
||||||
|
cmd.PersistentFlags().StringVar(&perisistentAuth.Host, "host", perisistentAuth.Host, "Databricks Host")
|
||||||
|
cmd.PersistentFlags().StringVar(&perisistentAuth.AccountID, "account-id", perisistentAuth.AccountID, "Databricks Account ID")
|
||||||
|
|
||||||
|
cmd.AddCommand(newEnvCommand())
|
||||||
|
cmd.AddCommand(newLoginCommand(&perisistentAuth))
|
||||||
|
cmd.AddCommand(newProfilesCommand())
|
||||||
|
cmd.AddCommand(newTokenCommand(&perisistentAuth))
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func promptForHost(ctx context.Context) (string, error) {
|
func promptForHost(ctx context.Context) (string, error) {
|
||||||
prompt := cmdio.Prompt(ctx)
|
prompt := cmdio.Prompt(ctx)
|
||||||
|
@ -41,9 +50,3 @@ func promptForAccountID(ctx context.Context) (string, error) {
|
||||||
}
|
}
|
||||||
return accountId, nil
|
return accountId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
root.RootCmd.AddCommand(authCmd)
|
|
||||||
authCmd.PersistentFlags().StringVar(&persistentAuth.Host, "host", persistentAuth.Host, "Databricks Host")
|
|
||||||
authCmd.PersistentFlags().StringVar(&persistentAuth.AccountID, "account-id", persistentAuth.AccountID, "Databricks Account ID")
|
|
||||||
}
|
|
||||||
|
|
|
@ -89,10 +89,18 @@ func loadFromDatabricksCfg(cfg *config.Config) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var envCmd = &cobra.Command{
|
func newEnvCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "env",
|
Use: "env",
|
||||||
Short: "Get env",
|
Short: "Get env",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
var host string
|
||||||
|
var profile string
|
||||||
|
cmd.Flags().StringVar(&host, "host", host, "Hostname to get auth env for")
|
||||||
|
cmd.Flags().StringVar(&profile, "profile", profile, "Profile to get auth env for")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
cfg := &config.Config{
|
cfg := &config.Config{
|
||||||
Host: host,
|
Host: host,
|
||||||
Profile: profile,
|
Profile: profile,
|
||||||
|
@ -130,14 +138,7 @@ var envCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
cmd.OutOrStdout().Write(raw)
|
cmd.OutOrStdout().Write(raw)
|
||||||
return nil
|
return nil
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var host string
|
return cmd
|
||||||
var profile string
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
authCmd.AddCommand(envCmd)
|
|
||||||
envCmd.Flags().StringVar(&host, "host", host, "Hostname to get auth env for")
|
|
||||||
envCmd.Flags().StringVar(&profile, "profile", profile, "Profile to get auth env for")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,7 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var loginTimeout time.Duration
|
func configureHost(ctx context.Context, persistentAuth *auth.PersistentAuth, args []string, argIndex int) error {
|
||||||
var configureCluster bool
|
|
||||||
|
|
||||||
func configureHost(ctx context.Context, args []string, argIndex int) error {
|
|
||||||
if len(args) > argIndex {
|
if len(args) > argIndex {
|
||||||
persistentAuth.Host = args[argIndex]
|
persistentAuth.Host = args[argIndex]
|
||||||
return nil
|
return nil
|
||||||
|
@ -31,13 +28,23 @@ func configureHost(ctx context.Context, args []string, argIndex int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var loginCmd = &cobra.Command{
|
func newLoginCommand(persistentAuth *auth.PersistentAuth) *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "login [HOST]",
|
Use: "login [HOST]",
|
||||||
Short: "Authenticate this machine",
|
Short: "Authenticate this machine",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
var loginTimeout time.Duration
|
||||||
|
var configureCluster bool
|
||||||
|
cmd.Flags().DurationVar(&loginTimeout, "timeout", auth.DefaultTimeout,
|
||||||
|
"Timeout for completing login challenge in the browser")
|
||||||
|
cmd.Flags().BoolVar(&configureCluster, "configure-cluster", false,
|
||||||
|
"Prompts to configure cluster")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
if persistentAuth.Host == "" {
|
if persistentAuth.Host == "" {
|
||||||
configureHost(ctx, args, 0)
|
configureHost(ctx, persistentAuth, args, 0)
|
||||||
}
|
}
|
||||||
defer persistentAuth.Close()
|
defer persistentAuth.Close()
|
||||||
|
|
||||||
|
@ -108,14 +115,7 @@ var loginCmd = &cobra.Command{
|
||||||
|
|
||||||
cmdio.LogString(ctx, fmt.Sprintf("Profile %s was successfully saved", profileName))
|
cmdio.LogString(ctx, fmt.Sprintf("Profile %s was successfully saved", profileName))
|
||||||
return nil
|
return nil
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
authCmd.AddCommand(loginCmd)
|
|
||||||
loginCmd.Flags().DurationVar(&loginTimeout, "timeout", auth.DefaultTimeout,
|
|
||||||
"Timeout for completing login challenge in the browser")
|
|
||||||
|
|
||||||
loginCmd.Flags().BoolVar(&configureCluster, "configure-cluster", false,
|
|
||||||
"Prompts to configure cluster")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ func (c *profileMetadata) IsEmpty() bool {
|
||||||
return c.Host == "" && c.AccountID == ""
|
return c.Host == "" && c.AccountID == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *profileMetadata) Load(ctx context.Context) {
|
func (c *profileMetadata) Load(ctx context.Context, skipValidate bool) {
|
||||||
// TODO: disable config loaders other than configfile
|
// TODO: disable config loaders other than configfile
|
||||||
cfg := &config.Config{Profile: c.Name}
|
cfg := &config.Config{Profile: c.Name}
|
||||||
_ = cfg.EnsureResolved()
|
_ = cfg.EnsureResolved()
|
||||||
|
@ -94,7 +94,8 @@ func (c *profileMetadata) Load(ctx context.Context) {
|
||||||
c.Host = cfg.Host
|
c.Host = cfg.Host
|
||||||
}
|
}
|
||||||
|
|
||||||
var profilesCmd = &cobra.Command{
|
func newProfilesCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "profiles",
|
Use: "profiles",
|
||||||
Short: "Lists profiles from ~/.databrickscfg",
|
Short: "Lists profiles from ~/.databrickscfg",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
|
@ -103,7 +104,12 @@ var profilesCmd = &cobra.Command{
|
||||||
{{range .Profiles}}{{.Name | green}} {{.Host|cyan}} {{bool .Valid}}
|
{{range .Profiles}}{{.Name | green}} {{.Host|cyan}} {{bool .Valid}}
|
||||||
{{end}}`),
|
{{end}}`),
|
||||||
},
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
var skipValidate bool
|
||||||
|
cmd.Flags().BoolVar(&skipValidate, "skip-validate", false, "Whether to skip validating the profiles")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
var profiles []*profileMetadata
|
var profiles []*profileMetadata
|
||||||
iniFile, err := getDatabricksCfg()
|
iniFile, err := getDatabricksCfg()
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
@ -126,7 +132,7 @@ var profilesCmd = &cobra.Command{
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
// load more information about profile
|
// load more information about profile
|
||||||
profile.Load(cmd.Context())
|
profile.Load(cmd.Context(), skipValidate)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
profiles = append(profiles, profile)
|
profiles = append(profiles, profile)
|
||||||
|
@ -135,12 +141,7 @@ var profilesCmd = &cobra.Command{
|
||||||
return cmdio.Render(cmd.Context(), struct {
|
return cmdio.Render(cmd.Context(), struct {
|
||||||
Profiles []*profileMetadata `json:"profiles"`
|
Profiles []*profileMetadata `json:"profiles"`
|
||||||
}{profiles})
|
}{profiles})
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var skipValidate bool
|
return cmd
|
||||||
|
|
||||||
func init() {
|
|
||||||
authCmd.AddCommand(profilesCmd)
|
|
||||||
profilesCmd.Flags().BoolVar(&skipValidate, "skip-validate", false, "Whether to skip validating the profiles")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,15 +9,20 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var tokenTimeout time.Duration
|
func newTokenCommand(persistentAuth *auth.PersistentAuth) *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
var tokenCmd = &cobra.Command{
|
|
||||||
Use: "token [HOST]",
|
Use: "token [HOST]",
|
||||||
Short: "Get authentication token",
|
Short: "Get authentication token",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
var tokenTimeout time.Duration
|
||||||
|
cmd.Flags().DurationVar(&tokenTimeout, "timeout", auth.DefaultTimeout,
|
||||||
|
"Timeout for acquiring a token.")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
if persistentAuth.Host == "" {
|
if persistentAuth.Host == "" {
|
||||||
configureHost(ctx, args, 0)
|
configureHost(ctx, persistentAuth, args, 0)
|
||||||
}
|
}
|
||||||
defer persistentAuth.Close()
|
defer persistentAuth.Close()
|
||||||
|
|
||||||
|
@ -33,11 +38,7 @@ var tokenCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
cmd.OutOrStdout().Write(raw)
|
cmd.OutOrStdout().Write(raw)
|
||||||
return nil
|
return nil
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
authCmd.AddCommand(tokenCmd)
|
|
||||||
tokenCmd.Flags().DurationVar(&tokenTimeout, "timeout", auth.DefaultTimeout,
|
|
||||||
"Timeout for acquiring a token.")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package bundle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "bundle",
|
||||||
|
Short: "Databricks Asset Bundles",
|
||||||
|
}
|
||||||
|
|
||||||
|
initVariableFlag(cmd)
|
||||||
|
cmd.AddCommand(newDeployCommand())
|
||||||
|
cmd.AddCommand(newDestroyCommand())
|
||||||
|
cmd.AddCommand(newLaunchCommand())
|
||||||
|
cmd.AddCommand(newRunCommand())
|
||||||
|
cmd.AddCommand(newSchemaCommand())
|
||||||
|
cmd.AddCommand(newSyncCommand())
|
||||||
|
cmd.AddCommand(newTestCommand())
|
||||||
|
cmd.AddCommand(newValidateCommand())
|
||||||
|
return cmd
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
package debug
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
parent "github.com/databricks/cli/cmd/bundle"
|
|
||||||
)
|
|
||||||
|
|
||||||
var debugCmd = &cobra.Command{
|
|
||||||
Use: "debug",
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddCommand(cmd *cobra.Command) {
|
|
||||||
debugCmd.AddCommand(cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
parent.AddCommand(debugCmd)
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package debug
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/databricks/cli/bundle"
|
|
||||||
bundleCmd "github.com/databricks/cli/cmd/bundle"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var whoamiCmd = &cobra.Command{
|
|
||||||
Use: "whoami",
|
|
||||||
|
|
||||||
PreRunE: bundleCmd.ConfigureBundleWithVariables,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
ctx := cmd.Context()
|
|
||||||
w := bundle.Get(ctx).WorkspaceClient()
|
|
||||||
user, err := w.CurrentUser.Me(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintln(cmd.OutOrStdout(), user.UserName)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
debugCmd.AddCommand(whoamiCmd)
|
|
||||||
}
|
|
|
@ -6,12 +6,19 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var deployCmd = &cobra.Command{
|
func newDeployCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "deploy",
|
Use: "deploy",
|
||||||
Short: "Deploy bundle",
|
Short: "Deploy bundle",
|
||||||
|
|
||||||
PreRunE: ConfigureBundleWithVariables,
|
PreRunE: ConfigureBundleWithVariables,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
var forceDeploy bool
|
||||||
|
var computeID string
|
||||||
|
cmd.Flags().BoolVar(&forceDeploy, "force", false, "Force acquisition of deployment lock.")
|
||||||
|
cmd.Flags().StringVarP(&computeID, "compute-id", "c", "", "Override compute in the deployment with the given compute ID.")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
b := bundle.Get(cmd.Context())
|
b := bundle.Get(cmd.Context())
|
||||||
|
|
||||||
// If `--force` is specified, force acquisition of the deployment lock.
|
// If `--force` is specified, force acquisition of the deployment lock.
|
||||||
|
@ -23,14 +30,7 @@ var deployCmd = &cobra.Command{
|
||||||
phases.Build(),
|
phases.Build(),
|
||||||
phases.Deploy(),
|
phases.Deploy(),
|
||||||
))
|
))
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var forceDeploy bool
|
return cmd
|
||||||
var computeID string
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
AddCommand(deployCmd)
|
|
||||||
deployCmd.Flags().BoolVar(&forceDeploy, "force", false, "Force acquisition of deployment lock.")
|
|
||||||
deployCmd.Flags().StringVarP(&computeID, "compute-id", "c", "", "Override compute in the deployment with the given compute ID.")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,20 @@ import (
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
var destroyCmd = &cobra.Command{
|
func newDestroyCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "destroy",
|
Use: "destroy",
|
||||||
Short: "Destroy deployed bundle resources",
|
Short: "Destroy deployed bundle resources",
|
||||||
|
|
||||||
PreRunE: ConfigureBundleWithVariables,
|
PreRunE: ConfigureBundleWithVariables,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
var autoApprove bool
|
||||||
|
var forceDestroy bool
|
||||||
|
cmd.Flags().BoolVar(&autoApprove, "auto-approve", false, "Skip interactive approvals for deleting resources and files")
|
||||||
|
cmd.Flags().BoolVar(&forceDestroy, "force", false, "Force acquisition of deployment lock.")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
b := bundle.Get(ctx)
|
b := bundle.Get(ctx)
|
||||||
|
|
||||||
|
@ -47,14 +55,7 @@ var destroyCmd = &cobra.Command{
|
||||||
phases.Build(),
|
phases.Build(),
|
||||||
phases.Destroy(),
|
phases.Destroy(),
|
||||||
))
|
))
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var autoApprove bool
|
return cmd
|
||||||
var forceDestroy bool
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
AddCommand(destroyCmd)
|
|
||||||
destroyCmd.Flags().BoolVar(&autoApprove, "auto-approve", false, "Skip interactive approvals for deleting resources and files")
|
|
||||||
destroyCmd.Flags().BoolVar(&forceDestroy, "force", false, "Force acquisition of deployment lock.")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var launchCmd = &cobra.Command{
|
func newLaunchCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "launch",
|
Use: "launch",
|
||||||
Short: "Launches a notebook on development cluster",
|
Short: "Launches a notebook on development cluster",
|
||||||
Long: `Reads a file and executes it on dev cluster`,
|
Long: `Reads a file and executes it on dev cluster`,
|
||||||
|
@ -17,7 +18,9 @@ var launchCmd = &cobra.Command{
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
|
|
||||||
PreRunE: root.MustConfigureBundle,
|
PreRunE: root.MustConfigureBundle,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("TODO")
|
return fmt.Errorf("TODO")
|
||||||
// contents, err := os.ReadFile(args[0])
|
// contents, err := os.ReadFile(args[0])
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
|
@ -29,9 +32,7 @@ var launchCmd = &cobra.Command{
|
||||||
// }
|
// }
|
||||||
// fmt.Fprintf(cmd.OutOrStdout(), "Success: %s", results.Text())
|
// fmt.Fprintf(cmd.OutOrStdout(), "Success: %s", results.Text())
|
||||||
// return nil
|
// return nil
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
AddCommand(launchCmd)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package bundle
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/databricks/cli/cmd/root"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
// rootCmd represents the root command for the bundle subcommand.
|
|
||||||
var rootCmd = &cobra.Command{
|
|
||||||
Use: "bundle",
|
|
||||||
Short: "Databricks Asset Bundles",
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddCommand(cmd *cobra.Command) {
|
|
||||||
rootCmd.AddCommand(cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var variables []string
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
root.RootCmd.AddCommand(rootCmd)
|
|
||||||
AddVariableFlag(rootCmd)
|
|
||||||
}
|
|
|
@ -13,16 +13,22 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var runOptions run.Options
|
func newRunCommand() *cobra.Command {
|
||||||
var noWait bool
|
cmd := &cobra.Command{
|
||||||
|
|
||||||
var runCmd = &cobra.Command{
|
|
||||||
Use: "run [flags] KEY",
|
Use: "run [flags] KEY",
|
||||||
Short: "Run a workload (e.g. a job or a pipeline)",
|
Short: "Run a workload (e.g. a job or a pipeline)",
|
||||||
|
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
PreRunE: ConfigureBundleWithVariables,
|
PreRunE: ConfigureBundleWithVariables,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
var runOptions run.Options
|
||||||
|
runOptions.Define(cmd.Flags())
|
||||||
|
|
||||||
|
var noWait bool
|
||||||
|
cmd.Flags().BoolVar(&noWait, "no-wait", false, "Don't wait for the run to complete.")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
b := bundle.Get(cmd.Context())
|
b := bundle.Get(cmd.Context())
|
||||||
|
|
||||||
err := bundle.Apply(cmd.Context(), b, bundle.Seq(
|
err := bundle.Apply(cmd.Context(), b, bundle.Seq(
|
||||||
|
@ -65,9 +71,9 @@ var runCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
}
|
||||||
|
|
||||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
}
|
}
|
||||||
|
@ -86,11 +92,7 @@ var runCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
return run.ResourceCompletions(b), cobra.ShellCompDirectiveNoFileComp
|
return run.ResourceCompletions(b), cobra.ShellCompDirectiveNoFileComp
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
runOptions.Define(runCmd.Flags())
|
|
||||||
rootCmd.AddCommand(runCmd)
|
|
||||||
runCmd.Flags().BoolVar(&noWait, "no-wait", false, "Don't wait for the run to complete.")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,18 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var schemaCmd = &cobra.Command{
|
func newSchemaCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "schema",
|
Use: "schema",
|
||||||
Short: "Generate JSON Schema for bundle configuration",
|
Short: "Generate JSON Schema for bundle configuration",
|
||||||
|
}
|
||||||
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
var openapi string
|
||||||
|
var onlyDocs bool
|
||||||
|
cmd.Flags().StringVar(&openapi, "openapi", "", "path to a databricks openapi spec")
|
||||||
|
cmd.Flags().BoolVar(&onlyDocs, "only-docs", false, "only generate descriptions for the schema")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
docs, err := schema.BundleDocs(openapi)
|
docs, err := schema.BundleDocs(openapi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -34,14 +41,7 @@ var schemaCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
cmd.OutOrStdout().Write(result)
|
cmd.OutOrStdout().Write(result)
|
||||||
return nil
|
return nil
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var openapi string
|
return cmd
|
||||||
var onlyDocs bool
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
AddCommand(schemaCmd)
|
|
||||||
schemaCmd.Flags().StringVar(&openapi, "openapi", "", "path to a databricks openapi spec")
|
|
||||||
schemaCmd.Flags().BoolVar(&onlyDocs, "only-docs", false, "only generate descriptions for the schema")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,13 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func syncOptionsFromBundle(cmd *cobra.Command, b *bundle.Bundle) (*sync.SyncOptions, error) {
|
type syncFlags struct {
|
||||||
|
interval time.Duration
|
||||||
|
full bool
|
||||||
|
watch bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *syncFlags) syncOptionsFromBundle(cmd *cobra.Command, b *bundle.Bundle) (*sync.SyncOptions, error) {
|
||||||
cacheDir, err := b.CacheDir()
|
cacheDir, err := b.CacheDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot get bundle cache directory: %w", err)
|
return nil, fmt.Errorf("cannot get bundle cache directory: %w", err)
|
||||||
|
@ -20,8 +26,8 @@ func syncOptionsFromBundle(cmd *cobra.Command, b *bundle.Bundle) (*sync.SyncOpti
|
||||||
opts := sync.SyncOptions{
|
opts := sync.SyncOptions{
|
||||||
LocalPath: b.Config.Path,
|
LocalPath: b.Config.Path,
|
||||||
RemotePath: b.Config.Workspace.FilesPath,
|
RemotePath: b.Config.Workspace.FilesPath,
|
||||||
Full: full,
|
Full: f.full,
|
||||||
PollInterval: interval,
|
PollInterval: f.interval,
|
||||||
|
|
||||||
SnapshotBasePath: cacheDir,
|
SnapshotBasePath: cacheDir,
|
||||||
WorkspaceClient: b.WorkspaceClient(),
|
WorkspaceClient: b.WorkspaceClient(),
|
||||||
|
@ -29,13 +35,21 @@ func syncOptionsFromBundle(cmd *cobra.Command, b *bundle.Bundle) (*sync.SyncOpti
|
||||||
return &opts, nil
|
return &opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var syncCmd = &cobra.Command{
|
func newSyncCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "sync [flags]",
|
Use: "sync [flags]",
|
||||||
Short: "Synchronize bundle tree to the workspace",
|
Short: "Synchronize bundle tree to the workspace",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
|
|
||||||
PreRunE: ConfigureBundleWithVariables,
|
PreRunE: ConfigureBundleWithVariables,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
var f syncFlags
|
||||||
|
cmd.Flags().DurationVar(&f.interval, "interval", 1*time.Second, "file system polling interval (for --watch)")
|
||||||
|
cmd.Flags().BoolVar(&f.full, "full", false, "perform full synchronization (default is incremental)")
|
||||||
|
cmd.Flags().BoolVar(&f.watch, "watch", false, "watch local file system for changes")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
b := bundle.Get(cmd.Context())
|
b := bundle.Get(cmd.Context())
|
||||||
|
|
||||||
// Run initialize phase to make sure paths are set.
|
// Run initialize phase to make sure paths are set.
|
||||||
|
@ -44,7 +58,7 @@ var syncCmd = &cobra.Command{
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
opts, err := syncOptionsFromBundle(cmd, b)
|
opts, err := f.syncOptionsFromBundle(cmd, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -57,21 +71,12 @@ var syncCmd = &cobra.Command{
|
||||||
|
|
||||||
log.Infof(ctx, "Remote file sync location: %v", opts.RemotePath)
|
log.Infof(ctx, "Remote file sync location: %v", opts.RemotePath)
|
||||||
|
|
||||||
if watch {
|
if f.watch {
|
||||||
return s.RunContinuous(ctx)
|
return s.RunContinuous(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.RunOnce(ctx)
|
return s.RunOnce(ctx)
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var interval time.Duration
|
return cmd
|
||||||
var full bool
|
|
||||||
var watch bool
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
AddCommand(syncCmd)
|
|
||||||
syncCmd.Flags().DurationVar(&interval, "interval", 1*time.Second, "file system polling interval (for --watch)")
|
|
||||||
syncCmd.Flags().BoolVar(&full, "full", false, "perform full synchronization (default is incremental)")
|
|
||||||
syncCmd.Flags().BoolVar(&watch, "watch", false, "watch local file system for changes")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testCmd = &cobra.Command{
|
func newTestCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "test",
|
Use: "test",
|
||||||
Short: "run tests for the project",
|
Short: "run tests for the project",
|
||||||
Long: `This is longer description of the command`,
|
Long: `This is longer description of the command`,
|
||||||
|
@ -16,7 +17,9 @@ var testCmd = &cobra.Command{
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
|
|
||||||
PreRunE: root.MustConfigureBundle,
|
PreRunE: root.MustConfigureBundle,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("TODO")
|
return fmt.Errorf("TODO")
|
||||||
// results := project.RunPythonOnDev(cmd.Context(), `return 1`)
|
// results := project.RunPythonOnDev(cmd.Context(), `return 1`)
|
||||||
// if results.Failed() {
|
// if results.Failed() {
|
||||||
|
@ -24,9 +27,7 @@ var testCmd = &cobra.Command{
|
||||||
// }
|
// }
|
||||||
// fmt.Fprintf(cmd.OutOrStdout(), "Success: %s", results.Text())
|
// fmt.Fprintf(cmd.OutOrStdout(), "Success: %s", results.Text())
|
||||||
// return nil
|
// return nil
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
AddCommand(testCmd)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,15 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var validateCmd = &cobra.Command{
|
func newValidateCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "validate",
|
Use: "validate",
|
||||||
Short: "Validate configuration",
|
Short: "Validate configuration",
|
||||||
|
|
||||||
PreRunE: ConfigureBundleWithVariables,
|
PreRunE: ConfigureBundleWithVariables,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
b := bundle.Get(cmd.Context())
|
b := bundle.Get(cmd.Context())
|
||||||
|
|
||||||
err := bundle.Apply(cmd.Context(), b, phases.Initialize())
|
err := bundle.Apply(cmd.Context(), b, phases.Initialize())
|
||||||
|
@ -27,9 +30,7 @@ var validateCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
cmd.OutOrStdout().Write(buf)
|
cmd.OutOrStdout().Write(buf)
|
||||||
return nil
|
return nil
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
AddCommand(validateCmd)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,16 @@ func ConfigureBundleWithVariables(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variables, err := cmd.Flags().GetStringSlice("var")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize variables by assigning them values passed as command line flags
|
// Initialize variables by assigning them values passed as command line flags
|
||||||
b := bundle.Get(cmd.Context())
|
b := bundle.Get(cmd.Context())
|
||||||
return b.Config.InitializeVariables(variables)
|
return b.Config.InitializeVariables(variables)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddVariableFlag(cmd *cobra.Command) {
|
func initVariableFlag(cmd *cobra.Command) {
|
||||||
cmd.PersistentFlags().StringSliceVar(&variables, "var", []string{}, `set values for variables defined in bundle config. Example: --var="foo=bar"`)
|
cmd.PersistentFlags().StringSlice("var", []string{}, `set values for variables defined in bundle config. Example: --var="foo=bar"`)
|
||||||
}
|
}
|
||||||
|
|
30
cmd/cmd.go
30
cmd/cmd.go
|
@ -1,23 +1,21 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/databricks/cli/cmd/account"
|
"github.com/databricks/cli/cmd/account"
|
||||||
|
"github.com/databricks/cli/cmd/api"
|
||||||
|
"github.com/databricks/cli/cmd/auth"
|
||||||
|
"github.com/databricks/cli/cmd/bundle"
|
||||||
|
"github.com/databricks/cli/cmd/configure"
|
||||||
|
"github.com/databricks/cli/cmd/fs"
|
||||||
"github.com/databricks/cli/cmd/root"
|
"github.com/databricks/cli/cmd/root"
|
||||||
|
"github.com/databricks/cli/cmd/sync"
|
||||||
|
"github.com/databricks/cli/cmd/version"
|
||||||
"github.com/databricks/cli/cmd/workspace"
|
"github.com/databricks/cli/cmd/workspace"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var once sync.Once
|
|
||||||
var cmd *cobra.Command
|
|
||||||
|
|
||||||
func New() *cobra.Command {
|
func New() *cobra.Command {
|
||||||
// TODO: this command is still a global.
|
cli := root.New()
|
||||||
// Once the non-generated commands are all instantiatable,
|
|
||||||
// we can remove the global and instantiate this as well.
|
|
||||||
once.Do(func() {
|
|
||||||
cli := root.RootCmd
|
|
||||||
|
|
||||||
// Add account subcommand.
|
// Add account subcommand.
|
||||||
cli.AddCommand(account.New())
|
cli.AddCommand(account.New())
|
||||||
|
@ -33,8 +31,14 @@ func New() *cobra.Command {
|
||||||
cli.AddGroup(&groups[i])
|
cli.AddGroup(&groups[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = cli
|
// Add other subcommands.
|
||||||
})
|
cli.AddCommand(api.New())
|
||||||
|
cli.AddCommand(auth.New())
|
||||||
|
cli.AddCommand(bundle.New())
|
||||||
|
cli.AddCommand(configure.New())
|
||||||
|
cli.AddCommand(fs.New())
|
||||||
|
cli.AddCommand(sync.New())
|
||||||
|
cli.AddCommand(version.New())
|
||||||
|
|
||||||
return cmd
|
return cli
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/databricks/cli/cmd/root"
|
|
||||||
"github.com/databricks/cli/libs/cmdio"
|
"github.com/databricks/cli/libs/cmdio"
|
||||||
"github.com/databricks/cli/libs/databrickscfg"
|
"github.com/databricks/cli/libs/databrickscfg"
|
||||||
"github.com/databricks/databricks-sdk-go/config"
|
"github.com/databricks/databricks-sdk-go/config"
|
||||||
|
@ -112,19 +111,30 @@ func configureNonInteractive(cmd *cobra.Command, ctx context.Context, cfg *confi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var configureCmd = &cobra.Command{
|
func newConfigureCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "configure",
|
Use: "configure",
|
||||||
Short: "Configure authentication",
|
Short: "Configure authentication",
|
||||||
Long: `Configure authentication.
|
Long: `Configure authentication.
|
||||||
|
|
||||||
This command adds a profile to your ~/.databrickscfg file.
|
This command adds a profile to your ~/.databrickscfg file.
|
||||||
You can write to a different file by setting the DATABRICKS_CONFIG_FILE environment variable.
|
You can write to a different file by setting the DATABRICKS_CONFIG_FILE environment variable.
|
||||||
|
|
||||||
If this command is invoked in non-interactive mode, it will read the token from stdin.
|
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.
|
The host must be specified with the --host flag.
|
||||||
`,
|
`,
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
}
|
||||||
|
|
||||||
|
cmd.Flags().String("host", "", "Databricks workspace host.")
|
||||||
|
cmd.Flags().String("profile", "DEFAULT", "Name for the connection profile to configure.")
|
||||||
|
|
||||||
|
// Include token flag for compatibility with the legacy CLI.
|
||||||
|
// It doesn't actually do anything because we always use PATs.
|
||||||
|
cmd.Flags().BoolP("token", "t", true, "Configure using Databricks Personal Access Token")
|
||||||
|
cmd.Flags().MarkHidden("token")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
var cfg config.Config
|
var cfg config.Config
|
||||||
|
|
||||||
// Load environment variables, possibly the DEFAULT profile.
|
// Load environment variables, possibly the DEFAULT profile.
|
||||||
|
@ -152,16 +162,11 @@ The host must be specified with the --host flag.
|
||||||
|
|
||||||
// Save profile to config file.
|
// Save profile to config file.
|
||||||
return databrickscfg.SaveToProfile(ctx, &cfg)
|
return databrickscfg.SaveToProfile(ctx, &cfg)
|
||||||
},
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func New() *cobra.Command {
|
||||||
root.RootCmd.AddCommand(configureCmd)
|
return newConfigureCommand()
|
||||||
configureCmd.Flags().String("host", "", "Databricks workspace host.")
|
|
||||||
configureCmd.Flags().String("profile", "DEFAULT", "Name for the connection profile to configure.")
|
|
||||||
|
|
||||||
// Include token flag for compatibility with the legacy CLI.
|
|
||||||
// It doesn't actually do anything because we always use PATs.
|
|
||||||
configureCmd.Flags().BoolP("token", "t", true, "Configure using Databricks Personal Access Token")
|
|
||||||
configureCmd.Flags().MarkHidden("token")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package configure
|
package configure_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -7,7 +7,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/databricks/cli/cmd/root"
|
"github.com/databricks/cli/cmd"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
)
|
)
|
||||||
|
@ -54,9 +54,10 @@ func TestDefaultConfigureNoInteractive(t *testing.T) {
|
||||||
})
|
})
|
||||||
os.Stdin = inp
|
os.Stdin = inp
|
||||||
|
|
||||||
root.RootCmd.SetArgs([]string{"configure", "--token", "--host", "https://host"})
|
cmd := cmd.New()
|
||||||
|
cmd.SetArgs([]string{"configure", "--token", "--host", "https://host"})
|
||||||
|
|
||||||
err := root.RootCmd.ExecuteContext(ctx)
|
err := cmd.ExecuteContext(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
cfgPath := filepath.Join(tempHomeDir, ".databrickscfg")
|
cfgPath := filepath.Join(tempHomeDir, ".databrickscfg")
|
||||||
|
@ -86,9 +87,10 @@ func TestConfigFileFromEnvNoInteractive(t *testing.T) {
|
||||||
t.Cleanup(func() { os.Stdin = oldStdin })
|
t.Cleanup(func() { os.Stdin = oldStdin })
|
||||||
os.Stdin = inp
|
os.Stdin = inp
|
||||||
|
|
||||||
root.RootCmd.SetArgs([]string{"configure", "--token", "--host", "https://host"})
|
cmd := cmd.New()
|
||||||
|
cmd.SetArgs([]string{"configure", "--token", "--host", "https://host"})
|
||||||
|
|
||||||
err := root.RootCmd.ExecuteContext(ctx)
|
err := cmd.ExecuteContext(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
_, err = os.Stat(cfgPath)
|
_, err = os.Stat(cfgPath)
|
||||||
|
@ -114,9 +116,10 @@ func TestCustomProfileConfigureNoInteractive(t *testing.T) {
|
||||||
t.Cleanup(func() { os.Stdin = oldStdin })
|
t.Cleanup(func() { os.Stdin = oldStdin })
|
||||||
os.Stdin = inp
|
os.Stdin = inp
|
||||||
|
|
||||||
root.RootCmd.SetArgs([]string{"configure", "--token", "--host", "https://host", "--profile", "CUSTOM"})
|
cmd := cmd.New()
|
||||||
|
cmd.SetArgs([]string{"configure", "--token", "--host", "https://host", "--profile", "CUSTOM"})
|
||||||
|
|
||||||
err := root.RootCmd.ExecuteContext(ctx)
|
err := cmd.ExecuteContext(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
_, err = os.Stat(cfgPath)
|
_, err = os.Stat(cfgPath)
|
||||||
|
|
|
@ -6,14 +6,16 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var catCmd = &cobra.Command{
|
func newCatCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "cat FILE_PATH",
|
Use: "cat FILE_PATH",
|
||||||
Short: "Show file content",
|
Short: "Show file content",
|
||||||
Long: `Show the contents of a file.`,
|
Long: `Show the contents of a file.`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
PreRunE: root.MustWorkspaceClient,
|
PreRunE: root.MustWorkspaceClient,
|
||||||
|
}
|
||||||
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
|
|
||||||
f, path, err := filerForPath(ctx, args[0])
|
f, path, err := filerForPath(ctx, args[0])
|
||||||
|
@ -26,9 +28,7 @@ var catCmd = &cobra.Command{
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return cmdio.RenderReader(ctx, r)
|
return cmdio.RenderReader(ctx, r)
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
fsCmd.AddCommand(catCmd)
|
|
||||||
}
|
}
|
||||||
|
|
49
cmd/fs/cp.go
49
cmd/fs/cp.go
|
@ -15,6 +15,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type copy struct {
|
type copy struct {
|
||||||
|
overwrite bool
|
||||||
|
recursive bool
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
sourceFiler filer.Filer
|
sourceFiler filer.Filer
|
||||||
targetFiler filer.Filer
|
targetFiler filer.Filer
|
||||||
|
@ -48,7 +51,7 @@ func (c *copy) cpWriteCallback(sourceDir, targetDir string) fs.WalkDirFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *copy) cpDirToDir(sourceDir, targetDir string) error {
|
func (c *copy) cpDirToDir(sourceDir, targetDir string) error {
|
||||||
if !cpRecursive {
|
if !c.recursive {
|
||||||
return fmt.Errorf("source path %s is a directory. Please specify the --recursive flag", sourceDir)
|
return fmt.Errorf("source path %s is a directory. Please specify the --recursive flag", sourceDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +74,7 @@ func (c *copy) cpFileToFile(sourcePath, targetPath string) error {
|
||||||
}
|
}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
|
|
||||||
if cpOverwrite {
|
if c.overwrite {
|
||||||
err = c.targetFiler.Write(c.ctx, targetPath, r, filer.OverwriteIfExists)
|
err = c.targetFiler.Write(c.ctx, targetPath, r, filer.OverwriteIfExists)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -123,11 +126,8 @@ func (c *copy) emitFileCopiedEvent(sourcePath, targetPath string) error {
|
||||||
return cmdio.RenderWithTemplate(c.ctx, event, template)
|
return cmdio.RenderWithTemplate(c.ctx, event, template)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cpOverwrite bool
|
func newCpCommand() *cobra.Command {
|
||||||
var cpRecursive bool
|
cmd := &cobra.Command{
|
||||||
|
|
||||||
// cpCmd represents the fs cp command
|
|
||||||
var cpCmd = &cobra.Command{
|
|
||||||
Use: "cp SOURCE_PATH TARGET_PATH",
|
Use: "cp SOURCE_PATH TARGET_PATH",
|
||||||
Short: "Copy files and directories to and from DBFS.",
|
Short: "Copy files and directories to and from DBFS.",
|
||||||
Long: `Copy files to and from DBFS.
|
Long: `Copy files to and from DBFS.
|
||||||
|
@ -140,11 +140,16 @@ var cpCmd = &cobra.Command{
|
||||||
|
|
||||||
When copying a file, if TARGET_PATH is a directory, the file will be created
|
When copying a file, if TARGET_PATH is a directory, the file will be created
|
||||||
inside the directory, otherwise the file is created at TARGET_PATH.
|
inside the directory, otherwise the file is created at TARGET_PATH.
|
||||||
`,
|
`,
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
PreRunE: root.MustWorkspaceClient,
|
PreRunE: root.MustWorkspaceClient,
|
||||||
|
}
|
||||||
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
var c copy
|
||||||
|
cmd.Flags().BoolVar(&c.overwrite, "overwrite", false, "overwrite existing files")
|
||||||
|
cmd.Flags().BoolVarP(&c.recursive, "recursive", "r", false, "recursively copy files from directory")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
|
|
||||||
// TODO: Error if a user uses '\' as path separator on windows when "file"
|
// TODO: Error if a user uses '\' as path separator on windows when "file"
|
||||||
|
@ -164,22 +169,18 @@ var cpCmd = &cobra.Command{
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceScheme := ""
|
c.sourceScheme = ""
|
||||||
if isDbfsPath(fullSourcePath) {
|
if isDbfsPath(fullSourcePath) {
|
||||||
sourceScheme = "dbfs"
|
c.sourceScheme = "dbfs"
|
||||||
}
|
}
|
||||||
targetScheme := ""
|
c.targetScheme = ""
|
||||||
if isDbfsPath(fullTargetPath) {
|
if isDbfsPath(fullTargetPath) {
|
||||||
targetScheme = "dbfs"
|
c.targetScheme = "dbfs"
|
||||||
}
|
}
|
||||||
|
|
||||||
c := copy{
|
c.ctx = ctx
|
||||||
ctx: ctx,
|
c.sourceFiler = sourceFiler
|
||||||
sourceFiler: sourceFiler,
|
c.targetFiler = targetFiler
|
||||||
targetFiler: targetFiler,
|
|
||||||
sourceScheme: sourceScheme,
|
|
||||||
targetScheme: targetScheme,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get information about file at source path
|
// Get information about file at source path
|
||||||
sourceInfo, err := sourceFiler.Stat(ctx, sourcePath)
|
sourceInfo, err := sourceFiler.Stat(ctx, sourcePath)
|
||||||
|
@ -200,11 +201,7 @@ var cpCmd = &cobra.Command{
|
||||||
|
|
||||||
// case 3: source path is a file, and target path is a file
|
// case 3: source path is a file, and target path is a file
|
||||||
return c.cpFileToFile(sourcePath, targetPath)
|
return c.cpFileToFile(sourcePath, targetPath)
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
cpCmd.Flags().BoolVar(&cpOverwrite, "overwrite", false, "overwrite existing files")
|
|
||||||
cpCmd.Flags().BoolVarP(&cpRecursive, "recursive", "r", false, "recursively copy files from directory")
|
|
||||||
fsCmd.AddCommand(cpCmd)
|
|
||||||
}
|
}
|
||||||
|
|
18
cmd/fs/fs.go
18
cmd/fs/fs.go
|
@ -1,17 +1,23 @@
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/databricks/cli/cmd/root"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fsCmd represents the fs command
|
func New() *cobra.Command {
|
||||||
var fsCmd = &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "fs",
|
Use: "fs",
|
||||||
Short: "Filesystem related commands",
|
Short: "Filesystem related commands",
|
||||||
Long: `Commands to do DBFS operations.`,
|
Long: `Commands to do DBFS operations.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
cmd.AddCommand(
|
||||||
root.RootCmd.AddCommand(fsCmd)
|
newCatCommand(),
|
||||||
|
newCpCommand(),
|
||||||
|
newLsCommand(),
|
||||||
|
newMkdirCommand(),
|
||||||
|
newRmCommand(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
27
cmd/fs/ls.go
27
cmd/fs/ls.go
|
@ -37,15 +37,21 @@ func toJsonDirEntry(f fs.DirEntry, baseDir string, isAbsolute bool) (*jsonDirEnt
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// lsCmd represents the ls command
|
func newLsCommand() *cobra.Command {
|
||||||
var lsCmd = &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "ls DIR_PATH",
|
Use: "ls DIR_PATH",
|
||||||
Short: "Lists files",
|
Short: "Lists files",
|
||||||
Long: `Lists files`,
|
Long: `Lists files`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
PreRunE: root.MustWorkspaceClient,
|
PreRunE: root.MustWorkspaceClient,
|
||||||
|
}
|
||||||
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
var long bool
|
||||||
|
var absolute bool
|
||||||
|
cmd.Flags().BoolVarP(&long, "long", "l", false, "Displays full information including size, file type and modification time since Epoch in milliseconds.")
|
||||||
|
cmd.Flags().BoolVar(&absolute, "absolute", false, "Displays absolute paths.")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
|
|
||||||
f, path, err := filerForPath(ctx, args[0])
|
f, path, err := filerForPath(ctx, args[0])
|
||||||
|
@ -60,7 +66,7 @@ var lsCmd = &cobra.Command{
|
||||||
|
|
||||||
jsonDirEntries := make([]jsonDirEntry, len(entries))
|
jsonDirEntries := make([]jsonDirEntry, len(entries))
|
||||||
for i, entry := range entries {
|
for i, entry := range entries {
|
||||||
jsonDirEntry, err := toJsonDirEntry(entry, args[0], lsAbsolute)
|
jsonDirEntry, err := toJsonDirEntry(entry, args[0], absolute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -71,7 +77,7 @@ var lsCmd = &cobra.Command{
|
||||||
})
|
})
|
||||||
|
|
||||||
// Use template for long mode if the flag is set
|
// Use template for long mode if the flag is set
|
||||||
if longMode {
|
if long {
|
||||||
return cmdio.RenderWithTemplate(ctx, jsonDirEntries, cmdio.Heredoc(`
|
return cmdio.RenderWithTemplate(ctx, jsonDirEntries, cmdio.Heredoc(`
|
||||||
{{range .}}{{if .IsDir}}DIRECTORY {{else}}FILE {{end}}{{.Size}} {{.ModTime|pretty_date}} {{.Name}}
|
{{range .}}{{if .IsDir}}DIRECTORY {{else}}FILE {{end}}{{.Size}} {{.ModTime|pretty_date}} {{.Name}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -81,14 +87,7 @@ var lsCmd = &cobra.Command{
|
||||||
{{range .}}{{.Name}}
|
{{range .}}{{.Name}}
|
||||||
{{end}}
|
{{end}}
|
||||||
`))
|
`))
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var longMode bool
|
return cmd
|
||||||
var lsAbsolute bool
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
lsCmd.Flags().BoolVarP(&longMode, "long", "l", false, "Displays full information including size, file type and modification time since Epoch in milliseconds.")
|
|
||||||
lsCmd.Flags().BoolVar(&lsAbsolute, "absolute", false, "Displays absolute paths.")
|
|
||||||
fsCmd.AddCommand(lsCmd)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var mkdirCmd = &cobra.Command{
|
func newMkdirCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "mkdir DIR_PATH",
|
Use: "mkdir DIR_PATH",
|
||||||
// Alias `mkdirs` for this command exists for legacy purposes. This command
|
// Alias `mkdirs` for this command exists for legacy purposes. This command
|
||||||
// is called databricks fs mkdirs in our legacy CLI: https://github.com/databricks/databricks-cli
|
// is called databricks fs mkdirs in our legacy CLI: https://github.com/databricks/databricks-cli
|
||||||
|
@ -14,8 +15,9 @@ var mkdirCmd = &cobra.Command{
|
||||||
Long: `Mkdir will create directories along the path to the argument directory.`,
|
Long: `Mkdir will create directories along the path to the argument directory.`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
PreRunE: root.MustWorkspaceClient,
|
PreRunE: root.MustWorkspaceClient,
|
||||||
|
}
|
||||||
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
|
|
||||||
f, path, err := filerForPath(ctx, args[0])
|
f, path, err := filerForPath(ctx, args[0])
|
||||||
|
@ -24,9 +26,7 @@ var mkdirCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.Mkdir(ctx, path)
|
return f.Mkdir(ctx, path)
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
fsCmd.AddCommand(mkdirCmd)
|
|
||||||
}
|
}
|
||||||
|
|
18
cmd/fs/rm.go
18
cmd/fs/rm.go
|
@ -6,14 +6,19 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rmCmd = &cobra.Command{
|
func newRmCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "rm PATH",
|
Use: "rm PATH",
|
||||||
Short: "Remove files and directories from dbfs.",
|
Short: "Remove files and directories from dbfs.",
|
||||||
Long: `Remove files and directories from dbfs.`,
|
Long: `Remove files and directories from dbfs.`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
PreRunE: root.MustWorkspaceClient,
|
PreRunE: root.MustWorkspaceClient,
|
||||||
|
}
|
||||||
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
var recursive bool
|
||||||
|
cmd.Flags().BoolVarP(&recursive, "recursive", "r", false, "Recursively delete a non-empty directory.")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
|
|
||||||
f, path, err := filerForPath(ctx, args[0])
|
f, path, err := filerForPath(ctx, args[0])
|
||||||
|
@ -25,12 +30,7 @@ var rmCmd = &cobra.Command{
|
||||||
return f.Delete(ctx, path, filer.DeleteRecursively)
|
return f.Delete(ctx, path, filer.DeleteRecursively)
|
||||||
}
|
}
|
||||||
return f.Delete(ctx, path)
|
return f.Delete(ctx, path)
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var recursive bool
|
return cmd
|
||||||
|
|
||||||
func init() {
|
|
||||||
rmCmd.Flags().BoolVarP(&recursive, "recursive", "r", false, "Recursively delete a non-empty directory.")
|
|
||||||
fsCmd.AddCommand(rmCmd)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,3 @@ func Execute(cmd *cobra.Command) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep a global copy until all commands can be initialized.
|
|
||||||
var RootCmd = New()
|
|
||||||
|
|
|
@ -17,7 +17,15 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func syncOptionsFromBundle(cmd *cobra.Command, args []string, b *bundle.Bundle) (*sync.SyncOptions, error) {
|
type syncFlags struct {
|
||||||
|
// project files polling interval
|
||||||
|
interval time.Duration
|
||||||
|
full bool
|
||||||
|
watch bool
|
||||||
|
output flags.Output
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *syncFlags) syncOptionsFromBundle(cmd *cobra.Command, args []string, b *bundle.Bundle) (*sync.SyncOptions, error) {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
return nil, fmt.Errorf("SRC and DST are not configurable in the context of a bundle")
|
return nil, fmt.Errorf("SRC and DST are not configurable in the context of a bundle")
|
||||||
}
|
}
|
||||||
|
@ -30,8 +38,8 @@ func syncOptionsFromBundle(cmd *cobra.Command, args []string, b *bundle.Bundle)
|
||||||
opts := sync.SyncOptions{
|
opts := sync.SyncOptions{
|
||||||
LocalPath: b.Config.Path,
|
LocalPath: b.Config.Path,
|
||||||
RemotePath: b.Config.Workspace.FilesPath,
|
RemotePath: b.Config.Workspace.FilesPath,
|
||||||
Full: full,
|
Full: f.full,
|
||||||
PollInterval: interval,
|
PollInterval: f.interval,
|
||||||
|
|
||||||
SnapshotBasePath: cacheDir,
|
SnapshotBasePath: cacheDir,
|
||||||
WorkspaceClient: b.WorkspaceClient(),
|
WorkspaceClient: b.WorkspaceClient(),
|
||||||
|
@ -39,7 +47,7 @@ func syncOptionsFromBundle(cmd *cobra.Command, args []string, b *bundle.Bundle)
|
||||||
return &opts, nil
|
return &opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncOptionsFromArgs(cmd *cobra.Command, args []string) (*sync.SyncOptions, error) {
|
func (f *syncFlags) syncOptionsFromArgs(cmd *cobra.Command, args []string) (*sync.SyncOptions, error) {
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return nil, flag.ErrHelp
|
return nil, flag.ErrHelp
|
||||||
}
|
}
|
||||||
|
@ -47,8 +55,8 @@ func syncOptionsFromArgs(cmd *cobra.Command, args []string) (*sync.SyncOptions,
|
||||||
opts := sync.SyncOptions{
|
opts := sync.SyncOptions{
|
||||||
LocalPath: args[0],
|
LocalPath: args[0],
|
||||||
RemotePath: args[1],
|
RemotePath: args[1],
|
||||||
Full: full,
|
Full: f.full,
|
||||||
PollInterval: interval,
|
PollInterval: f.interval,
|
||||||
|
|
||||||
// We keep existing behavior for VS Code extension where if there is
|
// We keep existing behavior for VS Code extension where if there is
|
||||||
// no bundle defined, we store the snapshots in `.databricks`.
|
// no bundle defined, we store the snapshots in `.databricks`.
|
||||||
|
@ -60,13 +68,22 @@ func syncOptionsFromArgs(cmd *cobra.Command, args []string) (*sync.SyncOptions,
|
||||||
return &opts, nil
|
return &opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var syncCmd = &cobra.Command{
|
func New() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "sync [flags] SRC DST",
|
Use: "sync [flags] SRC DST",
|
||||||
Short: "Synchronize a local directory to a workspace directory",
|
Short: "Synchronize a local directory to a workspace directory",
|
||||||
Args: cobra.MaximumNArgs(2),
|
Args: cobra.MaximumNArgs(2),
|
||||||
|
}
|
||||||
|
|
||||||
// PreRunE: root.TryConfigureBundle,
|
f := syncFlags{
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
output: flags.OutputText,
|
||||||
|
}
|
||||||
|
cmd.Flags().DurationVar(&f.interval, "interval", 1*time.Second, "file system polling interval (for --watch)")
|
||||||
|
cmd.Flags().BoolVar(&f.full, "full", false, "perform full synchronization (default is incremental)")
|
||||||
|
cmd.Flags().BoolVar(&f.watch, "watch", false, "watch local file system for changes")
|
||||||
|
cmd.Flags().Var(&f.output, "output", "type of output format")
|
||||||
|
|
||||||
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
var opts *sync.SyncOptions
|
var opts *sync.SyncOptions
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -84,7 +101,7 @@ var syncCmd = &cobra.Command{
|
||||||
// }
|
// }
|
||||||
// opts, err = syncOptionsFromBundle(cmd, args, b)
|
// opts, err = syncOptionsFromBundle(cmd, args, b)
|
||||||
// } else {
|
// } else {
|
||||||
opts, err = syncOptionsFromArgs(cmd, args)
|
opts, err = f.syncOptionsFromArgs(cmd, args)
|
||||||
// }
|
// }
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -97,7 +114,7 @@ var syncCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
var outputFunc func(context.Context, <-chan sync.Event, io.Writer)
|
var outputFunc func(context.Context, <-chan sync.Event, io.Writer)
|
||||||
switch output {
|
switch f.output {
|
||||||
case flags.OutputText:
|
case flags.OutputText:
|
||||||
outputFunc = textOutput
|
outputFunc = textOutput
|
||||||
case flags.OutputJSON:
|
case flags.OutputJSON:
|
||||||
|
@ -113,7 +130,7 @@ var syncCmd = &cobra.Command{
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
if watch {
|
if f.watch {
|
||||||
err = s.RunContinuous(ctx)
|
err = s.RunContinuous(ctx)
|
||||||
} else {
|
} else {
|
||||||
err = s.RunOnce(ctx)
|
err = s.RunOnce(ctx)
|
||||||
|
@ -122,9 +139,9 @@ var syncCmd = &cobra.Command{
|
||||||
s.Close()
|
s.Close()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return err
|
return err
|
||||||
},
|
}
|
||||||
|
|
||||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
err := root.TryConfigureBundle(cmd, args)
|
err := root.TryConfigureBundle(cmd, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, cobra.ShellCompDirectiveError
|
return nil, cobra.ShellCompDirectiveError
|
||||||
|
@ -149,19 +166,7 @@ var syncCmd = &cobra.Command{
|
||||||
default:
|
default:
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// project files polling interval
|
return cmd
|
||||||
var interval time.Duration
|
|
||||||
var full bool
|
|
||||||
var watch bool
|
|
||||||
var output flags.Output = flags.OutputText
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
root.RootCmd.AddCommand(syncCmd)
|
|
||||||
syncCmd.Flags().DurationVar(&interval, "interval", 1*time.Second, "file system polling interval (for --watch)")
|
|
||||||
syncCmd.Flags().BoolVar(&full, "full", false, "perform full synchronization (default is incremental)")
|
|
||||||
syncCmd.Flags().BoolVar(&watch, "watch", false, "watch local file system for changes")
|
|
||||||
syncCmd.Flags().Var(&output, "output", "type of output format")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@ func TestSyncOptionsFromBundle(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
opts, err := syncOptionsFromBundle(syncCmd, []string{}, b)
|
f := syncFlags{}
|
||||||
|
opts, err := f.syncOptionsFromBundle(New(), []string{}, b)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, tempDir, opts.LocalPath)
|
assert.Equal(t, tempDir, opts.LocalPath)
|
||||||
assert.Equal(t, "/Users/jane@doe.com/path", opts.RemotePath)
|
assert.Equal(t, "/Users/jane@doe.com/path", opts.RemotePath)
|
||||||
|
@ -37,16 +38,18 @@ func TestSyncOptionsFromBundle(t *testing.T) {
|
||||||
|
|
||||||
func TestSyncOptionsFromArgsRequiredTwoArgs(t *testing.T) {
|
func TestSyncOptionsFromArgsRequiredTwoArgs(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
_, err = syncOptionsFromArgs(syncCmd, []string{})
|
f := syncFlags{}
|
||||||
|
_, err = f.syncOptionsFromArgs(New(), []string{})
|
||||||
require.ErrorIs(t, err, flag.ErrHelp)
|
require.ErrorIs(t, err, flag.ErrHelp)
|
||||||
_, err = syncOptionsFromArgs(syncCmd, []string{"foo"})
|
_, err = f.syncOptionsFromArgs(New(), []string{"foo"})
|
||||||
require.ErrorIs(t, err, flag.ErrHelp)
|
require.ErrorIs(t, err, flag.ErrHelp)
|
||||||
_, err = syncOptionsFromArgs(syncCmd, []string{"foo", "bar", "qux"})
|
_, err = f.syncOptionsFromArgs(New(), []string{"foo", "bar", "qux"})
|
||||||
require.ErrorIs(t, err, flag.ErrHelp)
|
require.ErrorIs(t, err, flag.ErrHelp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyncOptionsFromArgs(t *testing.T) {
|
func TestSyncOptionsFromArgs(t *testing.T) {
|
||||||
opts, err := syncOptionsFromArgs(syncCmd, []string{"/local", "/remote"})
|
f := syncFlags{}
|
||||||
|
opts, err := f.syncOptionsFromArgs(New(), []string{"/local", "/remote"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "/local", opts.LocalPath)
|
assert.Equal(t, "/local", opts.LocalPath)
|
||||||
assert.Equal(t, "/remote", opts.RemotePath)
|
assert.Equal(t, "/remote", opts.RemotePath)
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
package version
|
package version
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/databricks/cli/cmd/root"
|
|
||||||
"github.com/databricks/cli/internal/build"
|
"github.com/databricks/cli/internal/build"
|
||||||
"github.com/databricks/cli/libs/cmdio"
|
"github.com/databricks/cli/libs/cmdio"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var versionCmd = &cobra.Command{
|
func New() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
|
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"template": "Databricks CLI v{{.Version}}\n",
|
"template": "Databricks CLI v{{.Version}}\n",
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdio.Render(cmd.Context(), build.GetInfo())
|
return cmdio.Render(cmd.Context(), build.GetInfo())
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
return cmd
|
||||||
root.RootCmd.AddCommand(versionCmd)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,13 +77,6 @@ func TestSecretsPutSecretStringValue(tt *testing.T) {
|
||||||
|
|
||||||
func TestSecretsPutSecretBytesValue(tt *testing.T) {
|
func TestSecretsPutSecretBytesValue(tt *testing.T) {
|
||||||
ctx, t := acc.WorkspaceTest(tt)
|
ctx, t := acc.WorkspaceTest(tt)
|
||||||
|
|
||||||
if true {
|
|
||||||
// Uncomment below to run this test in isolation.
|
|
||||||
// To be addressed once none of the commands taint global state.
|
|
||||||
t.Skip("skipping because the test above clobbers global state")
|
|
||||||
}
|
|
||||||
|
|
||||||
scope := temporarySecretScope(ctx, t)
|
scope := temporarySecretScope(ctx, t)
|
||||||
key := "test-key"
|
key := "test-key"
|
||||||
value := []byte{0x00, 0x01, 0x02, 0x03}
|
value := []byte{0x00, 0x01, 0x02, 0x03}
|
||||||
|
|
10
main.go
10
main.go
|
@ -2,17 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/databricks/cli/cmd"
|
"github.com/databricks/cli/cmd"
|
||||||
_ "github.com/databricks/cli/cmd/account"
|
|
||||||
_ "github.com/databricks/cli/cmd/api"
|
|
||||||
_ "github.com/databricks/cli/cmd/auth"
|
|
||||||
_ "github.com/databricks/cli/cmd/bundle"
|
|
||||||
_ "github.com/databricks/cli/cmd/bundle/debug"
|
|
||||||
_ "github.com/databricks/cli/cmd/configure"
|
|
||||||
_ "github.com/databricks/cli/cmd/fs"
|
|
||||||
"github.com/databricks/cli/cmd/root"
|
"github.com/databricks/cli/cmd/root"
|
||||||
_ "github.com/databricks/cli/cmd/sync"
|
|
||||||
_ "github.com/databricks/cli/cmd/version"
|
|
||||||
_ "github.com/databricks/cli/cmd/workspace"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
Loading…
Reference in New Issue