mirror of https://github.com/databricks/cli.git
Rename mutator
This commit is contained in:
parent
0301854a43
commit
b63e94366a
|
@ -0,0 +1,70 @@
|
||||||
|
package mutator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/databricks/cli/bundle"
|
||||||
|
"github.com/databricks/cli/libs/diag"
|
||||||
|
"github.com/databricks/cli/libs/dyn"
|
||||||
|
)
|
||||||
|
|
||||||
|
type configureDashboardDefaults struct{}
|
||||||
|
|
||||||
|
func ConfigureDashboardDefaults() bundle.Mutator {
|
||||||
|
return &configureDashboardDefaults{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *configureDashboardDefaults) Name() string {
|
||||||
|
return "ConfigureDashboardDefaults"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *configureDashboardDefaults) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
|
||||||
|
var diags diag.Diagnostics
|
||||||
|
|
||||||
|
pattern := dyn.NewPattern(
|
||||||
|
dyn.Key("resources"),
|
||||||
|
dyn.Key("dashboards"),
|
||||||
|
dyn.AnyKey(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Configure defaults for all dashboards.
|
||||||
|
err := b.Config.Mutate(func(v dyn.Value) (dyn.Value, error) {
|
||||||
|
return dyn.MapByPattern(v, pattern, func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
|
||||||
|
var err error
|
||||||
|
v, err = setIfNotExists(v, dyn.NewPath(dyn.Key("parent_path")), dyn.V(b.Config.Workspace.ResourcePath))
|
||||||
|
if err != nil {
|
||||||
|
return dyn.InvalidValue, err
|
||||||
|
}
|
||||||
|
v, err = setIfNotExists(v, dyn.NewPath(dyn.Key("embed_credentials")), dyn.V(false))
|
||||||
|
if err != nil {
|
||||||
|
return dyn.InvalidValue, err
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
diags = diags.Extend(diag.FromErr(err))
|
||||||
|
return diags
|
||||||
|
}
|
||||||
|
|
||||||
|
func setIfNotExists(v dyn.Value, path dyn.Path, defaultValue dyn.Value) (dyn.Value, error) {
|
||||||
|
// Get the field at the specified path (if set).
|
||||||
|
_, err := dyn.GetByPath(v, path)
|
||||||
|
switch {
|
||||||
|
case dyn.IsNoSuchKeyError(err):
|
||||||
|
// OK, we'll set the default value.
|
||||||
|
break
|
||||||
|
case dyn.IsCannotTraverseNilError(err):
|
||||||
|
// Cannot traverse the value, skip it.
|
||||||
|
return v, nil
|
||||||
|
case err == nil:
|
||||||
|
// The field is set, skip it.
|
||||||
|
return v, nil
|
||||||
|
default:
|
||||||
|
// Return the error.
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the field at the specified path.
|
||||||
|
return dyn.SetByPath(v, path, defaultValue)
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
package mutator_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/databricks/cli/bundle"
|
||||||
|
"github.com/databricks/cli/bundle/config"
|
||||||
|
"github.com/databricks/cli/bundle/config/mutator"
|
||||||
|
"github.com/databricks/cli/bundle/config/resources"
|
||||||
|
"github.com/databricks/cli/bundle/internal/bundletest"
|
||||||
|
"github.com/databricks/cli/libs/dyn"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfigureDashboardDefaultsParentPath(t *testing.T) {
|
||||||
|
b := &bundle.Bundle{
|
||||||
|
Config: config.Root{
|
||||||
|
Workspace: config.Workspace{
|
||||||
|
ResourcePath: "/foo/bar",
|
||||||
|
},
|
||||||
|
Resources: config.Resources{
|
||||||
|
Dashboards: map[string]*resources.Dashboard{
|
||||||
|
"d1": {
|
||||||
|
// Empty string is skipped.
|
||||||
|
// See below for how it is set.
|
||||||
|
ParentPath: "",
|
||||||
|
},
|
||||||
|
"d2": {
|
||||||
|
// Non-empty string is skipped.
|
||||||
|
ParentPath: "already-set",
|
||||||
|
},
|
||||||
|
"d3": {
|
||||||
|
// No parent path set.
|
||||||
|
},
|
||||||
|
"d4": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can't set an empty string in the typed configuration.
|
||||||
|
// Do it on the dyn.Value directly.
|
||||||
|
bundletest.Mutate(t, b, func(v dyn.Value) (dyn.Value, error) {
|
||||||
|
return dyn.Set(v, "resources.dashboards.d1.parent_path", dyn.V(""))
|
||||||
|
})
|
||||||
|
|
||||||
|
diags := bundle.Apply(context.Background(), b, mutator.ConfigureDashboardDefaults())
|
||||||
|
require.NoError(t, diags.Error())
|
||||||
|
|
||||||
|
var v dyn.Value
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Set to empty string; unchanged.
|
||||||
|
v, err = dyn.Get(b.Config.Value(), "resources.dashboards.d1.parent_path")
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.Equal(t, "", v.MustString())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to "already-set"; unchanged.
|
||||||
|
v, err = dyn.Get(b.Config.Value(), "resources.dashboards.d2.parent_path")
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.Equal(t, "already-set", v.MustString())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not set; now set to the workspace resource path.
|
||||||
|
v, err = dyn.Get(b.Config.Value(), "resources.dashboards.d3.parent_path")
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.Equal(t, "/foo/bar", v.MustString())
|
||||||
|
}
|
||||||
|
|
||||||
|
// No valid dashboard; no change.
|
||||||
|
_, err = dyn.Get(b.Config.Value(), "resources.dashboards.d4.parent_path")
|
||||||
|
assert.True(t, dyn.IsCannotTraverseNilError(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigureDashboardDefaultsEmbedCredentials(t *testing.T) {
|
||||||
|
b := &bundle.Bundle{
|
||||||
|
Config: config.Root{
|
||||||
|
Resources: config.Resources{
|
||||||
|
Dashboards: map[string]*resources.Dashboard{
|
||||||
|
"d1": {
|
||||||
|
EmbedCredentials: true,
|
||||||
|
},
|
||||||
|
"d2": {
|
||||||
|
EmbedCredentials: false,
|
||||||
|
},
|
||||||
|
"d3": {
|
||||||
|
// No parent path set.
|
||||||
|
},
|
||||||
|
"d4": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
diags := bundle.Apply(context.Background(), b, mutator.ConfigureDashboardDefaults())
|
||||||
|
require.NoError(t, diags.Error())
|
||||||
|
|
||||||
|
var v dyn.Value
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Set to true; still true.
|
||||||
|
v, err = dyn.Get(b.Config.Value(), "resources.dashboards.d1.embed_credentials")
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.Equal(t, true, v.MustBool())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to false; still false.
|
||||||
|
v, err = dyn.Get(b.Config.Value(), "resources.dashboards.d2.embed_credentials")
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.Equal(t, false, v.MustBool())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not set; now false.
|
||||||
|
v, err = dyn.Get(b.Config.Value(), "resources.dashboards.d3.embed_credentials")
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.Equal(t, false, v.MustBool())
|
||||||
|
}
|
||||||
|
|
||||||
|
// No valid dashboard; no change.
|
||||||
|
_, err = dyn.Get(b.Config.Value(), "resources.dashboards.d4.embed_credentials")
|
||||||
|
assert.True(t, dyn.IsCannotTraverseNilError(err))
|
||||||
|
}
|
|
@ -1,62 +0,0 @@
|
||||||
package mutator
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/databricks/cli/bundle"
|
|
||||||
"github.com/databricks/cli/libs/diag"
|
|
||||||
"github.com/databricks/cli/libs/dyn"
|
|
||||||
)
|
|
||||||
|
|
||||||
type configureDefaultParentPath struct{}
|
|
||||||
|
|
||||||
func ConfigureDefaultParentPath() bundle.Mutator {
|
|
||||||
return &configureDefaultParentPath{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *configureDefaultParentPath) Name() string {
|
|
||||||
return "ConfigureDefaultParentPath"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *configureDefaultParentPath) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
|
|
||||||
var diags diag.Diagnostics
|
|
||||||
|
|
||||||
pattern := dyn.NewPattern(
|
|
||||||
dyn.Key("resources"),
|
|
||||||
dyn.Key("dashboards"),
|
|
||||||
dyn.AnyKey(),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Default value for the parent path.
|
|
||||||
defaultValue := b.Config.Workspace.ResourcePath
|
|
||||||
|
|
||||||
// Configure the default parent path for all dashboards.
|
|
||||||
err := b.Config.Mutate(func(v dyn.Value) (dyn.Value, error) {
|
|
||||||
return dyn.MapByPattern(v, pattern, func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
|
|
||||||
// Get the current parent path (if set).
|
|
||||||
f, err := dyn.Get(v, "parent_path")
|
|
||||||
switch {
|
|
||||||
case dyn.IsNoSuchKeyError(err):
|
|
||||||
// OK, we'll set the default value.
|
|
||||||
break
|
|
||||||
case dyn.IsCannotTraverseNilError(err):
|
|
||||||
// Cannot traverse the value, skip it.
|
|
||||||
return v, nil
|
|
||||||
default:
|
|
||||||
// Return the error.
|
|
||||||
return v, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the default value (if not set).
|
|
||||||
if !f.IsValid() {
|
|
||||||
f = dyn.V(defaultValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the parent path.
|
|
||||||
return dyn.Set(v, "parent_path", f)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
diags = diags.Extend(diag.FromErr(err))
|
|
||||||
return diags
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
package mutator_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/databricks/cli/bundle"
|
|
||||||
"github.com/databricks/cli/bundle/config"
|
|
||||||
"github.com/databricks/cli/bundle/config/mutator"
|
|
||||||
"github.com/databricks/cli/bundle/config/resources"
|
|
||||||
"github.com/databricks/cli/bundle/internal/bundletest"
|
|
||||||
"github.com/databricks/cli/libs/dyn"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestConfigureDefaultParentPath(t *testing.T) {
|
|
||||||
b := &bundle.Bundle{
|
|
||||||
Config: config.Root{
|
|
||||||
Workspace: config.Workspace{
|
|
||||||
ResourcePath: "/foo/bar",
|
|
||||||
},
|
|
||||||
Resources: config.Resources{
|
|
||||||
Dashboards: map[string]*resources.Dashboard{
|
|
||||||
"d1": {
|
|
||||||
// Empty string is skipped.
|
|
||||||
// See below for how it is set.
|
|
||||||
ParentPath: "",
|
|
||||||
},
|
|
||||||
"d2": {
|
|
||||||
// Non-empty string is skipped.
|
|
||||||
ParentPath: "already-set",
|
|
||||||
},
|
|
||||||
"d3": {
|
|
||||||
// No parent path set.
|
|
||||||
},
|
|
||||||
"d4": nil,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can't set an empty string in the typed configuration.
|
|
||||||
// Do it on the dyn.Value directly.
|
|
||||||
bundletest.Mutate(t, b, func(v dyn.Value) (dyn.Value, error) {
|
|
||||||
return dyn.Set(v, "resources.dashboards.d1.parent_path", dyn.V(""))
|
|
||||||
})
|
|
||||||
|
|
||||||
diags := bundle.Apply(context.Background(), b, mutator.ConfigureDefaultParentPath())
|
|
||||||
require.NoError(t, diags.Error())
|
|
||||||
|
|
||||||
assert.Equal(t, "", b.Config.Resources.Dashboards["d1"].ParentPath)
|
|
||||||
assert.Equal(t, "already-set", b.Config.Resources.Dashboards["d2"].ParentPath)
|
|
||||||
assert.Equal(t, "/foo/bar", b.Config.Resources.Dashboards["d3"].ParentPath)
|
|
||||||
assert.Nil(t, b.Config.Resources.Dashboards["d4"])
|
|
||||||
}
|
|
|
@ -57,7 +57,7 @@ func Initialize() bundle.Mutator {
|
||||||
),
|
),
|
||||||
mutator.SetRunAs(),
|
mutator.SetRunAs(),
|
||||||
mutator.OverrideCompute(),
|
mutator.OverrideCompute(),
|
||||||
mutator.ConfigureDefaultParentPath(),
|
mutator.ConfigureDashboardDefaults(),
|
||||||
mutator.ProcessTargetMode(),
|
mutator.ProcessTargetMode(),
|
||||||
mutator.ApplyPresets(),
|
mutator.ApplyPresets(),
|
||||||
mutator.DefaultQueueing(),
|
mutator.DefaultQueueing(),
|
||||||
|
|
Loading…
Reference in New Issue