Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@

* Fixed `--force-pull` on `bundle summary` and `bundle open` so the flag bypasses the local state cache and reads state from the workspace.

* Replace regex-based variable interpolation with a character scanner ([#4747](https://github.com/databricks/cli/pull/4747)).

### Dependency updates
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Warning: invalid variable reference ${resources.volumes.bar.bad..syntax}: invalid path
at resources.volumes.foo.schema_name
in databricks.yml:11:21

Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Deploying resources...
Updating deployment state...
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Warning: invalid variable reference ${resources.volumes.bar.bad..syntax}: invalid path
at resources.volumes.foo.schema_name
in databricks.yml:11:21

create volumes.bar
create volumes.foo

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Warning: invalid variable reference ${resources.volumes.bar.bad..syntax}: invalid path
at resources.volumes.foo.schema_name
in databricks.yml:11:21

Error: exit status 1

Error: Invalid attribute name
Expand Down
4 changes: 4 additions & 0 deletions acceptance/bundle/resource_deps/bad_syntax/output.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@

>>> [CLI] bundle validate -o json
Warning: invalid variable reference ${resources.volumes.bar.bad..syntax}: invalid path
at resources.volumes.foo.schema_name
in databricks.yml:11:21

{
"volumes": {
"bar": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bundle:
name: '$foo is not a reference'

variables:
a:
default: hello

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

>>> [CLI] bundle validate
Name: $foo is not a reference
Target: default
Workspace:
User: [USERNAME]
Path: /Workspace/Users/[USERNAME]/.bundle/$foo is not a reference/default

Validation OK!
1 change: 1 addition & 0 deletions acceptance/bundle/variables/dollar_before_non_brace/script
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
trace $CLI bundle validate
6 changes: 6 additions & 0 deletions acceptance/bundle/variables/empty_ref/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bundle:
name: '${}'

variables:
a:
default: hello
3 changes: 3 additions & 0 deletions acceptance/bundle/variables/empty_ref/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions acceptance/bundle/variables/empty_ref/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

>>> [CLI] bundle validate
Warning: empty variable reference
at bundle.name
in databricks.yml:2:9

Name: ${}
Target: default
Workspace:
User: [USERNAME]
Path: /Workspace/Users/[USERNAME]/.bundle/${}/default

Found 1 warning
1 change: 1 addition & 0 deletions acceptance/bundle/variables/empty_ref/script
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
trace $CLI bundle validate
6 changes: 6 additions & 0 deletions acceptance/bundle/variables/leading_digit_ref/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bundle:
name: '${0foo}'

variables:
a:
default: hello
3 changes: 3 additions & 0 deletions acceptance/bundle/variables/leading_digit_ref/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions acceptance/bundle/variables/leading_digit_ref/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

>>> [CLI] bundle validate
Warning: invalid variable reference ${0foo}: invalid key "0foo"
at bundle.name
in databricks.yml:2:9

Name: ${0foo}
Target: default
Workspace:
User: [USERNAME]
Path: /Workspace/Users/[USERNAME]/.bundle/${0foo}/default

Found 1 warning
1 change: 1 addition & 0 deletions acceptance/bundle/variables/leading_digit_ref/script
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
trace $CLI bundle validate
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bundle:
name: "${foo.bar-}"

variables:
a:
default: hello
3 changes: 3 additions & 0 deletions acceptance/bundle/variables/malformed_reference/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions acceptance/bundle/variables/malformed_reference/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

>>> [CLI] bundle validate
Warning: invalid variable reference ${foo.bar-}: invalid key "bar-"
at bundle.name
in databricks.yml:2:9

Name: ${foo.bar-}
Target: default
Workspace:
User: [USERNAME]
Path: /Workspace/Users/[USERNAME]/.bundle/${foo.bar-}/default

Found 1 warning
1 change: 1 addition & 0 deletions acceptance/bundle/variables/malformed_reference/script
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
trace $CLI bundle validate
6 changes: 6 additions & 0 deletions acceptance/bundle/variables/unterminated_ref/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
bundle:
name: '${foo.bar'

variables:
a:
default: hello
3 changes: 3 additions & 0 deletions acceptance/bundle/variables/unterminated_ref/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions acceptance/bundle/variables/unterminated_ref/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

>>> [CLI] bundle validate
Warning: unterminated variable reference
at bundle.name
in databricks.yml:2:9

Name: ${foo.bar
Target: default
Workspace:
User: [USERNAME]
Path: /Workspace/Users/[USERNAME]/.bundle/${foo.bar/default

Found 1 warning
1 change: 1 addition & 0 deletions acceptance/bundle/variables/unterminated_ref/script
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
trace $CLI bundle validate
12 changes: 12 additions & 0 deletions acceptance/bundle/variables/var_in_var_3level/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
bundle:
name: test-bundle

variables:
env:
default: prod
region_prod:
default: us
endpoint_us:
default: https://us.example.com
result:
default: ${var.endpoint_${var.region_${var.env}}}
3 changes: 3 additions & 0 deletions acceptance/bundle/variables/var_in_var_3level/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions acceptance/bundle/variables/var_in_var_3level/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

>>> [CLI] bundle validate -o json
{
"endpoint_us": {
"default": "https://us.example.com",
"value": "https://us.example.com"
},
"env": {
"default": "prod",
"value": "prod"
},
"region_prod": {
"default": "us",
"value": "us"
},
"result": {
"default": "https://us.example.com",
"value": "https://us.example.com"
}
}
1 change: 1 addition & 0 deletions acceptance/bundle/variables/var_in_var_3level/script
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
trace $CLI bundle validate -o json | jq .variables
64 changes: 64 additions & 0 deletions bundle/config/mutator/warn_malformed_references.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package mutator

import (
"context"
"errors"
"slices"

"github.com/databricks/cli/bundle"
"github.com/databricks/cli/libs/diag"
"github.com/databricks/cli/libs/dyn"
"github.com/databricks/cli/libs/interpolation"
)

type warnMalformedReferences struct{}

// WarnMalformedReferences returns a mutator that emits warnings for strings
// containing malformed variable references (e.g. "${foo.bar-}").
func WarnMalformedReferences() bundle.Mutator {
return &warnMalformedReferences{}
}

func (*warnMalformedReferences) Name() string {
return "WarnMalformedReferences"
}

func (*warnMalformedReferences) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
var diags diag.Diagnostics
_, err := dyn.Walk(b.Config.Value(), func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
// Only check values with source locations to avoid false positives
// from synthesized/computed values.
if len(v.Locations()) == 0 {
return v, nil
}

s, ok := v.AsString()
if !ok {
return v, nil
}

var pe *interpolation.ParseError
if _, parseErr := interpolation.Parse(s); !errors.As(parseErr, &pe) {
return v, nil
}

// Clone locations and adjust column with the position offset
// so the diagnostic points to the problematic reference.
locs := slices.Clone(v.Locations())
if len(locs) > 0 {
locs[0].Column += pe.Pos
}

diags = append(diags, diag.Diagnostic{
Severity: diag.Warning,
Summary: pe.Msg,
Locations: locs,
Paths: []dyn.Path{p},
})
return v, nil
})
if err != nil {
diags = diags.Extend(diag.FromErr(err))
}
return diags
}
61 changes: 24 additions & 37 deletions bundle/configsync/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/databricks/cli/bundle/direct/dstate"
"github.com/databricks/cli/libs/dyn"
"github.com/databricks/cli/libs/dyn/dynvar"
"github.com/databricks/cli/libs/interpolation"
"github.com/databricks/cli/libs/log"
"github.com/databricks/cli/libs/structs/structpath"
)
Expand Down Expand Up @@ -500,50 +501,36 @@ func parseTemplateSegments(template string, resolved dyn.Value) []templateSegmen
}

var segments []templateSegment
cursor := 0

for _, m := range ref.Matches {
fullMatch := m[0]

idx := strings.Index(template[cursor:], fullMatch)
if idx < 0 {
return nil
}

if idx > 0 {
for _, tok := range ref.Tokens {
switch tok.Kind {
case interpolation.TokenLiteral:
segments = append(segments, templateSegment{
raw: template[cursor : cursor+idx],
raw: tok.Value,
})
}
case interpolation.TokenRef:
fullMatch := "${" + tok.Value + "}"
resolvedPath, ok := resolveReferencePath(fullMatch)
if !ok {
return nil
}

resolvedPath, ok := resolveReferencePath(fullMatch)
if !ok {
return nil
}
resolvedV, err := dyn.GetByPath(resolved, resolvedPath)
if err != nil {
return nil
}

resolvedV, err := dyn.GetByPath(resolved, resolvedPath)
if err != nil {
return nil
}
resolvedStr, ok := resolvedV.AsString()
if !ok {
return nil
}

resolvedStr, ok := resolvedV.AsString()
if !ok {
return nil
segments = append(segments, templateSegment{
raw: fullMatch,
isVariable: true,
resolvedValue: resolvedStr,
})
}

segments = append(segments, templateSegment{
raw: fullMatch,
isVariable: true,
resolvedValue: resolvedStr,
})

cursor += idx + len(fullMatch)
}

if cursor < len(template) {
segments = append(segments, templateSegment{
raw: template[cursor:],
})
}

return segments
Expand Down
4 changes: 4 additions & 0 deletions bundle/phases/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ func Initialize(ctx context.Context, b *bundle.Bundle) {
// searches for strings with variable references in them.
mutator.RewriteWorkspacePrefix(),

// Walks the config tree and emits warnings for malformed variable references
// (e.g. "${foo.bar-}") before variable resolution occurs.
mutator.WarnMalformedReferences(),

// Collect telemetry on $${} and \${} escape patterns before variable resolution.
mutator.CollectEscapeTelemetry(),

Expand Down
Loading
Loading