mirror of https://github.com/databricks/cli.git
Allow multiple lookup functions for interpolation (#128)
This commit is contained in:
parent
3f8e233a18
commit
94a86972e5
|
@ -2,6 +2,7 @@ package interpolation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -39,16 +40,23 @@ func (s *stringField) dependsOn() []string {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringField) interpolate(fn LookupFunction, lookup map[string]string) {
|
func (s *stringField) interpolate(fns []LookupFunction, lookup map[string]string) {
|
||||||
out := re.ReplaceAllStringFunc(s.Get(), func(s string) string {
|
out := re.ReplaceAllStringFunc(s.Get(), func(s string) string {
|
||||||
// Turn the whole match into the submatch.
|
// Turn the whole match into the submatch.
|
||||||
match := re.FindStringSubmatch(s)
|
match := re.FindStringSubmatch(s)
|
||||||
v, err := fn(match[1], lookup)
|
for _, fn := range fns {
|
||||||
if err != nil {
|
v, err := fn(match[1], lookup)
|
||||||
panic(err)
|
if errors.Is(err, ErrSkipInterpolation) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
return v
|
// No substitution.
|
||||||
|
return s
|
||||||
})
|
})
|
||||||
|
|
||||||
s.Set(out)
|
s.Set(out)
|
||||||
|
@ -163,7 +171,7 @@ func (a *accumulator) start(v any) {
|
||||||
a.walk([]string{}, rv, nilSetter{})
|
a.walk([]string{}, rv, nilSetter{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *accumulator) expand(fn LookupFunction) error {
|
func (a *accumulator) expand(fns ...LookupFunction) error {
|
||||||
for path, v := range a.strings {
|
for path, v := range a.strings {
|
||||||
ds := v.dependsOn()
|
ds := v.dependsOn()
|
||||||
if len(ds) == 0 {
|
if len(ds) == 0 {
|
||||||
|
@ -176,24 +184,24 @@ func (a *accumulator) expand(fn LookupFunction) error {
|
||||||
return fmt.Errorf("cannot interpolate %s: %w", path, err)
|
return fmt.Errorf("cannot interpolate %s: %w", path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.interpolate(fn, m)
|
v.interpolate(fns, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type interpolate struct {
|
type interpolate struct {
|
||||||
fn LookupFunction
|
fns []LookupFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *interpolate) expand(v any) error {
|
func (m *interpolate) expand(v any) error {
|
||||||
a := accumulator{}
|
a := accumulator{}
|
||||||
a.start(v)
|
a.start(v)
|
||||||
return a.expand(m.fn)
|
return a.expand(m.fns...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Interpolate(fn LookupFunction) bundle.Mutator {
|
func Interpolate(fns ...LookupFunction) bundle.Mutator {
|
||||||
return &interpolate{fn: fn}
|
return &interpolate{fns: fns}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *interpolate) Name() string {
|
func (m *interpolate) Name() string {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package interpolation
|
package interpolation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -10,6 +11,9 @@ import (
|
||||||
// LookupFunction returns the value to rewrite a path expression to.
|
// LookupFunction returns the value to rewrite a path expression to.
|
||||||
type LookupFunction func(path string, depends map[string]string) (string, error)
|
type LookupFunction func(path string, depends map[string]string) (string, error)
|
||||||
|
|
||||||
|
// ErrSkipInterpolation can be used to fall through from [LookupFunction].
|
||||||
|
var ErrSkipInterpolation = errors.New("skip interpolation")
|
||||||
|
|
||||||
// DefaultLookup looks up the specified path in the map.
|
// DefaultLookup looks up the specified path in the map.
|
||||||
// It returns an error if it doesn't exist.
|
// It returns an error if it doesn't exist.
|
||||||
func DefaultLookup(path string, lookup map[string]string) (string, error) {
|
func DefaultLookup(path string, lookup map[string]string) (string, error) {
|
||||||
|
@ -29,7 +33,7 @@ func pathPrefixMatches(prefix []string, path string) bool {
|
||||||
func ExcludeLookupsInPath(exclude ...string) LookupFunction {
|
func ExcludeLookupsInPath(exclude ...string) LookupFunction {
|
||||||
return func(path string, lookup map[string]string) (string, error) {
|
return func(path string, lookup map[string]string) (string, error) {
|
||||||
if pathPrefixMatches(exclude, path) {
|
if pathPrefixMatches(exclude, path) {
|
||||||
return fmt.Sprintf("${%s}", path), nil
|
return "", ErrSkipInterpolation
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefaultLookup(path, lookup)
|
return DefaultLookup(path, lookup)
|
||||||
|
@ -39,10 +43,10 @@ func ExcludeLookupsInPath(exclude ...string) LookupFunction {
|
||||||
// IncludeLookupsInPath is a lookup function that limits lookups to the specified path.
|
// IncludeLookupsInPath is a lookup function that limits lookups to the specified path.
|
||||||
func IncludeLookupsInPath(include ...string) LookupFunction {
|
func IncludeLookupsInPath(include ...string) LookupFunction {
|
||||||
return func(path string, lookup map[string]string) (string, error) {
|
return func(path string, lookup map[string]string) (string, error) {
|
||||||
if pathPrefixMatches(include, path) {
|
if !pathPrefixMatches(include, path) {
|
||||||
return DefaultLookup(path, lookup)
|
return "", ErrSkipInterpolation
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("${%s}", path), nil
|
return DefaultLookup(path, lookup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,9 @@ func fixture() interpolationFixture {
|
||||||
func TestExcludePath(t *testing.T) {
|
func TestExcludePath(t *testing.T) {
|
||||||
tmp := fixture()
|
tmp := fixture()
|
||||||
m := interpolate{
|
m := interpolate{
|
||||||
fn: ExcludeLookupsInPath("a"),
|
fns: []LookupFunction{
|
||||||
|
ExcludeLookupsInPath("a"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.expand(&tmp)
|
err := m.expand(&tmp)
|
||||||
|
@ -46,7 +48,9 @@ func TestExcludePath(t *testing.T) {
|
||||||
func TestIncludePath(t *testing.T) {
|
func TestIncludePath(t *testing.T) {
|
||||||
tmp := fixture()
|
tmp := fixture()
|
||||||
m := interpolate{
|
m := interpolate{
|
||||||
fn: IncludeLookupsInPath("a"),
|
fns: []LookupFunction{
|
||||||
|
IncludeLookupsInPath("a"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.expand(&tmp)
|
err := m.expand(&tmp)
|
||||||
|
@ -57,3 +61,21 @@ func TestIncludePath(t *testing.T) {
|
||||||
assert.Equal(t, "1", tmp.C["ax"])
|
assert.Equal(t, "1", tmp.C["ax"])
|
||||||
assert.Equal(t, "${b.x}", tmp.C["bx"])
|
assert.Equal(t, "${b.x}", tmp.C["bx"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIncludePathMultiple(t *testing.T) {
|
||||||
|
tmp := fixture()
|
||||||
|
m := interpolate{
|
||||||
|
fns: []LookupFunction{
|
||||||
|
IncludeLookupsInPath("a"),
|
||||||
|
IncludeLookupsInPath("b"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := m.expand(&tmp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, "1", tmp.A["x"])
|
||||||
|
assert.Equal(t, "2", tmp.B["x"])
|
||||||
|
assert.Equal(t, "1", tmp.C["ax"])
|
||||||
|
assert.Equal(t, "2", tmp.C["bx"])
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue