Skip to content

Commit f699aba

Browse files
committed
propagate -var
1 parent 2141440 commit f699aba

File tree

3 files changed

+122
-2
lines changed

3 files changed

+122
-2
lines changed

cmd/bundle/deployment/migrate.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/databricks/cli/cmd/root"
1717
"github.com/databricks/cli/libs/cmdio"
1818
"github.com/databricks/cli/libs/logdiag"
19+
"github.com/databricks/cli/libs/shellquote"
1920
"github.com/databricks/cli/libs/structs/structaccess"
2021
"github.com/databricks/cli/libs/structs/structpath"
2122
"github.com/spf13/cobra"
@@ -74,25 +75,42 @@ func runPlanCheck(cmd *cobra.Command, extraArgs []string, extraArgsStr string) e
7475

7576
func getCommonArgs(cmd *cobra.Command) ([]string, string) {
7677
var args []string
78+
var quotedArgs []string
79+
7780
if flag := cmd.Flag("target"); flag != nil && flag.Changed {
7881
target := flag.Value.String()
7982
if target != "" {
8083
args = append(args, "-t")
8184
args = append(args, target)
85+
quotedArgs = append(quotedArgs, "-t")
86+
quotedArgs = append(quotedArgs, shellquote.BashArg(target))
8287
}
8388
}
8489
if flag := cmd.Flag("profile"); flag != nil && flag.Changed {
8590
profile := flag.Value.String()
8691
if profile != "" {
8792
args = append(args, "-p")
8893
args = append(args, profile)
94+
quotedArgs = append(quotedArgs, "-p")
95+
quotedArgs = append(quotedArgs, shellquote.BashArg(profile))
96+
}
97+
}
98+
if flag := cmd.Flag("var"); flag != nil && flag.Changed {
99+
varValues, err := cmd.Flags().GetStringSlice("var")
100+
if err == nil {
101+
for _, v := range varValues {
102+
args = append(args, "--var")
103+
args = append(args, v)
104+
quotedArgs = append(quotedArgs, "--var")
105+
quotedArgs = append(quotedArgs, shellquote.BashArg(v))
106+
}
89107
}
90108
}
91109

92110
argsStr := ""
93111

94-
if len(args) > 0 {
95-
argsStr = " " + strings.Join(args, " ")
112+
if len(quotedArgs) > 0 {
113+
argsStr = " " + strings.Join(quotedArgs, " ")
96114
}
97115

98116
return args, argsStr

libs/shellquote/quote.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package shellquote
2+
3+
import (
4+
"strings"
5+
)
6+
7+
// BashArg quotes a string for safe use as a bash command argument.
8+
// It returns the argument unquoted if it contains only safe characters,
9+
// otherwise it wraps it in single quotes and escapes any single quotes within.
10+
func BashArg(s string) string {
11+
if s == "" {
12+
return "''"
13+
}
14+
15+
// Check if string needs quoting
16+
needsQuoting := false
17+
for _, c := range s {
18+
if !isSafeChar(c) {
19+
needsQuoting = true
20+
break
21+
}
22+
}
23+
24+
if !needsQuoting {
25+
return s
26+
}
27+
28+
// Use single quotes and escape any single quotes in the string
29+
// by ending the quote, adding an escaped quote, and starting a new quote
30+
return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
31+
}
32+
33+
// isSafeChar returns true if the character is safe to use unquoted in bash.
34+
func isSafeChar(c rune) bool {
35+
return (c >= 'a' && c <= 'z') ||
36+
(c >= 'A' && c <= 'Z') ||
37+
(c >= '0' && c <= '9') ||
38+
c == '-' || c == '_' || c == '/' || c == '.' || c == ':'
39+
}

libs/shellquote/quote_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package shellquote
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestBashArg(t *testing.T) {
10+
tests := []struct {
11+
input string
12+
expected string
13+
}{
14+
// Simple cases - no quoting needed
15+
{"hello", "hello"},
16+
{"hello-world", "hello-world"},
17+
{"hello_world", "hello_world"},
18+
{"path/to/file", "path/to/file"},
19+
{"file.txt", "file.txt"},
20+
{"host:port", "host:port"},
21+
{"123", "123"},
22+
{"a1b2c3", "a1b2c3"},
23+
24+
// Empty string
25+
{"", "''"},
26+
27+
// Cases requiring quoting - spaces
28+
{"hello world", "'hello world'"},
29+
{"Custom Job Name", "'Custom Job Name'"},
30+
31+
// Cases requiring quoting - special characters
32+
{"job_name=Custom Job Name", "'job_name=Custom Job Name'"},
33+
{"foo=bar", "'foo=bar'"},
34+
{"a b c", "'a b c'"},
35+
{"*", "'*'"},
36+
{"$VAR", "'$VAR'"},
37+
{"a|b", "'a|b'"},
38+
{"a&b", "'a&b'"},
39+
{"a;b", "'a;b'"},
40+
{"a>b", "'a>b'"},
41+
{"a<b", "'a<b'"},
42+
{"a(b)", "'a(b)'"},
43+
{"a[b]", "'a[b]'"},
44+
{"a{b}", "'a{b}'"},
45+
{"a`b`", "'a`b`'"},
46+
{"a\\b", "'a\\b'"},
47+
{"a\"b\"", `'a"b"'`},
48+
49+
// Single quotes in string
50+
{"it's", `'it'\''s'`},
51+
{"can't", `'can'\''t'`},
52+
{"'", `''\'''`},
53+
{"''", `''\'''\'''`},
54+
{"a'b'c", `'a'\''b'\''c'`},
55+
}
56+
57+
for _, tt := range tests {
58+
t.Run(tt.input, func(t *testing.T) {
59+
result := BashArg(tt.input)
60+
assert.Equal(t, tt.expected, result)
61+
})
62+
}
63+
}

0 commit comments

Comments
 (0)