-
Notifications
You must be signed in to change notification settings - Fork 165
Expand file tree
/
Copy pathopen.go
More file actions
156 lines (130 loc) · 4.41 KB
/
open.go
File metadata and controls
156 lines (130 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copied to cmd/pipelines/open.go and adapted for pipelines use.
// Consider if changes made here should be made to the pipelines counterpart as well.
package bundle
import (
"context"
"errors"
"fmt"
"github.com/databricks/cli/bundle"
"github.com/databricks/cli/bundle/resources"
"github.com/databricks/cli/cmd/bundle/utils"
"github.com/databricks/cli/cmd/root"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/logdiag"
"github.com/spf13/cobra"
"golang.org/x/exp/maps"
"github.com/pkg/browser"
)
func promptOpenArgument(ctx context.Context, b *bundle.Bundle) (string, error) {
// Compute map of "Human readable name of resource" -> "resource key".
inv := make(map[string]string)
for k, ref := range resources.Completions(b) {
title := fmt.Sprintf("%s: %s", ref.Description.SingularTitle, ref.Resource.GetName())
inv[title] = k
}
key, err := cmdio.Select(ctx, inv, "Resource to open")
if err != nil {
return "", err
}
return key, nil
}
func resolveOpenArgument(ctx context.Context, b *bundle.Bundle, args []string) (string, error) {
// If no arguments are specified, prompt the user to select the resource to open.
if len(args) == 0 && cmdio.IsPromptSupported(ctx) {
return promptOpenArgument(ctx, b)
}
if len(args) < 1 {
return "", errors.New("expected a KEY of the resource to open")
}
arg := args[0]
// Check for an exact match first.
completions := resources.Completions(b)
if _, ok := completions[arg]; ok {
return arg, nil
}
// Check for substring matches.
matches := resources.LookupBySubstring(b, arg)
switch {
case len(matches) == 1:
return matches[0].Key, nil
case len(matches) > 1:
if cmdio.IsPromptSupported(ctx) {
// Show a filtered prompt with only matching resources.
inv := make(map[string]string)
for _, ref := range matches {
title := fmt.Sprintf("%s: %s", ref.Description.SingularTitle, ref.Resource.GetName())
inv[title] = ref.Key
}
return cmdio.Select(ctx, inv, "Resource to open")
}
// Non-interactive: return error listing candidates.
keys := make([]string, 0, len(matches))
for _, ref := range matches {
keys = append(keys, ref.Key)
}
return "", fmt.Errorf("multiple resources match %q: %v", arg, keys)
}
// No matches; return the arg as-is and let Lookup handle the "not found" error.
return arg, nil
}
func newOpenCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "open",
Short: "Open a resource in the browser",
Long: `Open a deployed bundle resource in the Databricks workspace.
Examples:
databricks bundle open # Prompts to select a resource to open
databricks bundle open my_job # Open specific job in Workflows UI
databricks bundle open my_dashboard # Open dashboard in browser
Use after deployment to quickly navigate to your resources in the workspace.`,
Args: root.MaximumNArgs(1),
}
var forcePull bool
cmd.Flags().BoolVar(&forcePull, "force-pull", false, "Skip local cache and load the state from the remote workspace")
cmd.RunE = func(cmd *cobra.Command, args []string) error {
var arg string
b, err := utils.ProcessBundle(cmd, utils.ProcessOptions{
PostInitFunc: func(ctx context.Context, b *bundle.Bundle) error {
var err error
arg, err = resolveOpenArgument(ctx, b, args)
return err
},
InitIDs: true,
})
if err != nil {
return err
}
// Locate resource to open.
ref, err := resources.Lookup(b, arg)
if err != nil {
return err
}
// Confirm that the resource has a URL.
url := ref.Resource.GetURL()
if url == "" {
return errors.New("resource does not have a URL associated with it (has it been deployed?)")
}
cmdio.LogString(cmd.Context(), "Opening browser at "+url)
return browser.OpenURL(url)
}
cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
ctx := logdiag.InitContext(cmd.Context())
cmd.SetContext(ctx)
b := root.MustConfigureBundle(cmd)
if logdiag.HasError(cmd.Context()) {
return nil, cobra.ShellCompDirectiveError
}
// No completion in the context of a bundle.
// Source and destination paths are taken from bundle configuration.
if b == nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
if len(args) == 0 {
completions := resources.Completions(b)
return maps.Keys(completions), cobra.ShellCompDirectiveNoFileComp
} else {
return nil, cobra.ShellCompDirectiveNoFileComp
}
}
return cmd
}