2024-01-25 11:35:14 +00:00
|
|
|
package bundle
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/databricks/cli/internal"
|
2024-02-07 11:18:56 +00:00
|
|
|
"github.com/databricks/cli/internal/acc"
|
2024-01-25 11:35:14 +00:00
|
|
|
"github.com/databricks/cli/libs/filer"
|
|
|
|
"github.com/databricks/databricks-sdk-go"
|
|
|
|
"github.com/databricks/databricks-sdk-go/service/pipelines"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestAccGenerateFromExistingPipelineAndDeploy(t *testing.T) {
|
2024-02-07 11:18:56 +00:00
|
|
|
ctx, wt := acc.WorkspaceTest(t)
|
|
|
|
gt := &generatePipelineTest{T: t, w: wt.W}
|
2024-01-25 11:35:14 +00:00
|
|
|
|
|
|
|
uniqueId := uuid.New().String()
|
2024-02-07 11:18:56 +00:00
|
|
|
bundleRoot, err := initTestTemplate(t, ctx, "with_includes", map[string]any{
|
2024-01-25 11:35:14 +00:00
|
|
|
"unique_id": uniqueId,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-02-14 18:04:45 +00:00
|
|
|
pipelineId, name := gt.createTestPipeline(ctx)
|
2024-01-25 11:35:14 +00:00
|
|
|
t.Cleanup(func() {
|
2024-02-07 11:18:56 +00:00
|
|
|
gt.destroyPipeline(ctx, pipelineId)
|
2024-01-25 11:35:14 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Setenv("BUNDLE_ROOT", bundleRoot)
|
2024-02-07 11:18:56 +00:00
|
|
|
c := internal.NewCobraTestRunnerWithContext(t, ctx, "bundle", "generate", "pipeline",
|
2024-01-25 11:35:14 +00:00
|
|
|
"--existing-pipeline-id", fmt.Sprint(pipelineId),
|
|
|
|
"--config-dir", filepath.Join(bundleRoot, "resources"),
|
|
|
|
"--source-dir", filepath.Join(bundleRoot, "src"))
|
|
|
|
_, _, err = c.Run()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = os.Stat(filepath.Join(bundleRoot, "src", "notebook.py"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = os.Stat(filepath.Join(bundleRoot, "src", "test.py"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-01-31 10:23:35 +00:00
|
|
|
matches, err := filepath.Glob(filepath.Join(bundleRoot, "resources", "generated_pipeline_*.yml"))
|
2024-01-25 11:35:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, matches, 1)
|
|
|
|
|
|
|
|
// check the content of generated yaml
|
2024-02-14 18:04:45 +00:00
|
|
|
fileName := matches[0]
|
|
|
|
data, err := os.ReadFile(fileName)
|
2024-01-25 11:35:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
generatedYaml := string(data)
|
2024-02-14 18:04:45 +00:00
|
|
|
|
|
|
|
// Replace pipeline name
|
|
|
|
generatedYaml = strings.ReplaceAll(generatedYaml, name, internal.RandomName("copy-generated-pipeline-"))
|
|
|
|
err = os.WriteFile(fileName, []byte(generatedYaml), 0644)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-01-25 11:35:14 +00:00
|
|
|
require.Contains(t, generatedYaml, "libraries:")
|
|
|
|
require.Contains(t, generatedYaml, "- notebook:")
|
|
|
|
require.Contains(t, generatedYaml, fmt.Sprintf("path: %s", filepath.Join("..", "src", "notebook.py")))
|
|
|
|
require.Contains(t, generatedYaml, "- file:")
|
|
|
|
require.Contains(t, generatedYaml, fmt.Sprintf("path: %s", filepath.Join("..", "src", "test.py")))
|
|
|
|
|
2024-02-07 11:18:56 +00:00
|
|
|
err = deployBundle(t, ctx, bundleRoot)
|
2024-01-25 11:35:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-02-07 11:18:56 +00:00
|
|
|
err = destroyBundle(t, ctx, bundleRoot)
|
2024-01-25 11:35:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2024-02-07 11:18:56 +00:00
|
|
|
type generatePipelineTest struct {
|
|
|
|
T *testing.T
|
|
|
|
w *databricks.WorkspaceClient
|
|
|
|
}
|
|
|
|
|
2024-02-14 18:04:45 +00:00
|
|
|
func (gt *generatePipelineTest) createTestPipeline(ctx context.Context) (string, string) {
|
2024-02-07 11:18:56 +00:00
|
|
|
t := gt.T
|
|
|
|
w := gt.w
|
2024-01-25 11:35:14 +00:00
|
|
|
|
|
|
|
tmpdir := internal.TemporaryWorkspaceDir(t, w)
|
|
|
|
f, err := filer.NewWorkspaceFilesClient(w, tmpdir)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = f.Write(ctx, "notebook.py", strings.NewReader("# Databricks notebook source\nprint('Hello world!'))"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = f.Write(ctx, "test.py", strings.NewReader("print('Hello!')"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-02-15 15:03:19 +00:00
|
|
|
env := internal.GetEnvOrSkipTest(t, "CLOUD_ENV")
|
|
|
|
nodeTypeId := internal.GetNodeTypeId(env)
|
|
|
|
|
2024-02-14 18:04:45 +00:00
|
|
|
name := internal.RandomName("generated-pipeline-")
|
2024-01-25 11:35:14 +00:00
|
|
|
resp, err := w.Pipelines.Create(ctx, pipelines.CreatePipeline{
|
2024-02-14 18:04:45 +00:00
|
|
|
Name: name,
|
2024-01-25 11:35:14 +00:00
|
|
|
Libraries: []pipelines.PipelineLibrary{
|
|
|
|
{
|
|
|
|
Notebook: &pipelines.NotebookLibrary{
|
|
|
|
Path: path.Join(tmpdir, "notebook"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
File: &pipelines.FileLibrary{
|
|
|
|
Path: path.Join(tmpdir, "test.py"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-02-15 15:03:19 +00:00
|
|
|
Clusters: []pipelines.PipelineCluster{
|
|
|
|
{
|
|
|
|
CustomTags: map[string]string{
|
|
|
|
"Tag1": "Yes",
|
|
|
|
"Tag2": "24X7",
|
|
|
|
"Tag3": "APP-1234",
|
|
|
|
},
|
|
|
|
NodeTypeId: nodeTypeId,
|
|
|
|
NumWorkers: 2,
|
|
|
|
SparkConf: map[string]string{
|
|
|
|
"spark.databricks.enableWsfs": "true",
|
|
|
|
"spark.databricks.hive.metastore.glueCatalog.enabled": "true",
|
|
|
|
"spark.databricks.pip.ignoreSSL": "true",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-01-25 11:35:14 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2024-02-14 18:04:45 +00:00
|
|
|
return resp.PipelineId, name
|
2024-01-25 11:35:14 +00:00
|
|
|
}
|
|
|
|
|
2024-02-07 11:18:56 +00:00
|
|
|
func (gt *generatePipelineTest) destroyPipeline(ctx context.Context, pipelineId string) {
|
|
|
|
err := gt.w.Pipelines.Delete(ctx, pipelines.DeletePipelineRequest{
|
2024-01-25 11:35:14 +00:00
|
|
|
PipelineId: pipelineId,
|
|
|
|
})
|
2024-02-07 11:18:56 +00:00
|
|
|
require.NoError(gt.T, err)
|
2024-01-25 11:35:14 +00:00
|
|
|
}
|