Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 214
Add NewPatternFromString and bundle.SetDefault; use it for volumes & dashboards#2734
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
7381948a68e3df9371ce2d7e75a8fd131c17705c68437db7415719eb88cd57ad738ef7bd83eda2ca2a38370e0331f4a9e7File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package bundle | ||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "github.com/databricks/cli/libs/diag" | ||
| "github.com/databricks/cli/libs/dyn" | ||
| ) | ||
| type setDefault struct { | ||
| pattern dyn.Pattern | ||
| key dyn.Path | ||
| value any | ||
| } | ||
| func SetDefaultMutator(pattern dyn.Pattern, key string, value any) Mutator { | ||
| return &setDefault{ | ||
| pattern: pattern, | ||
| key: dyn.NewPath(dyn.Key(key)), | ||
| value: value, | ||
| } | ||
| } | ||
| func (m *setDefault) Name() string { | ||
| return fmt.Sprintf("SetDefaultMutator(%v, %v, %v)", m.pattern, m.key, m.value) | ||
| } | ||
| func (m *setDefault) Apply(ctx context.Context, b *Bundle) diag.Diagnostics { | ||
| err := b.Config.Mutate(func(v dyn.Value) (dyn.Value, error) { | ||
| return dyn.MapByPattern(v, m.pattern, func(p dyn.Path, v dyn.Value) (dyn.Value, error) { | ||
| _, err := dyn.GetByPath(v, m.key) | ||
| switch { | ||
| case dyn.IsNoSuchKeyError(err): | ||
| return dyn.SetByPath(v, m.key, dyn.V(m.value)) | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I now see the path is guaranteed to have a single component. Then it always works. | ||
| default: | ||
| return v, err | ||
| } | ||
| }) | ||
| }) | ||
| if err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| return nil | ||
| } | ||
| func SetDefault(ctx context.Context, b *Bundle, pattern string, value any) diag.Diagnostics { | ||
| pat, err := dyn.NewPatternFromString(pattern) | ||
| if err != nil { | ||
| return diag.FromErr(fmt.Errorf("Internal error: invalid pattern: %s: %w", pattern, err)) | ||
| } | ||
| pat, key := pat.SplitKey() | ||
| if pat == nil || key == "" { | ||
| return diag.FromErr(fmt.Errorf("Internal error: invalid pattern: %s", pattern)) | ||
| } | ||
denik marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| m := SetDefaultMutator(pat, key, value) | ||
| return Apply(ctx, b, m) | ||
denik marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -88,6 +88,21 @@ func TestNewPathFromString(t *testing.T) { | ||
| input: "foo[1]bar", | ||
| err: errors.New("invalid path: foo[1]bar"), | ||
| }, | ||
| { | ||
| // * is parsed as regular string in NewPathFromString | ||
| input: "foo.*", | ||
denik marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| output: NewPath(Key("foo"), Key("*")), | ||
| }, | ||
| { | ||
| // * is parsed as regular string in NewPathFromString | ||
| input: "foo.*.bar", | ||
| output: NewPath(Key("foo"), Key("*"), Key("bar")), | ||
| }, | ||
| { | ||
| // This is an invalid path (but would be valid for patterns) | ||
| input: "foo[*].bar", | ||
| err: errors.New("invalid path: foo[*].bar"), | ||
| }, | ||
| } { | ||
| p, err := NewPathFromString(tc.input) | ||
| if tc.err != nil { | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| package dyn | ||
| import ( | ||
| "fmt" | ||
| "strconv" | ||
| "strings" | ||
| ) | ||
| // MustPatternFromString is like NewPatternFromString but panics on error. | ||
| func MustPatternFromString(input string) Pattern { | ||
| p, err := NewPatternFromString(input) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| return p | ||
| } | ||
| // NewPatternFromString parses a pattern from a string. | ||
| // | ||
| // The string must be a sequence of keys and indices separated by dots. | ||
| // Indices must be enclosed in square brackets. | ||
| // The string may include a leading dot. | ||
| // The wildcard character '*' can be used to match any key or index. | ||
| // | ||
| // Examples: | ||
| // - foo.bar | ||
| // - foo[1].bar | ||
| // - foo.*.bar | ||
| // - foo[*].bar | ||
denik marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| // - . | ||
| func NewPatternFromString(input string) (Pattern, error) { | ||
| var pattern Pattern | ||
| p := input | ||
| // Trim leading dot. | ||
| if p != "" && p[0] == '.' { | ||
| p = p[1:] | ||
| } | ||
| for p != "" { | ||
| // Every component may have a leading dot. | ||
| if p[0] == '.' { | ||
| p = p[1:] | ||
| } | ||
| if p == "" { | ||
| return nil, fmt.Errorf("invalid pattern: %s", input) | ||
| } | ||
| if p[0] == '[' { | ||
| // Find next ] | ||
| i := strings.Index(p, "]") | ||
| if i < 0 { | ||
| return nil, fmt.Errorf("invalid pattern: %s", input) | ||
| } | ||
| // Check for wildcard | ||
| if p[1:i] == "*" { | ||
| pattern = append(pattern, AnyIndex()) | ||
| } else { | ||
| // Parse index | ||
| j, err := strconv.Atoi(p[1:i]) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("invalid pattern: %s", input) | ||
| } | ||
| // Append index | ||
| pattern = append(pattern, Index(j)) | ||
| } | ||
| p = p[i+1:] | ||
| // The next character must be a . or [ | ||
| if p != "" && strings.IndexAny(p, ".[") != 0 { | ||
| return nil, fmt.Errorf("invalid pattern: %s", input) | ||
| } | ||
| } else { | ||
| // Find next . or [ | ||
| i := strings.IndexAny(p, ".[") | ||
| if i < 0 { | ||
| i = len(p) | ||
| } | ||
| if i == 0 { | ||
| return nil, fmt.Errorf("invalid pattern: %s", input) | ||
| } | ||
| // Check for wildcard | ||
| if p[:i] == "*" { | ||
| pattern = append(pattern, AnyKey()) | ||
| } else { | ||
| // Append key | ||
| pattern = append(pattern, Key(p[:i])) | ||
| } | ||
| p = p[i:] | ||
| } | ||
| } | ||
| return pattern, nil | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.