2022-11-30 13:15:22 +00:00
|
|
|
package config
|
|
|
|
|
2023-07-25 11:35:08 +00:00
|
|
|
import (
|
2023-07-26 12:58:52 +00:00
|
|
|
"bytes"
|
2023-07-25 11:35:08 +00:00
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"path"
|
|
|
|
"strings"
|
|
|
|
|
2023-09-04 09:55:01 +00:00
|
|
|
"github.com/databricks/cli/bundle/config/paths"
|
2023-09-27 09:04:44 +00:00
|
|
|
"github.com/databricks/cli/libs/process"
|
2023-07-25 11:35:08 +00:00
|
|
|
"github.com/databricks/databricks-sdk-go/service/compute"
|
|
|
|
)
|
|
|
|
|
2023-09-04 09:55:01 +00:00
|
|
|
type Artifacts map[string]*Artifact
|
|
|
|
|
|
|
|
func (artifacts Artifacts) SetConfigFilePath(path string) {
|
|
|
|
for _, artifact := range artifacts {
|
|
|
|
artifact.ConfigFilePath = path
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-25 11:35:08 +00:00
|
|
|
type ArtifactType string
|
|
|
|
|
|
|
|
const ArtifactPythonWheel ArtifactType = `whl`
|
|
|
|
|
|
|
|
type ArtifactFile struct {
|
|
|
|
Source string `json:"source"`
|
|
|
|
RemotePath string `json:"-" bundle:"readonly"`
|
|
|
|
Libraries []*compute.Library `json:"-" bundle:"readonly"`
|
|
|
|
}
|
2022-11-30 13:15:22 +00:00
|
|
|
|
|
|
|
// Artifact defines a single local code artifact that can be
|
|
|
|
// built/uploaded/referenced in the context of this bundle.
|
|
|
|
type Artifact struct {
|
2023-07-25 11:35:08 +00:00
|
|
|
Type ArtifactType `json:"type"`
|
2022-11-30 13:15:22 +00:00
|
|
|
|
2023-07-25 11:35:08 +00:00
|
|
|
// The local path to the directory with a root of artifact,
|
|
|
|
// for example, where setup.py is for Python projects
|
2023-10-03 13:59:28 +00:00
|
|
|
Path string `json:"path,omitempty"`
|
2022-11-30 13:15:22 +00:00
|
|
|
|
2023-07-25 11:35:08 +00:00
|
|
|
// The relative or absolute path to the built artifact files
|
|
|
|
// (Python wheel, Java jar and etc) itself
|
2023-10-03 13:59:28 +00:00
|
|
|
Files []ArtifactFile `json:"files,omitempty"`
|
|
|
|
BuildCommand string `json:"build,omitempty"`
|
2023-09-04 09:55:01 +00:00
|
|
|
|
|
|
|
paths.Paths
|
2023-07-25 11:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Artifact) Build(ctx context.Context) ([]byte, error) {
|
|
|
|
if a.BuildCommand == "" {
|
|
|
|
return nil, fmt.Errorf("no build property defined")
|
|
|
|
}
|
|
|
|
|
2023-07-26 12:58:52 +00:00
|
|
|
out := make([][]byte, 0)
|
|
|
|
commands := strings.Split(a.BuildCommand, " && ")
|
|
|
|
for _, command := range commands {
|
|
|
|
buildParts := strings.Split(command, " ")
|
2023-09-27 09:04:44 +00:00
|
|
|
var buf bytes.Buffer
|
|
|
|
_, err := process.Background(ctx, buildParts,
|
|
|
|
process.WithCombinedOutput(&buf),
|
|
|
|
process.WithDir(a.Path))
|
2023-07-26 12:58:52 +00:00
|
|
|
if err != nil {
|
2023-09-27 09:04:44 +00:00
|
|
|
return buf.Bytes(), err
|
2023-07-26 12:58:52 +00:00
|
|
|
}
|
2023-09-27 09:04:44 +00:00
|
|
|
out = append(out, buf.Bytes())
|
2023-07-26 12:58:52 +00:00
|
|
|
}
|
|
|
|
return bytes.Join(out, []byte{}), nil
|
2023-07-25 11:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Artifact) NormalisePaths() {
|
|
|
|
for _, f := range a.Files {
|
|
|
|
// If no libraries attached, nothing to normalise, skipping
|
|
|
|
if f.Libraries == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
wsfsBase := "/Workspace"
|
|
|
|
remotePath := path.Join(wsfsBase, f.RemotePath)
|
|
|
|
for i := range f.Libraries {
|
|
|
|
lib := f.Libraries[i]
|
2023-09-08 13:45:21 +00:00
|
|
|
if lib.Whl != "" {
|
2023-07-25 11:35:08 +00:00
|
|
|
lib.Whl = remotePath
|
2023-09-08 13:45:21 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
if lib.Jar != "" {
|
|
|
|
lib.Jar = remotePath
|
|
|
|
continue
|
2023-07-25 11:35:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2022-11-30 13:15:22 +00:00
|
|
|
|
2023-07-25 11:35:08 +00:00
|
|
|
// This function determines if artifact files needs to be uploaded.
|
|
|
|
// During the bundle processing we analyse which library uses which artifact file.
|
|
|
|
// If artifact file is used as a library, we store the reference to this library in artifact file Libraries field.
|
|
|
|
// If artifact file has libraries it's been used in, it means than we need to upload this file.
|
|
|
|
// Otherwise this artifact file is not used and we skip uploading
|
|
|
|
func (af *ArtifactFile) NeedsUpload() bool {
|
|
|
|
return af.Libraries != nil
|
2022-11-30 13:15:22 +00:00
|
|
|
}
|