Skip to content

Commit cb7c8e3

Browse files
authored
pipelines: open command (#3223)
## Changes New `pipelines open` command to open commands in the browser. Copied from cmd/bundle/open.go ## Tests Acceptance tests copied from `acceptance/bundle/open/open`: test open only on macos
1 parent f0faa1d commit cb7c8e3

File tree

11 files changed

+232
-0
lines changed

11 files changed

+232
-0
lines changed

acceptance/pipelines/install-pipelines-cli/output.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Available Commands:
1616
destroy Destroy a pipelines project
1717
help Help about any command
1818
init Initialize a new pipelines project
19+
open Open a pipeline in the browser
1920
run Run a pipeline
2021
version Retrieve information about the current version of the Pipelines CLI
2122

@@ -57,6 +58,7 @@ Available Commands:
5758
destroy Destroy a pipelines project
5859
help Help about any command
5960
init Initialize a new pipelines project
61+
open Open a pipeline in the browser
6062
run Run a pipeline
6163
version Retrieve information about the current version of the Pipelines CLI
6264

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
bundle:
2+
name: caterpillar
3+
4+
resources:
5+
jobs:
6+
foo:
7+
name: foo
8+
tasks:
9+
- task_key: task
10+
spark_python_task:
11+
python_file: ./foo.py
12+
environment_key: default
13+
14+
environments:
15+
- environment_key: default
16+
spec:
17+
client: "2"

acceptance/pipelines/open/foo.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print(1)

acceptance/pipelines/open/open

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
echo "I AM BROWSER"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Local = true
2+
Cloud = false
3+
4+
[GOOS]
5+
linux = false
6+
windows = false
7+
8+
[EnvMatrix]
9+
DATABRICKS_CLI_DEPLOYMENT = ["terraform", "direct-exp"]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
=== no run key specified
3+
>>> [PIPELINES] open
4+
Error: expected a KEY of the pipeline to open
5+
6+
Exit code: 1
7+
8+
=== not deployed yet
9+
>>> [PIPELINES] open foo
10+
Error: pipeline does not have a URL associated with it (has it been deployed?)
11+
12+
Exit code: 1
13+
14+
>>> [PIPELINES] deploy
15+
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/caterpillar/default/files...
16+
Deploying resources...
17+
Updating deployment state...
18+
Deployment complete!
19+
20+
=== Modify PATH so that real open is not run
21+
=== open after deployment. This will fail to open browser and complain, that's ok, we only want the message
22+
>>> [PIPELINES] open foo
23+
Opening browser at [DATABRICKS_URL]/jobs/[NUMID]?o=[NUMID]
24+
Error: exec: "open": cannot run executable found relative to current directory
25+
26+
Exit code (musterr): 1

acceptance/pipelines/open/script

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
title "no run key specified"
2+
errcode trace $PIPELINES open
3+
4+
title "not deployed yet"
5+
errcode trace $PIPELINES open foo
6+
7+
errcode trace $PIPELINES deploy
8+
9+
title "Modify PATH so that real open is not run"
10+
export PATH=.:$PATH
11+
12+
title "open after deployment. This will fail to open browser and complain, that's ok, we only want the message"
13+
musterr trace $PIPELINES open foo
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GOOS.windows = false
2+
GOOS.linux = false

cmd/bundle/open.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Copied to cmd/pipelines/open.go and adapted for pipelines use.
2+
// Consider if changes made here should be made to the pipelines counterpart as well.
13
package bundle
24

35
import (

cmd/pipelines/open.go

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copied from cmd/bundle/open.go and adapted for pipelines use.
2+
// Consider if changes made here should be made to the bundle counterpart as well.
3+
package pipelines
4+
5+
import (
6+
"context"
7+
"errors"
8+
"fmt"
9+
"os"
10+
"path/filepath"
11+
12+
"github.com/databricks/cli/bundle"
13+
"github.com/databricks/cli/bundle/config/mutator"
14+
"github.com/databricks/cli/bundle/deploy/terraform"
15+
"github.com/databricks/cli/bundle/phases"
16+
"github.com/databricks/cli/bundle/resources"
17+
"github.com/databricks/cli/bundle/statemgmt"
18+
"github.com/databricks/cli/cmd/bundle/utils"
19+
"github.com/databricks/cli/cmd/root"
20+
"github.com/databricks/cli/libs/cmdio"
21+
"github.com/databricks/cli/libs/logdiag"
22+
"github.com/spf13/cobra"
23+
"golang.org/x/exp/maps"
24+
25+
"github.com/pkg/browser"
26+
)
27+
28+
func promptOpenArgument(ctx context.Context, b *bundle.Bundle) (string, error) {
29+
// Compute map of "Human readable name of resource" -> "resource key".
30+
inv := make(map[string]string)
31+
for k, ref := range resources.Completions(b) {
32+
title := fmt.Sprintf("%s: %s", ref.Description.SingularTitle, ref.Resource.GetName())
33+
inv[title] = k
34+
}
35+
36+
key, err := cmdio.Select(ctx, inv, "Pipeline to open")
37+
if err != nil {
38+
return "", err
39+
}
40+
41+
return key, nil
42+
}
43+
44+
func resolveOpenArgument(ctx context.Context, b *bundle.Bundle, args []string) (string, error) {
45+
// If no arguments are specified, prompt the user to select the resource to open.
46+
if len(args) == 0 && cmdio.IsPromptSupported(ctx) {
47+
return promptOpenArgument(ctx, b)
48+
}
49+
50+
if len(args) < 1 {
51+
return "", errors.New("expected a KEY of the pipeline to open")
52+
}
53+
54+
return args[0], nil
55+
}
56+
57+
func openCommand() *cobra.Command {
58+
cmd := &cobra.Command{
59+
Use: "open",
60+
Short: "Open a pipeline in the browser",
61+
Args: root.MaximumNArgs(1),
62+
}
63+
64+
var forcePull bool
65+
cmd.Flags().BoolVar(&forcePull, "force-pull", false, "Skip local cache and load the state from the remote workspace")
66+
67+
cmd.RunE = func(cmd *cobra.Command, args []string) error {
68+
ctx := logdiag.InitContext(cmd.Context())
69+
cmd.SetContext(ctx)
70+
71+
b := utils.ConfigureBundleWithVariables(cmd)
72+
if b == nil || logdiag.HasError(ctx) {
73+
return root.ErrAlreadyPrinted
74+
}
75+
76+
phases.Initialize(ctx, b)
77+
if logdiag.HasError(ctx) {
78+
return root.ErrAlreadyPrinted
79+
}
80+
81+
arg, err := resolveOpenArgument(ctx, b, args)
82+
if err != nil {
83+
return err
84+
}
85+
86+
cacheDir, err := terraform.Dir(ctx, b)
87+
if err != nil {
88+
return err
89+
}
90+
_, stateFileErr := os.Stat(filepath.Join(cacheDir, b.StateFilename()))
91+
_, configFileErr := os.Stat(filepath.Join(cacheDir, terraform.TerraformConfigFileName))
92+
noCache := errors.Is(stateFileErr, os.ErrNotExist) || errors.Is(configFileErr, os.ErrNotExist)
93+
94+
if forcePull || noCache {
95+
bundle.ApplyContext(ctx, b, statemgmt.StatePull())
96+
if logdiag.HasError(ctx) {
97+
return root.ErrAlreadyPrinted
98+
}
99+
100+
if !b.DirectDeployment {
101+
bundle.ApplySeqContext(ctx, b,
102+
terraform.Interpolate(),
103+
terraform.Write(),
104+
)
105+
}
106+
107+
if logdiag.HasError(ctx) {
108+
return root.ErrAlreadyPrinted
109+
}
110+
}
111+
112+
bundle.ApplySeqContext(ctx, b,
113+
statemgmt.Load(),
114+
mutator.InitializeURLs(),
115+
)
116+
if logdiag.HasError(ctx) {
117+
return root.ErrAlreadyPrinted
118+
}
119+
120+
// Locate resource to open.
121+
ref, err := resources.Lookup(b, arg)
122+
if err != nil {
123+
return err
124+
}
125+
126+
// Confirm that the resource has a URL.
127+
url := ref.Resource.GetURL()
128+
if url == "" {
129+
return errors.New("pipeline does not have a URL associated with it (has it been deployed?)")
130+
}
131+
132+
cmdio.LogString(ctx, "Opening browser at "+url)
133+
return browser.OpenURL(url)
134+
}
135+
136+
cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
137+
b := root.MustConfigureBundle(cmd)
138+
if logdiag.HasError(cmd.Context()) {
139+
return nil, cobra.ShellCompDirectiveError
140+
}
141+
142+
// No completion in the context of a bundle.
143+
// Source and destination paths are taken from bundle configuration.
144+
if b == nil {
145+
return nil, cobra.ShellCompDirectiveNoFileComp
146+
}
147+
148+
if len(args) == 0 {
149+
completions := resources.Completions(b)
150+
return maps.Keys(completions), cobra.ShellCompDirectiveNoFileComp
151+
} else {
152+
return nil, cobra.ShellCompDirectiveNoFileComp
153+
}
154+
}
155+
156+
return cmd
157+
}

0 commit comments

Comments
 (0)