2024-03-27 10:49:05 +00:00
|
|
|
package loader_test
|
2022-11-18 09:57:31 +00:00
|
|
|
|
|
|
|
import (
|
2022-11-28 09:59:43 +00:00
|
|
|
"context"
|
2022-11-18 09:57:31 +00:00
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
|
|
|
|
2023-05-16 16:35:39 +00:00
|
|
|
"github.com/databricks/cli/bundle"
|
|
|
|
"github.com/databricks/cli/bundle/config"
|
2024-03-27 10:49:05 +00:00
|
|
|
"github.com/databricks/cli/bundle/config/loader"
|
2024-10-07 09:16:20 +00:00
|
|
|
"github.com/databricks/cli/libs/diag"
|
|
|
|
"github.com/databricks/cli/libs/dyn"
|
2022-11-18 09:57:31 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestProcessInclude(t *testing.T) {
|
2023-11-15 14:03:36 +00:00
|
|
|
b := &bundle.Bundle{
|
2024-10-07 09:16:20 +00:00
|
|
|
BundleRootPath: "testdata/basic",
|
2022-11-28 09:59:43 +00:00
|
|
|
Config: config.Root{
|
|
|
|
Workspace: config.Workspace{
|
|
|
|
Host: "foo",
|
|
|
|
},
|
2022-11-18 09:57:31 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-09-27 10:03:05 +00:00
|
|
|
m := loader.ProcessInclude(filepath.Join(b.BundleRootPath, "host.yml"), "host.yml")
|
2024-03-27 10:49:05 +00:00
|
|
|
assert.Equal(t, "ProcessInclude(host.yml)", m.Name())
|
2022-11-18 09:57:31 +00:00
|
|
|
|
2024-03-27 10:49:05 +00:00
|
|
|
// Assert the host value prior to applying the mutator
|
2023-11-15 14:03:36 +00:00
|
|
|
assert.Equal(t, "foo", b.Config.Workspace.Host)
|
2024-03-27 10:49:05 +00:00
|
|
|
|
|
|
|
// Apply the mutator and assert that the host value has been updated
|
|
|
|
diags := bundle.Apply(context.Background(), b, m)
|
2024-03-25 14:18:47 +00:00
|
|
|
require.NoError(t, diags.Error())
|
2023-11-15 14:03:36 +00:00
|
|
|
assert.Equal(t, "bar", b.Config.Workspace.Host)
|
2022-11-18 09:57:31 +00:00
|
|
|
}
|
2024-10-07 09:16:20 +00:00
|
|
|
|
|
|
|
func TestProcessIncludeFormatMatch(t *testing.T) {
|
|
|
|
for _, fileName := range []string{
|
|
|
|
"one_job.job.yml",
|
|
|
|
"one_pipeline.pipeline.yaml",
|
|
|
|
"two_job.yml",
|
|
|
|
"job_and_pipeline.yml",
|
|
|
|
"multiple_resources.yml",
|
|
|
|
} {
|
|
|
|
t.Run(fileName, func(t *testing.T) {
|
|
|
|
b := &bundle.Bundle{
|
|
|
|
BundleRootPath: "testdata/format_match",
|
|
|
|
Config: config.Root{
|
|
|
|
Bundle: config.Bundle{
|
|
|
|
Name: "format_test",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
m := loader.ProcessInclude(filepath.Join(b.BundleRootPath, fileName), fileName)
|
|
|
|
diags := bundle.Apply(context.Background(), b, m)
|
|
|
|
assert.Empty(t, diags)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestProcessIncludeFormatNotMatch(t *testing.T) {
|
|
|
|
for fileName, expectedDiags := range map[string]diag.Diagnostics{
|
|
|
|
"single_job.pipeline.yaml": {
|
|
|
|
{
|
|
|
|
Severity: diag.Recommendation,
|
|
|
|
Summary: "define a single pipeline in a file with the .pipeline.yaml extension.",
|
|
|
|
Detail: "The following resources are defined or configured in this file:\n - job1 (job)\n",
|
|
|
|
Locations: []dyn.Location{
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/single_job.pipeline.yaml"), Line: 11, Column: 11},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/single_job.pipeline.yaml"), Line: 4, Column: 7},
|
|
|
|
},
|
|
|
|
Paths: []dyn.Path{
|
|
|
|
dyn.MustPathFromString("resources.jobs.job1"),
|
|
|
|
dyn.MustPathFromString("targets.target1.resources.jobs.job1"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"job_and_pipeline.job.yml": {
|
|
|
|
{
|
|
|
|
Severity: diag.Recommendation,
|
|
|
|
Summary: "define a single job in a file with the .job.yml extension.",
|
|
|
|
Detail: "The following resources are defined or configured in this file:\n - job1 (job)\n - pipeline1 (pipeline)\n",
|
|
|
|
Locations: []dyn.Location{
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/job_and_pipeline.job.yml"), Line: 11, Column: 11},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/job_and_pipeline.job.yml"), Line: 4, Column: 7},
|
|
|
|
},
|
|
|
|
Paths: []dyn.Path{
|
|
|
|
dyn.MustPathFromString("resources.pipelines.pipeline1"),
|
|
|
|
dyn.MustPathFromString("targets.target1.resources.jobs.job1"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"job_and_pipeline.experiment.yml": {
|
|
|
|
{
|
|
|
|
Severity: diag.Recommendation,
|
|
|
|
Summary: "define a single experiment in a file with the .experiment.yml extension.",
|
|
|
|
Detail: "The following resources are defined or configured in this file:\n - job1 (job)\n - pipeline1 (pipeline)\n",
|
|
|
|
Locations: []dyn.Location{
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/job_and_pipeline.experiment.yml"), Line: 11, Column: 11},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/job_and_pipeline.experiment.yml"), Line: 4, Column: 7},
|
|
|
|
},
|
|
|
|
Paths: []dyn.Path{
|
|
|
|
dyn.MustPathFromString("resources.pipelines.pipeline1"),
|
|
|
|
dyn.MustPathFromString("targets.target1.resources.jobs.job1"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"two_jobs.job.yml": {
|
|
|
|
{
|
|
|
|
Severity: diag.Recommendation,
|
|
|
|
Summary: "define a single job in a file with the .job.yml extension.",
|
|
|
|
Detail: "The following resources are defined or configured in this file:\n - job1 (job)\n - job2 (job)\n",
|
|
|
|
Locations: []dyn.Location{
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/two_jobs.job.yml"), Line: 4, Column: 7},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/two_jobs.job.yml"), Line: 7, Column: 7},
|
|
|
|
},
|
|
|
|
Paths: []dyn.Path{
|
|
|
|
dyn.MustPathFromString("resources.jobs.job1"),
|
|
|
|
dyn.MustPathFromString("resources.jobs.job2"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"second_job_in_target.job.yml": {
|
|
|
|
{
|
|
|
|
Severity: diag.Recommendation,
|
|
|
|
Summary: "define a single job in a file with the .job.yml extension.",
|
|
|
|
Detail: "The following resources are defined or configured in this file:\n - job1 (job)\n - job2 (job)\n",
|
|
|
|
Locations: []dyn.Location{
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/second_job_in_target.job.yml"), Line: 11, Column: 11},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/second_job_in_target.job.yml"), Line: 4, Column: 7},
|
|
|
|
},
|
|
|
|
Paths: []dyn.Path{
|
|
|
|
dyn.MustPathFromString("resources.jobs.job1"),
|
|
|
|
dyn.MustPathFromString("targets.target1.resources.jobs.job2"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"two_jobs_in_target.job.yml": {
|
|
|
|
{
|
|
|
|
Severity: diag.Recommendation,
|
|
|
|
Summary: "define a single job in a file with the .job.yml extension.",
|
|
|
|
Detail: "The following resources are defined or configured in this file:\n - job1 (job)\n - job2 (job)\n",
|
|
|
|
Locations: []dyn.Location{
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/two_jobs_in_target.job.yml"), Line: 6, Column: 11},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/two_jobs_in_target.job.yml"), Line: 8, Column: 11},
|
|
|
|
},
|
|
|
|
Paths: []dyn.Path{
|
|
|
|
dyn.MustPathFromString("targets.target1.resources.jobs.job1"),
|
|
|
|
dyn.MustPathFromString("targets.target1.resources.jobs.job2"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"multiple_resources.model_serving_endpoint.yml": {
|
|
|
|
{
|
|
|
|
Severity: diag.Recommendation,
|
|
|
|
Summary: "define a single model serving endpoint in a file with the .model_serving_endpoint.yml extension.",
|
|
|
|
Detail: `The following resources are defined or configured in this file:
|
|
|
|
- experiment1 (experiment)
|
|
|
|
- job1 (job)
|
|
|
|
- job2 (job)
|
|
|
|
- job3 (job)
|
|
|
|
- model1 (model)
|
|
|
|
- model_serving_endpoint1 (model_serving_endpoint)
|
|
|
|
- pipeline1 (pipeline)
|
|
|
|
- pipeline2 (pipeline)
|
|
|
|
- quality_monitor1 (quality_monitor)
|
|
|
|
- registered_model1 (registered_model)
|
|
|
|
- schema1 (schema)
|
|
|
|
`,
|
|
|
|
Locations: []dyn.Location{
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 12, Column: 7},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 14, Column: 7},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 18, Column: 7},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 22, Column: 7},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 24, Column: 7},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 28, Column: 7},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 35, Column: 11},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 39, Column: 11},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 43, Column: 11},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 4, Column: 7},
|
|
|
|
{File: filepath.FromSlash("testdata/format_not_match/multiple_resources.model_serving_endpoint.yml"), Line: 8, Column: 7},
|
|
|
|
},
|
|
|
|
Paths: []dyn.Path{
|
|
|
|
dyn.MustPathFromString("resources.experiments.experiment1"),
|
|
|
|
dyn.MustPathFromString("resources.jobs.job1"),
|
|
|
|
dyn.MustPathFromString("resources.jobs.job2"),
|
|
|
|
dyn.MustPathFromString("resources.model_serving_endpoints.model_serving_endpoint1"),
|
|
|
|
dyn.MustPathFromString("resources.models.model1"),
|
|
|
|
dyn.MustPathFromString("resources.pipelines.pipeline1"),
|
|
|
|
dyn.MustPathFromString("resources.pipelines.pipeline2"),
|
|
|
|
dyn.MustPathFromString("resources.schemas.schema1"),
|
|
|
|
dyn.MustPathFromString("targets.target1.resources.jobs.job3"),
|
|
|
|
dyn.MustPathFromString("targets.target1.resources.quality_monitors.quality_monitor1"),
|
|
|
|
dyn.MustPathFromString("targets.target1.resources.registered_models.registered_model1"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
t.Run(fileName, func(t *testing.T) {
|
|
|
|
b := &bundle.Bundle{
|
|
|
|
BundleRootPath: "testdata/format_not_match",
|
|
|
|
Config: config.Root{
|
|
|
|
Bundle: config.Bundle{
|
|
|
|
Name: "format_test",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
m := loader.ProcessInclude(filepath.Join(b.BundleRootPath, fileName), fileName)
|
|
|
|
diags := bundle.Apply(context.Background(), b, m)
|
|
|
|
require.Len(t, diags, 1)
|
|
|
|
assert.Equal(t, expectedDiags, diags)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|