Merge branch 'main' into bump-parallelism

This commit is contained in:
Pieter Noordhuis 2024-12-16 14:07:12 +01:00 committed by GitHub
commit fc117096ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
451 changed files with 4864 additions and 2854 deletions

View File

@ -1 +1 @@
f2385add116e3716c8a90a0b68e204deb40f996c 7016dcbf2e011459416cf408ce21143bcc4b3a25

8
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,8 @@
# Enable gofumpt and goimports in golangci-lint (#1999)
2e018cfaec200a02ee2bd5b389e7da3c6f15f460
# Enable errcheck everywhere and fix or silent remaining issues (#1987)
8d5351c1c3d7befda4baae5d6adb99367aa50b3c
# Add error checking in tests and enable errcheck there (#1980)
1b2be1b2cb4b7909df2a8ad4cb6a0f43e8fcf0c6

3
.gitattributes vendored
View File

@ -37,6 +37,9 @@ cmd/workspace/apps/apps.go linguist-generated=true
cmd/workspace/artifact-allowlists/artifact-allowlists.go linguist-generated=true cmd/workspace/artifact-allowlists/artifact-allowlists.go linguist-generated=true
cmd/workspace/automatic-cluster-update/automatic-cluster-update.go linguist-generated=true cmd/workspace/automatic-cluster-update/automatic-cluster-update.go linguist-generated=true
cmd/workspace/catalogs/catalogs.go linguist-generated=true cmd/workspace/catalogs/catalogs.go linguist-generated=true
cmd/workspace/clean-room-assets/clean-room-assets.go linguist-generated=true
cmd/workspace/clean-room-task-runs/clean-room-task-runs.go linguist-generated=true
cmd/workspace/clean-rooms/clean-rooms.go linguist-generated=true
cmd/workspace/cluster-policies/cluster-policies.go linguist-generated=true cmd/workspace/cluster-policies/cluster-policies.go linguist-generated=true
cmd/workspace/clusters/clusters.go linguist-generated=true cmd/workspace/clusters/clusters.go linguist-generated=true
cmd/workspace/cmd.go linguist-generated=true cmd/workspace/cmd.go linguist-generated=true

View File

@ -44,7 +44,7 @@ jobs:
run: | run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
go install gotest.tools/gotestsum@latest go install gotest.tools/gotestsum@v1.12.0
- name: Pull external libraries - name: Pull external libraries
run: | run: |

View File

@ -2,21 +2,37 @@ linters:
disable-all: true disable-all: true
enable: enable:
- bodyclose - bodyclose
# errcheck and govet are part of default setup and should be included but give too many errors now - errcheck
# once errors are fixed, they should be enabled here:
#- errcheck
- gosimple - gosimple
#- govet - govet
- ineffassign - ineffassign
- staticcheck - staticcheck
- unused - unused
- gofmt - gofmt
- gofumpt
- goimports
linters-settings: linters-settings:
govet:
enable-all: true
disable:
- fieldalignment
- shadow
gofmt: gofmt:
rewrite-rules: rewrite-rules:
- pattern: 'a[b:len(a)]' - pattern: 'a[b:len(a)]'
replacement: 'a[b:]' replacement: 'a[b:]'
- pattern: 'interface{}' - pattern: 'interface{}'
replacement: 'any' replacement: 'any'
errcheck:
exclude-functions:
- (*github.com/spf13/cobra.Command).RegisterFlagCompletionFunc
- (*github.com/spf13/cobra.Command).MarkFlagRequired
- (*github.com/spf13/pflag.FlagSet).MarkDeprecated
- (*github.com/spf13/pflag.FlagSet).MarkHidden
gofumpt:
module-path: github.com/databricks/cli
extra-rules: true
#goimports:
# local-prefixes: github.com/databricks/cli
issues: issues:
exclude-dirs-use-default: false # recommended by docs https://golangci-lint.run/usage/false-positives/ exclude-dirs-use-default: false # recommended by docs https://golangci-lint.run/usage/false-positives/

View File

@ -7,11 +7,14 @@
"go.lintFlags": [ "go.lintFlags": [
"--fast" "--fast"
], ],
"go.useLanguageServer": true,
"gopls": {
"formatting.gofumpt": true
},
"files.trimTrailingWhitespace": true, "files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true, "files.insertFinalNewline": true,
"files.trimFinalNewlines": true, "files.trimFinalNewlines": true,
"python.envFile": "${workspaceRoot}/.env", "python.envFile": "${workspaceRoot}/.env",
"databricks.python.envFile": "${workspaceFolder}/.env",
"python.analysis.stubPath": ".vscode", "python.analysis.stubPath": ".vscode",
"jupyter.interactiveWindow.cellMarker.codeRegex": "^# COMMAND ----------|^# Databricks notebook source|^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])", "jupyter.interactiveWindow.cellMarker.codeRegex": "^# COMMAND ----------|^# Databricks notebook source|^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])",
"jupyter.interactiveWindow.cellMarker.default": "# COMMAND ----------" "jupyter.interactiveWindow.cellMarker.default": "# COMMAND ----------"

View File

@ -7,13 +7,13 @@ fmt:
@gofmt -w $(shell find . -type f -name '*.go' -not -path "./vendor/*") @gofmt -w $(shell find . -type f -name '*.go' -not -path "./vendor/*")
lint: vendor lint: vendor
@echo "✓ Linting source code with https://golangci-lint.run/ (with --fix)..."
@golangci-lint run --fix ./...
lintcheck: vendor
@echo "✓ Linting source code with https://golangci-lint.run/ ..." @echo "✓ Linting source code with https://golangci-lint.run/ ..."
@golangci-lint run ./... @golangci-lint run ./...
lintfix: vendor
@echo "✓ Linting source code with 'golangci-lint run --fix' ..."
@golangci-lint run --fix ./...
test: lint testonly test: lint testonly
testonly: testonly:
@ -37,6 +37,6 @@ vendor:
@go mod vendor @go mod vendor
integration: integration:
gotestsum --format github-actions --rerun-fails --jsonfile output.json --packages "./internal/..." -- -run "TestAcc.*" -p 8 -parallel 8 -timeout=2h gotestsum --format github-actions --rerun-fails --jsonfile output.json --packages "./integration/..." -- -p 8 -parallel 8 -timeout=2h
.PHONY: fmt lint lintfix test testonly coverage build snapshot vendor integration .PHONY: fmt lint lintcheck test testonly coverage build snapshot vendor integration

View File

@ -3,7 +3,6 @@ package artifacts
import ( import (
"context" "context"
"fmt" "fmt"
"slices" "slices"
"github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle"

View File

@ -13,8 +13,7 @@ func DetectPackages() bundle.Mutator {
return &autodetect{} return &autodetect{}
} }
type autodetect struct { type autodetect struct{}
}
func (m *autodetect) Name() string { func (m *autodetect) Name() string {
return "artifacts.DetectPackages" return "artifacts.DetectPackages"

View File

@ -96,7 +96,6 @@ func (m *expandGlobs) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnost
// Set the expanded globs back into the configuration. // Set the expanded globs back into the configuration.
return dyn.SetByPath(v, base, dyn.V(output)) return dyn.SetByPath(v, base, dyn.V(output))
}) })
if err != nil { if err != nil {
return diag.FromErr(err) return diag.FromErr(err)
} }

View File

@ -15,8 +15,7 @@ import (
"github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/log"
) )
type detectPkg struct { type detectPkg struct{}
}
func DetectPackage() bundle.Mutator { func DetectPackage() bundle.Mutator {
return &detectPkg{} return &detectPkg{}
@ -42,7 +41,7 @@ func (m *detectPkg) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostic
return nil return nil
} }
log.Infof(ctx, fmt.Sprintf("Found Python wheel project at %s", b.BundleRootPath)) log.Infof(ctx, "Found Python wheel project at %s", b.BundleRootPath)
module := extractModuleName(setupPy) module := extractModuleName(setupPy)
if b.Config.Artifacts == nil { if b.Config.Artifacts == nil {

View File

@ -186,7 +186,7 @@ func (b *Bundle) CacheDir(ctx context.Context, paths ...string) (string, error)
// Make directory if it doesn't exist yet. // Make directory if it doesn't exist yet.
dir := filepath.Join(parts...) dir := filepath.Join(parts...)
err := os.MkdirAll(dir, 0700) err := os.MkdirAll(dir, 0o700)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -203,7 +203,7 @@ func (b *Bundle) InternalDir(ctx context.Context) (string, error) {
} }
dir := filepath.Join(cacheDir, internalFolder) dir := filepath.Join(cacheDir, internalFolder)
err = os.MkdirAll(dir, 0700) err = os.MkdirAll(dir, 0o700)
if err != nil { if err != nil {
return dir, err return dir, err
} }

View File

@ -47,8 +47,10 @@ type PyDABs struct {
Import []string `json:"import,omitempty"` Import []string `json:"import,omitempty"`
} }
type Command string type (
type ScriptHook string Command string
ScriptHook string
)
// These hook names are subject to change and currently experimental // These hook names are subject to change and currently experimental
const ( const (

View File

@ -6,8 +6,10 @@ import (
"github.com/databricks/databricks-sdk-go/service/jobs" "github.com/databricks/databricks-sdk-go/service/jobs"
) )
var jobOrder = yamlsaver.NewOrder([]string{"name", "job_clusters", "compute", "tasks"}) var (
var taskOrder = yamlsaver.NewOrder([]string{"task_key", "depends_on", "existing_cluster_id", "new_cluster", "job_cluster_key"}) jobOrder = yamlsaver.NewOrder([]string{"name", "job_clusters", "compute", "tasks"})
taskOrder = yamlsaver.NewOrder([]string{"task_key", "depends_on", "existing_cluster_id", "new_cluster", "job_cluster_key"})
)
func ConvertJobToValue(job *jobs.Job) (dyn.Value, error) { func ConvertJobToValue(job *jobs.Job) (dyn.Value, error) {
value := make(map[string]dyn.Value) value := make(map[string]dyn.Value)

View File

@ -27,7 +27,7 @@ func (m *processRootIncludes) Apply(ctx context.Context, b *bundle.Bundle) diag.
var out []bundle.Mutator var out []bundle.Mutator
// Map with files we've already seen to avoid loading them twice. // Map with files we've already seen to avoid loading them twice.
var seen = map[string]bool{} seen := map[string]bool{}
for _, file := range config.FileNames { for _, file := range config.FileNames {
seen[file] = true seen[file] = true

View File

@ -481,5 +481,4 @@ func TestApplyPresetsSourceLinkedDeployment(t *testing.T) {
require.Equal(t, tt.expectedValue, b.Config.Presets.SourceLinkedDeployment) require.Equal(t, tt.expectedValue, b.Config.Presets.SourceLinkedDeployment)
}) })
} }
} }

View File

@ -42,7 +42,6 @@ func rewriteComputeIdToClusterId(v dyn.Value, p dyn.Path) (dyn.Value, diag.Diagn
var diags diag.Diagnostics var diags diag.Diagnostics
computeIdPath := p.Append(dyn.Key("compute_id")) computeIdPath := p.Append(dyn.Key("compute_id"))
computeId, err := dyn.GetByPath(v, computeIdPath) computeId, err := dyn.GetByPath(v, computeIdPath)
// If the "compute_id" key is not set, we don't need to do anything. // If the "compute_id" key is not set, we don't need to do anything.
if err != nil { if err != nil {
return v, nil return v, nil

View File

@ -17,7 +17,7 @@ import (
) )
func touchEmptyFile(t *testing.T, path string) { func touchEmptyFile(t *testing.T, path string) {
err := os.MkdirAll(filepath.Dir(path), 0700) err := os.MkdirAll(filepath.Dir(path), 0o700)
require.NoError(t, err) require.NoError(t, err)
f, err := os.Create(path) f, err := os.Create(path)
require.NoError(t, err) require.NoError(t, err)

View File

@ -28,7 +28,7 @@ func (m *expandWorkspaceRoot) Apply(ctx context.Context, b *bundle.Bundle) diag.
} }
currentUser := b.Config.Workspace.CurrentUser currentUser := b.Config.Workspace.CurrentUser
if currentUser == nil || currentUser.UserName == "" { if currentUser == nil || currentUser.User == nil || currentUser.UserName == "" {
return diag.Errorf("unable to expand workspace root: current user not set") return diag.Errorf("unable to expand workspace root: current user not set")
} }

View File

@ -10,8 +10,7 @@ import (
"github.com/databricks/cli/libs/diag" "github.com/databricks/cli/libs/diag"
) )
type initializeURLs struct { type initializeURLs struct{}
}
// InitializeURLs makes sure the URL field of each resource is configured. // InitializeURLs makes sure the URL field of each resource is configured.
// NOTE: since this depends on an extra API call, this mutator adds some extra // NOTE: since this depends on an extra API call, this mutator adds some extra
@ -32,11 +31,14 @@ func (m *initializeURLs) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagn
} }
orgId := strconv.FormatInt(workspaceId, 10) orgId := strconv.FormatInt(workspaceId, 10)
host := b.WorkspaceClient().Config.CanonicalHostName() host := b.WorkspaceClient().Config.CanonicalHostName()
initializeForWorkspace(b, orgId, host) err = initializeForWorkspace(b, orgId, host)
if err != nil {
return diag.FromErr(err)
}
return nil return nil
} }
func initializeForWorkspace(b *bundle.Bundle, orgId string, host string) error { func initializeForWorkspace(b *bundle.Bundle, orgId, host string) error {
baseURL, err := url.Parse(host) baseURL, err := url.Parse(host)
if err != nil { if err != nil {
return err return err

View File

@ -110,7 +110,8 @@ func TestInitializeURLs(t *testing.T) {
"dashboard1": "https://mycompany.databricks.com/dashboardsv3/01ef8d56871e1d50ae30ce7375e42478/published?o=123456", "dashboard1": "https://mycompany.databricks.com/dashboardsv3/01ef8d56871e1d50ae30ce7375e42478/published?o=123456",
} }
initializeForWorkspace(b, "123456", "https://mycompany.databricks.com/") err := initializeForWorkspace(b, "123456", "https://mycompany.databricks.com/")
require.NoError(t, err)
for _, group := range b.Config.Resources.AllResources() { for _, group := range b.Config.Resources.AllResources() {
for key, r := range group.Resources { for key, r := range group.Resources {
@ -133,7 +134,8 @@ func TestInitializeURLsWithoutOrgId(t *testing.T) {
}, },
} }
initializeForWorkspace(b, "123456", "https://adb-123456.azuredatabricks.net/") err := initializeForWorkspace(b, "123456", "https://adb-123456.azuredatabricks.net/")
require.NoError(t, err)
require.Equal(t, "https://adb-123456.azuredatabricks.net/jobs/1", b.Config.Resources.Jobs["job1"].URL) require.Equal(t, "https://adb-123456.azuredatabricks.net/jobs/1", b.Config.Resources.Jobs["job1"].URL)
} }

View File

@ -2,6 +2,8 @@ package mutator
import ( import (
"context" "context"
"errors"
"os"
"path/filepath" "path/filepath"
"github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle"
@ -24,8 +26,10 @@ func (m *loadGitDetails) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagn
var diags diag.Diagnostics var diags diag.Diagnostics
info, err := git.FetchRepositoryInfo(ctx, b.BundleRoot.Native(), b.WorkspaceClient()) info, err := git.FetchRepositoryInfo(ctx, b.BundleRoot.Native(), b.WorkspaceClient())
if err != nil { if err != nil {
if !errors.Is(err, os.ErrNotExist) {
diags = append(diags, diag.WarningFromErr(err)...) diags = append(diags, diag.WarningFromErr(err)...)
} }
}
if info.WorktreeRoot == "" { if info.WorktreeRoot == "" {
b.WorktreeRoot = b.BundleRoot b.WorktreeRoot = b.BundleRoot

View File

@ -6,6 +6,7 @@ import (
"github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle"
"github.com/databricks/cli/bundle/config" "github.com/databricks/cli/bundle/config"
"github.com/databricks/cli/bundle/config/resources" "github.com/databricks/cli/bundle/config/resources"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/diag" "github.com/databricks/cli/libs/diag"
"github.com/databricks/cli/libs/env" "github.com/databricks/cli/libs/env"
) )
@ -22,7 +23,7 @@ func (m *overrideCompute) Name() string {
func overrideJobCompute(j *resources.Job, compute string) { func overrideJobCompute(j *resources.Job, compute string) {
for i := range j.Tasks { for i := range j.Tasks {
var task = &j.Tasks[i] task := &j.Tasks[i]
if task.ForEachTask != nil { if task.ForEachTask != nil {
task = &task.ForEachTask.Task task = &task.ForEachTask.Task
@ -38,18 +39,32 @@ func overrideJobCompute(j *resources.Job, compute string) {
} }
func (m *overrideCompute) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { func (m *overrideCompute) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
if b.Config.Bundle.Mode != config.Development { var diags diag.Diagnostics
if b.Config.Bundle.Mode == config.Production {
if b.Config.Bundle.ClusterId != "" { if b.Config.Bundle.ClusterId != "" {
return diag.Errorf("cannot override compute for an target that does not use 'mode: development'") // Overriding compute via a command-line flag for production works, but is not recommended.
diags = diags.Extend(diag.Diagnostics{{
Summary: "Setting a cluster override for a target that uses 'mode: production' is not recommended",
Detail: "It is recommended to always use the same compute for production target for consistency.",
Severity: diag.Warning,
}})
} }
return nil
} }
if v := env.Get(ctx, "DATABRICKS_CLUSTER_ID"); v != "" { if v := env.Get(ctx, "DATABRICKS_CLUSTER_ID"); v != "" {
// For historical reasons, we allow setting the cluster ID via the DATABRICKS_CLUSTER_ID
// when development mode is used. Sometimes, this is done by accident, so we log an info message.
if b.Config.Bundle.Mode == config.Development {
cmdio.LogString(ctx, "Setting a cluster override because DATABRICKS_CLUSTER_ID is set. It is recommended to use --cluster-id instead, which works in any target mode.")
} else {
// We don't allow using DATABRICKS_CLUSTER_ID in any other mode, it's too error-prone.
return diag.Warningf("The DATABRICKS_CLUSTER_ID variable is set but is ignored since the current target does not use 'mode: development'")
}
b.Config.Bundle.ClusterId = v b.Config.Bundle.ClusterId = v
} }
if b.Config.Bundle.ClusterId == "" { if b.Config.Bundle.ClusterId == "" {
return nil return diags
} }
r := b.Config.Resources r := b.Config.Resources
@ -57,5 +72,5 @@ func (m *overrideCompute) Apply(ctx context.Context, b *bundle.Bundle) diag.Diag
overrideJobCompute(r.Jobs[i], b.Config.Bundle.ClusterId) overrideJobCompute(r.Jobs[i], b.Config.Bundle.ClusterId)
} }
return nil return diags
} }

View File

@ -8,13 +8,14 @@ import (
"github.com/databricks/cli/bundle/config" "github.com/databricks/cli/bundle/config"
"github.com/databricks/cli/bundle/config/mutator" "github.com/databricks/cli/bundle/config/mutator"
"github.com/databricks/cli/bundle/config/resources" "github.com/databricks/cli/bundle/config/resources"
"github.com/databricks/cli/libs/diag"
"github.com/databricks/databricks-sdk-go/service/compute" "github.com/databricks/databricks-sdk-go/service/compute"
"github.com/databricks/databricks-sdk-go/service/jobs" "github.com/databricks/databricks-sdk-go/service/jobs"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestOverrideDevelopment(t *testing.T) { func TestOverrideComputeModeDevelopment(t *testing.T) {
t.Setenv("DATABRICKS_CLUSTER_ID", "") t.Setenv("DATABRICKS_CLUSTER_ID", "")
b := &bundle.Bundle{ b := &bundle.Bundle{
Config: config.Root{ Config: config.Root{
@ -62,10 +63,13 @@ func TestOverrideDevelopment(t *testing.T) {
assert.Empty(t, b.Config.Resources.Jobs["job1"].Tasks[3].JobClusterKey) assert.Empty(t, b.Config.Resources.Jobs["job1"].Tasks[3].JobClusterKey)
} }
func TestOverrideDevelopmentEnv(t *testing.T) { func TestOverrideComputeModeDefaultIgnoresVariable(t *testing.T) {
t.Setenv("DATABRICKS_CLUSTER_ID", "newClusterId") t.Setenv("DATABRICKS_CLUSTER_ID", "newClusterId")
b := &bundle.Bundle{ b := &bundle.Bundle{
Config: config.Root{ Config: config.Root{
Bundle: config.Bundle{
Mode: "",
},
Resources: config.Resources{ Resources: config.Resources{
Jobs: map[string]*resources.Job{ Jobs: map[string]*resources.Job{
"job1": {JobSettings: &jobs.JobSettings{ "job1": {JobSettings: &jobs.JobSettings{
@ -86,11 +90,12 @@ func TestOverrideDevelopmentEnv(t *testing.T) {
m := mutator.OverrideCompute() m := mutator.OverrideCompute()
diags := bundle.Apply(context.Background(), b, m) diags := bundle.Apply(context.Background(), b, m)
require.NoError(t, diags.Error()) require.Len(t, diags, 1)
assert.Equal(t, "The DATABRICKS_CLUSTER_ID variable is set but is ignored since the current target does not use 'mode: development'", diags[0].Summary)
assert.Equal(t, "cluster2", b.Config.Resources.Jobs["job1"].Tasks[1].ExistingClusterId) assert.Equal(t, "cluster2", b.Config.Resources.Jobs["job1"].Tasks[1].ExistingClusterId)
} }
func TestOverridePipelineTask(t *testing.T) { func TestOverrideComputePipelineTask(t *testing.T) {
t.Setenv("DATABRICKS_CLUSTER_ID", "newClusterId") t.Setenv("DATABRICKS_CLUSTER_ID", "newClusterId")
b := &bundle.Bundle{ b := &bundle.Bundle{
Config: config.Root{ Config: config.Root{
@ -115,7 +120,7 @@ func TestOverridePipelineTask(t *testing.T) {
assert.Empty(t, b.Config.Resources.Jobs["job1"].Tasks[0].ExistingClusterId) assert.Empty(t, b.Config.Resources.Jobs["job1"].Tasks[0].ExistingClusterId)
} }
func TestOverrideForEachTask(t *testing.T) { func TestOverrideComputeForEachTask(t *testing.T) {
t.Setenv("DATABRICKS_CLUSTER_ID", "newClusterId") t.Setenv("DATABRICKS_CLUSTER_ID", "newClusterId")
b := &bundle.Bundle{ b := &bundle.Bundle{
Config: config.Root{ Config: config.Root{
@ -140,10 +145,11 @@ func TestOverrideForEachTask(t *testing.T) {
assert.Empty(t, b.Config.Resources.Jobs["job1"].Tasks[0].ForEachTask.Task) assert.Empty(t, b.Config.Resources.Jobs["job1"].Tasks[0].ForEachTask.Task)
} }
func TestOverrideProduction(t *testing.T) { func TestOverrideComputeModeProduction(t *testing.T) {
b := &bundle.Bundle{ b := &bundle.Bundle{
Config: config.Root{ Config: config.Root{
Bundle: config.Bundle{ Bundle: config.Bundle{
Mode: config.Production,
ClusterId: "newClusterID", ClusterId: "newClusterID",
}, },
Resources: config.Resources{ Resources: config.Resources{
@ -166,13 +172,19 @@ func TestOverrideProduction(t *testing.T) {
m := mutator.OverrideCompute() m := mutator.OverrideCompute()
diags := bundle.Apply(context.Background(), b, m) diags := bundle.Apply(context.Background(), b, m)
require.True(t, diags.HasError()) require.Len(t, diags, 1)
assert.Equal(t, "Setting a cluster override for a target that uses 'mode: production' is not recommended", diags[0].Summary)
assert.Equal(t, diag.Warning, diags[0].Severity)
assert.Equal(t, "newClusterID", b.Config.Resources.Jobs["job1"].Tasks[0].ExistingClusterId)
} }
func TestOverrideProductionEnv(t *testing.T) { func TestOverrideComputeModeProductionIgnoresVariable(t *testing.T) {
t.Setenv("DATABRICKS_CLUSTER_ID", "newClusterId") t.Setenv("DATABRICKS_CLUSTER_ID", "newClusterId")
b := &bundle.Bundle{ b := &bundle.Bundle{
Config: config.Root{ Config: config.Root{
Bundle: config.Bundle{
Mode: config.Production,
},
Resources: config.Resources{ Resources: config.Resources{
Jobs: map[string]*resources.Job{ Jobs: map[string]*resources.Job{
"job1": {JobSettings: &jobs.JobSettings{ "job1": {JobSettings: &jobs.JobSettings{
@ -193,5 +205,7 @@ func TestOverrideProductionEnv(t *testing.T) {
m := mutator.OverrideCompute() m := mutator.OverrideCompute()
diags := bundle.Apply(context.Background(), b, m) diags := bundle.Apply(context.Background(), b, m)
require.NoError(t, diags.Error()) require.Len(t, diags, 1)
assert.Equal(t, "The DATABRICKS_CLUSTER_ID variable is set but is ignored since the current target does not use 'mode: development'", diags[0].Summary)
assert.Equal(t, "cluster2", b.Config.Resources.Jobs["job1"].Tasks[1].ExistingClusterId)
} }

View File

@ -95,7 +95,7 @@ func jobRewritePatterns() []jobRewritePattern {
// VisitJobPaths visits all paths in job resources and applies a function to each path. // VisitJobPaths visits all paths in job resources and applies a function to each path.
func VisitJobPaths(value dyn.Value, fn VisitFunc) (dyn.Value, error) { func VisitJobPaths(value dyn.Value, fn VisitFunc) (dyn.Value, error) {
var err error var err error
var newValue = value newValue := value
for _, rewritePattern := range jobRewritePatterns() { for _, rewritePattern := range jobRewritePatterns() {
newValue, err = dyn.MapByPattern(newValue, rewritePattern.pattern, func(p dyn.Path, v dyn.Value) (dyn.Value, error) { newValue, err = dyn.MapByPattern(newValue, rewritePattern.pattern, func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
@ -105,7 +105,6 @@ func VisitJobPaths(value dyn.Value, fn VisitFunc) (dyn.Value, error) {
return fn(p, rewritePattern.kind, v) return fn(p, rewritePattern.kind, v)
}) })
if err != nil { if err != nil {
return dyn.InvalidValue, err return dyn.InvalidValue, err
} }

View File

@ -57,14 +57,12 @@ func (m *prependWorkspacePrefix) Apply(ctx context.Context, b *bundle.Bundle) di
return dyn.NewValue(fmt.Sprintf("/Workspace%s", path), v.Locations()), nil return dyn.NewValue(fmt.Sprintf("/Workspace%s", path), v.Locations()), nil
}) })
if err != nil { if err != nil {
return dyn.InvalidValue, err return dyn.InvalidValue, err
} }
} }
return v, nil return v, nil
}) })
if err != nil { if err != nil {
return diag.FromErr(err) return diag.FromErr(err)
} }

View File

@ -30,7 +30,6 @@ type parsePythonDiagnosticsTest struct {
} }
func TestParsePythonDiagnostics(t *testing.T) { func TestParsePythonDiagnostics(t *testing.T) {
testCases := []parsePythonDiagnosticsTest{ testCases := []parsePythonDiagnosticsTest{
{ {
name: "short error with location", name: "short error with location",

View File

@ -9,12 +9,11 @@ import (
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/databricks/databricks-sdk-go/logger" "github.com/databricks/databricks-sdk-go/logger"
"github.com/fatih/color" "github.com/fatih/color"
"strings"
"github.com/databricks/cli/libs/python" "github.com/databricks/cli/libs/python"
"github.com/databricks/cli/bundle/env" "github.com/databricks/cli/bundle/env"
@ -94,11 +93,10 @@ func (m *pythonMutator) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagno
// mutateDiags is used because Mutate returns 'error' instead of 'diag.Diagnostics' // mutateDiags is used because Mutate returns 'error' instead of 'diag.Diagnostics'
var mutateDiags diag.Diagnostics var mutateDiags diag.Diagnostics
var mutateDiagsHasError = errors.New("unexpected error") mutateDiagsHasError := errors.New("unexpected error")
err := b.Config.Mutate(func(leftRoot dyn.Value) (dyn.Value, error) { err := b.Config.Mutate(func(leftRoot dyn.Value) (dyn.Value, error) {
pythonPath, err := detectExecutable(ctx, experimental.PyDABs.VEnvPath) pythonPath, err := detectExecutable(ctx, experimental.PyDABs.VEnvPath)
if err != nil { if err != nil {
return dyn.InvalidValue, fmt.Errorf("failed to get Python interpreter path: %w", err) return dyn.InvalidValue, fmt.Errorf("failed to get Python interpreter path: %w", err)
} }
@ -141,7 +139,7 @@ func createCacheDir(ctx context.Context) (string, error) {
// use 'default' as target name // use 'default' as target name
cacheDir := filepath.Join(tempDir, "default", "pydabs") cacheDir := filepath.Join(tempDir, "default", "pydabs")
err := os.MkdirAll(cacheDir, 0700) err := os.MkdirAll(cacheDir, 0o700)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -152,7 +150,7 @@ func createCacheDir(ctx context.Context) (string, error) {
return os.MkdirTemp("", "-pydabs") return os.MkdirTemp("", "-pydabs")
} }
func (m *pythonMutator) runPythonMutator(ctx context.Context, cacheDir string, rootPath string, pythonPath string, root dyn.Value) (dyn.Value, diag.Diagnostics) { func (m *pythonMutator) runPythonMutator(ctx context.Context, cacheDir, rootPath, pythonPath string, root dyn.Value) (dyn.Value, diag.Diagnostics) {
inputPath := filepath.Join(cacheDir, "input.json") inputPath := filepath.Join(cacheDir, "input.json")
outputPath := filepath.Join(cacheDir, "output.json") outputPath := filepath.Join(cacheDir, "output.json")
diagnosticsPath := filepath.Join(cacheDir, "diagnostics.json") diagnosticsPath := filepath.Join(cacheDir, "diagnostics.json")
@ -263,10 +261,10 @@ func writeInputFile(inputPath string, input dyn.Value) error {
return fmt.Errorf("failed to marshal input: %w", err) return fmt.Errorf("failed to marshal input: %w", err)
} }
return os.WriteFile(inputPath, rootConfigJson, 0600) return os.WriteFile(inputPath, rootConfigJson, 0o600)
} }
func loadOutputFile(rootPath string, outputPath string) (dyn.Value, diag.Diagnostics) { func loadOutputFile(rootPath, outputPath string) (dyn.Value, diag.Diagnostics) {
outputFile, err := os.Open(outputPath) outputFile, err := os.Open(outputPath)
if err != nil { if err != nil {
return dyn.InvalidValue, diag.FromErr(fmt.Errorf("failed to open output file: %w", err)) return dyn.InvalidValue, diag.FromErr(fmt.Errorf("failed to open output file: %w", err))
@ -381,7 +379,7 @@ func createLoadOverrideVisitor(ctx context.Context) merge.OverrideVisitor {
return right, nil return right, nil
}, },
VisitUpdate: func(valuePath dyn.Path, left dyn.Value, right dyn.Value) (dyn.Value, error) { VisitUpdate: func(valuePath dyn.Path, left, right dyn.Value) (dyn.Value, error) {
return dyn.InvalidValue, fmt.Errorf("unexpected change at %q (update)", valuePath.String()) return dyn.InvalidValue, fmt.Errorf("unexpected change at %q (update)", valuePath.String())
}, },
} }
@ -430,7 +428,7 @@ func createInitOverrideVisitor(ctx context.Context) merge.OverrideVisitor {
return right, nil return right, nil
}, },
VisitUpdate: func(valuePath dyn.Path, left dyn.Value, right dyn.Value) (dyn.Value, error) { VisitUpdate: func(valuePath dyn.Path, left, right dyn.Value) (dyn.Value, error) {
if !valuePath.HasPrefix(jobsPath) { if !valuePath.HasPrefix(jobsPath) {
return dyn.InvalidValue, fmt.Errorf("unexpected change at %q (update)", valuePath.String()) return dyn.InvalidValue, fmt.Errorf("unexpected change at %q (update)", valuePath.String())
} }

View File

@ -106,7 +106,6 @@ func TestPythonMutator_load(t *testing.T) {
Column: 5, Column: 5,
}, },
}, diags[0].Locations) }, diags[0].Locations)
} }
func TestPythonMutator_load_disallowed(t *testing.T) { func TestPythonMutator_load_disallowed(t *testing.T) {
@ -588,7 +587,7 @@ or activate the environment before running CLI commands:
assert.Equal(t, expected, out) assert.Equal(t, expected, out)
} }
func withProcessStub(t *testing.T, args []string, output string, diagnostics string) context.Context { func withProcessStub(t *testing.T, args []string, output, diagnostics string) context.Context {
ctx := context.Background() ctx := context.Background()
ctx, stub := process.WithStub(ctx) ctx, stub := process.WithStub(ctx)
@ -611,10 +610,10 @@ func withProcessStub(t *testing.T, args []string, output string, diagnostics str
assert.NoError(t, err) assert.NoError(t, err)
if reflect.DeepEqual(actual.Args, args) { if reflect.DeepEqual(actual.Args, args) {
err := os.WriteFile(outputPath, []byte(output), 0600) err := os.WriteFile(outputPath, []byte(output), 0o600)
require.NoError(t, err) require.NoError(t, err)
err = os.WriteFile(diagnosticsPath, []byte(diagnostics), 0600) err = os.WriteFile(diagnosticsPath, []byte(diagnostics), 0o600)
require.NoError(t, err) require.NoError(t, err)
return nil return nil
@ -626,7 +625,7 @@ func withProcessStub(t *testing.T, args []string, output string, diagnostics str
return ctx return ctx
} }
func loadYaml(name string, content string) *bundle.Bundle { func loadYaml(name, content string) *bundle.Bundle {
v, diag := config.LoadFromBytes(name, []byte(content)) v, diag := config.LoadFromBytes(name, []byte(content))
if diag.Error() != nil { if diag.Error() != nil {
@ -650,17 +649,17 @@ func withFakeVEnv(t *testing.T, venvPath string) {
interpreterPath := interpreterPath(venvPath) interpreterPath := interpreterPath(venvPath)
err = os.MkdirAll(filepath.Dir(interpreterPath), 0755) err = os.MkdirAll(filepath.Dir(interpreterPath), 0o755)
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = os.WriteFile(interpreterPath, []byte(""), 0755) err = os.WriteFile(interpreterPath, []byte(""), 0o755)
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = os.WriteFile(filepath.Join(venvPath, "pyvenv.cfg"), []byte(""), 0755) err = os.WriteFile(filepath.Join(venvPath, "pyvenv.cfg"), []byte(""), 0o755)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -36,8 +36,7 @@ func (m *resolveResourceReferences) Apply(ctx context.Context, b *bundle.Bundle)
return fmt.Errorf("failed to resolve %s, err: %w", v.Lookup, err) return fmt.Errorf("failed to resolve %s, err: %w", v.Lookup, err)
} }
v.Set(id) return v.Set(id)
return nil
}) })
} }

View File

@ -108,7 +108,8 @@ func TestNoLookupIfVariableIsSet(t *testing.T) {
m := mocks.NewMockWorkspaceClient(t) m := mocks.NewMockWorkspaceClient(t)
b.SetWorkpaceClient(m.WorkspaceClient) b.SetWorkpaceClient(m.WorkspaceClient)
b.Config.Variables["my-cluster-id"].Set("random value") err := b.Config.Variables["my-cluster-id"].Set("random value")
require.NoError(t, err)
diags := bundle.Apply(context.Background(), b, ResolveResourceReferences()) diags := bundle.Apply(context.Background(), b, ResolveResourceReferences())
require.NoError(t, diags.Error()) require.NoError(t, diags.Error())

View File

@ -32,7 +32,8 @@ func ResolveVariableReferencesInLookup() bundle.Mutator {
} }
func ResolveVariableReferencesInComplexVariables() bundle.Mutator { func ResolveVariableReferencesInComplexVariables() bundle.Mutator {
return &resolveVariableReferences{prefixes: []string{ return &resolveVariableReferences{
prefixes: []string{
"bundle", "bundle",
"workspace", "workspace",
"variables", "variables",
@ -173,7 +174,6 @@ func (m *resolveVariableReferences) Apply(ctx context.Context, b *bundle.Bundle)
return dyn.InvalidValue, dynvar.ErrSkipResolution return dyn.InvalidValue, dynvar.ErrSkipResolution
}) })
}) })
if err != nil { if err != nil {
return dyn.InvalidValue, err return dyn.InvalidValue, err
} }
@ -184,7 +184,6 @@ func (m *resolveVariableReferences) Apply(ctx context.Context, b *bundle.Bundle)
diags = diags.Extend(normaliseDiags) diags = diags.Extend(normaliseDiags)
return root, nil return root, nil
}) })
if err != nil { if err != nil {
diags = diags.Extend(diag.FromErr(err)) diags = diags.Extend(diag.FromErr(err))
} }

View File

@ -63,7 +63,6 @@ func (m *rewriteWorkspacePrefix) Apply(ctx context.Context, b *bundle.Bundle) di
return v, nil return v, nil
}) })
}) })
if err != nil { if err != nil {
return diag.FromErr(err) return diag.FromErr(err)
} }

View File

@ -81,5 +81,4 @@ func TestNoWorkspacePrefixUsed(t *testing.T) {
require.Equal(t, "${workspace.artifact_path}/jar1.jar", b.Config.Resources.Jobs["test_job"].JobSettings.Tasks[1].Libraries[0].Jar) require.Equal(t, "${workspace.artifact_path}/jar1.jar", b.Config.Resources.Jobs["test_job"].JobSettings.Tasks[1].Libraries[0].Jar)
require.Equal(t, "${workspace.file_path}/notebook2", b.Config.Resources.Jobs["test_job"].JobSettings.Tasks[2].NotebookTask.NotebookPath) require.Equal(t, "${workspace.file_path}/notebook2", b.Config.Resources.Jobs["test_job"].JobSettings.Tasks[2].NotebookTask.NotebookPath)
require.Equal(t, "${workspace.artifact_path}/jar2.jar", b.Config.Resources.Jobs["test_job"].JobSettings.Tasks[2].Libraries[0].Jar) require.Equal(t, "${workspace.artifact_path}/jar2.jar", b.Config.Resources.Jobs["test_job"].JobSettings.Tasks[2].Libraries[0].Jar)
} }

View File

@ -12,8 +12,7 @@ import (
"github.com/databricks/databricks-sdk-go/service/jobs" "github.com/databricks/databricks-sdk-go/service/jobs"
) )
type setRunAs struct { type setRunAs struct{}
}
// This mutator does two things: // This mutator does two things:
// //
@ -30,7 +29,7 @@ func (m *setRunAs) Name() string {
return "SetRunAs" return "SetRunAs"
} }
func reportRunAsNotSupported(resourceType string, location dyn.Location, currentUser string, runAsUser string) diag.Diagnostics { func reportRunAsNotSupported(resourceType string, location dyn.Location, currentUser, runAsUser string) diag.Diagnostics {
return diag.Diagnostics{{ return diag.Diagnostics{{
Summary: fmt.Sprintf("%s do not support a setting a run_as user that is different from the owner.\n"+ Summary: fmt.Sprintf("%s do not support a setting a run_as user that is different from the owner.\n"+
"Current identity: %s. Run as identity: %s.\n"+ "Current identity: %s. Run as identity: %s.\n"+

View File

@ -65,7 +65,6 @@ func setVariable(ctx context.Context, v dyn.Value, variable *variable.Variable,
// We should have had a value to set for the variable at this point. // We should have had a value to set for the variable at this point.
return dyn.InvalidValue, fmt.Errorf(`no value assigned to required variable %s. Assignment can be done through the "--var" flag or by setting the %s environment variable`, name, bundleVarPrefix+name) return dyn.InvalidValue, fmt.Errorf(`no value assigned to required variable %s. Assignment can be done through the "--var" flag or by setting the %s environment variable`, name, bundleVarPrefix+name)
} }
func (m *setVariables) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { func (m *setVariables) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {

View File

@ -35,7 +35,7 @@ func (m *syncInferRoot) Name() string {
// If the path does not exist, it returns an empty string. // If the path does not exist, it returns an empty string.
// //
// See "sync_infer_root_internal_test.go" for examples. // See "sync_infer_root_internal_test.go" for examples.
func (m *syncInferRoot) computeRoot(path string, root string) string { func (m *syncInferRoot) computeRoot(path, root string) string {
for !filepath.IsLocal(path) { for !filepath.IsLocal(path) {
// Break if we have reached the root of the filesystem. // Break if we have reached the root of the filesystem.
dir := filepath.Dir(root) dir := filepath.Dir(root)

View File

@ -275,8 +275,8 @@ func (m *translatePaths) Apply(_ context.Context, b *bundle.Bundle) diag.Diagnos
} }
func gatherFallbackPaths(v dyn.Value, typ string) (map[string]string, error) { func gatherFallbackPaths(v dyn.Value, typ string) (map[string]string, error) {
var fallback = make(map[string]string) fallback := make(map[string]string)
var pattern = dyn.NewPattern(dyn.Key("resources"), dyn.Key(typ), dyn.AnyKey()) pattern := dyn.NewPattern(dyn.Key("resources"), dyn.Key(typ), dyn.AnyKey())
// Previous behavior was to use a resource's location as the base path to resolve // Previous behavior was to use a resource's location as the base path to resolve
// relative paths in its definition. With the introduction of [dyn.Value] throughout, // relative paths in its definition. With the introduction of [dyn.Value] throughout,

View File

@ -28,12 +28,13 @@ import (
func touchNotebookFile(t *testing.T, path string) { func touchNotebookFile(t *testing.T, path string) {
f, err := os.Create(path) f, err := os.Create(path)
require.NoError(t, err) require.NoError(t, err)
f.WriteString("# Databricks notebook source\n") _, err = f.WriteString("# Databricks notebook source\n")
require.NoError(t, err)
f.Close() f.Close()
} }
func touchEmptyFile(t *testing.T, path string) { func touchEmptyFile(t *testing.T, path string) {
err := os.MkdirAll(filepath.Dir(path), 0700) err := os.MkdirAll(filepath.Dir(path), 0o700)
require.NoError(t, err) require.NoError(t, err)
f, err := os.Create(path) f, err := os.Create(path)
require.NoError(t, err) require.NoError(t, err)

View File

@ -15,8 +15,7 @@ func VerifyCliVersion() bundle.Mutator {
return &verifyCliVersion{} return &verifyCliVersion{}
} }
type verifyCliVersion struct { type verifyCliVersion struct{}
}
func (v *verifyCliVersion) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { func (v *verifyCliVersion) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
// No constraints specified, skip the check. // No constraints specified, skip the check.

View File

@ -1,7 +1,9 @@
package config package config
const Paused = "PAUSED" const (
const Unpaused = "UNPAUSED" Paused = "PAUSED"
Unpaused = "UNPAUSED"
)
type Presets struct { type Presets struct {
// NamePrefix to prepend to all resource names. // NamePrefix to prepend to all resource names.

View File

@ -49,7 +49,8 @@ func TestCustomMarshallerIsImplemented(t *testing.T) {
// Eg: resource.Job implements MarshalJSON // Eg: resource.Job implements MarshalJSON
v := reflect.Zero(vt.Elem()).Interface() v := reflect.Zero(vt.Elem()).Interface()
assert.NotPanics(t, func() { assert.NotPanics(t, func() {
json.Marshal(v) _, err := json.Marshal(v)
assert.NoError(t, err)
}, "Resource %s does not have a custom marshaller", field.Name) }, "Resource %s does not have a custom marshaller", field.Name)
// Unmarshalling a *resourceStruct will panic if the resource does not have a custom unmarshaller // Unmarshalling a *resourceStruct will panic if the resource does not have a custom unmarshaller
@ -58,7 +59,8 @@ func TestCustomMarshallerIsImplemented(t *testing.T) {
// Eg: *resource.Job implements UnmarshalJSON // Eg: *resource.Job implements UnmarshalJSON
v = reflect.New(vt.Elem()).Interface() v = reflect.New(vt.Elem()).Interface()
assert.NotPanics(t, func() { assert.NotPanics(t, func() {
json.Unmarshal([]byte("{}"), v) err := json.Unmarshal([]byte("{}"), v)
assert.NoError(t, err)
}, "Resource %s does not have a custom unmarshaller", field.Name) }, "Resource %s does not have a custom unmarshaller", field.Name)
} }
} }

View File

@ -100,7 +100,7 @@ func TestRootMergeTargetOverridesWithMode(t *testing.T) {
}, },
}, },
} }
root.initializeDynamicValue() require.NoError(t, root.initializeDynamicValue())
require.NoError(t, root.MergeTargetOverrides("development")) require.NoError(t, root.MergeTargetOverrides("development"))
assert.Equal(t, Development, root.Bundle.Mode) assert.Equal(t, Development, root.Bundle.Mode)
} }
@ -156,7 +156,7 @@ func TestRootMergeTargetOverridesWithVariables(t *testing.T) {
}, },
}, },
} }
root.initializeDynamicValue() require.NoError(t, root.initializeDynamicValue())
require.NoError(t, root.MergeTargetOverrides("development")) require.NoError(t, root.MergeTargetOverrides("development"))
assert.Equal(t, "bar", root.Variables["foo"].Default) assert.Equal(t, "bar", root.Variables["foo"].Default)
assert.Equal(t, "foo var", root.Variables["foo"].Description) assert.Equal(t, "foo var", root.Variables["foo"].Description)
@ -168,7 +168,6 @@ func TestRootMergeTargetOverridesWithVariables(t *testing.T) {
"key1": "value1", "key1": "value1",
}, root.Variables["complex"].Default) }, root.Variables["complex"].Default)
assert.Equal(t, "complex var", root.Variables["complex"].Description) assert.Equal(t, "complex var", root.Variables["complex"].Description)
} }
func TestIsFullVariableOverrideDef(t *testing.T) { func TestIsFullVariableOverrideDef(t *testing.T) {
@ -252,5 +251,4 @@ func TestIsFullVariableOverrideDef(t *testing.T) {
for i, tc := range testCases { for i, tc := range testCases {
assert.Equal(t, tc.expected, isFullVariableOverrideDef(tc.value), "test case %d", i) assert.Equal(t, tc.expected, isFullVariableOverrideDef(tc.value), "test case %d", i)
} }
} }

View File

@ -13,8 +13,7 @@ func FilesToSync() bundle.ReadOnlyMutator {
return &filesToSync{} return &filesToSync{}
} }
type filesToSync struct { type filesToSync struct{}
}
func (v *filesToSync) Name() string { func (v *filesToSync) Name() string {
return "validate:files_to_sync" return "validate:files_to_sync"

View File

@ -2,6 +2,7 @@ package validate
import ( import (
"context" "context"
"path/filepath"
"testing" "testing"
"github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle"
@ -81,7 +82,7 @@ func TestFilesToSync_EverythingIgnored(t *testing.T) {
b := setupBundleForFilesToSyncTest(t) b := setupBundleForFilesToSyncTest(t)
// Ignore all files. // Ignore all files.
testutil.WriteFile(t, "*\n.*\n", b.BundleRootPath, ".gitignore") testutil.WriteFile(t, filepath.Join(b.BundleRootPath, ".gitignore"), "*\n.*\n")
ctx := context.Background() ctx := context.Background()
rb := bundle.ReadOnly(b) rb := bundle.ReadOnly(b)

View File

@ -15,8 +15,7 @@ import (
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
type folderPermissions struct { type folderPermissions struct{}
}
// Apply implements bundle.ReadOnlyMutator. // Apply implements bundle.ReadOnlyMutator.
func (f *folderPermissions) Apply(ctx context.Context, b bundle.ReadOnlyBundle) diag.Diagnostics { func (f *folderPermissions) Apply(ctx context.Context, b bundle.ReadOnlyBundle) diag.Diagnostics {

View File

@ -13,8 +13,7 @@ func JobClusterKeyDefined() bundle.ReadOnlyMutator {
return &jobClusterKeyDefined{} return &jobClusterKeyDefined{}
} }
type jobClusterKeyDefined struct { type jobClusterKeyDefined struct{}
}
func (v *jobClusterKeyDefined) Name() string { func (v *jobClusterKeyDefined) Name() string {
return "validate:job_cluster_key_defined" return "validate:job_cluster_key_defined"

View File

@ -17,8 +17,7 @@ func JobTaskClusterSpec() bundle.ReadOnlyMutator {
return &jobTaskClusterSpec{} return &jobTaskClusterSpec{}
} }
type jobTaskClusterSpec struct { type jobTaskClusterSpec struct{}
}
func (v *jobTaskClusterSpec) Name() string { func (v *jobTaskClusterSpec) Name() string {
return "validate:job_task_cluster_spec" return "validate:job_task_cluster_spec"

View File

@ -175,7 +175,6 @@ func TestValidateSingleNodeClusterFailForJobClusters(t *testing.T) {
Paths: []dyn.Path{dyn.MustPathFromString("resources.jobs.foo.job_clusters[0].new_cluster")}, Paths: []dyn.Path{dyn.MustPathFromString("resources.jobs.foo.job_clusters[0].new_cluster")},
}, },
}, diags) }, diags)
}) })
} }
} }

View File

@ -8,8 +8,7 @@ import (
"github.com/databricks/cli/libs/dyn" "github.com/databricks/cli/libs/dyn"
) )
type validate struct { type validate struct{}
}
type location struct { type location struct {
path string path string

View File

@ -17,8 +17,7 @@ func ValidateSyncPatterns() bundle.ReadOnlyMutator {
return &validateSyncPatterns{} return &validateSyncPatterns{}
} }
type validateSyncPatterns struct { type validateSyncPatterns struct{}
}
func (v *validateSyncPatterns) Name() string { func (v *validateSyncPatterns) Name() string {
return "validate:validate_sync_patterns" return "validate:validate_sync_patterns"

View File

@ -42,7 +42,6 @@ func TestLookup_Empty(t *testing.T) {
// No string representation for an invalid lookup // No string representation for an invalid lookup
assert.Empty(t, lookup.String()) assert.Empty(t, lookup.String())
} }
func TestLookup_Multiple(t *testing.T) { func TestLookup_Multiple(t *testing.T) {

View File

@ -20,7 +20,6 @@ func (l resolveCluster) Resolve(ctx context.Context, w *databricks.WorkspaceClie
ClusterSources: []compute.ClusterSource{compute.ClusterSourceApi, compute.ClusterSourceUi}, ClusterSources: []compute.ClusterSource{compute.ClusterSourceApi, compute.ClusterSourceUi},
}, },
}) })
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -11,6 +11,7 @@ import (
"github.com/databricks/cli/libs/databrickscfg" "github.com/databricks/cli/libs/databrickscfg"
"github.com/databricks/databricks-sdk-go/config" "github.com/databricks/databricks-sdk-go/config"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func setupWorkspaceTest(t *testing.T) string { func setupWorkspaceTest(t *testing.T) string {
@ -42,11 +43,12 @@ func TestWorkspaceResolveProfileFromHost(t *testing.T) {
setupWorkspaceTest(t) setupWorkspaceTest(t)
// This works if there is a config file with a matching profile. // This works if there is a config file with a matching profile.
databrickscfg.SaveToProfile(context.Background(), &config.Config{ err := databrickscfg.SaveToProfile(context.Background(), &config.Config{
Profile: "default", Profile: "default",
Host: "https://abc.cloud.databricks.com", Host: "https://abc.cloud.databricks.com",
Token: "123", Token: "123",
}) })
require.NoError(t, err)
client, err := w.Client() client, err := w.Client()
assert.NoError(t, err) assert.NoError(t, err)
@ -57,12 +59,13 @@ func TestWorkspaceResolveProfileFromHost(t *testing.T) {
home := setupWorkspaceTest(t) home := setupWorkspaceTest(t)
// This works if there is a config file with a matching profile. // This works if there is a config file with a matching profile.
databrickscfg.SaveToProfile(context.Background(), &config.Config{ err := databrickscfg.SaveToProfile(context.Background(), &config.Config{
ConfigFile: filepath.Join(home, "customcfg"), ConfigFile: filepath.Join(home, "customcfg"),
Profile: "custom", Profile: "custom",
Host: "https://abc.cloud.databricks.com", Host: "https://abc.cloud.databricks.com",
Token: "123", Token: "123",
}) })
require.NoError(t, err)
t.Setenv("DATABRICKS_CONFIG_FILE", filepath.Join(home, "customcfg")) t.Setenv("DATABRICKS_CONFIG_FILE", filepath.Join(home, "customcfg"))
client, err := w.Client() client, err := w.Client()
@ -90,12 +93,13 @@ func TestWorkspaceVerifyProfileForHost(t *testing.T) {
setupWorkspaceTest(t) setupWorkspaceTest(t)
// This works if there is a config file with a matching profile. // This works if there is a config file with a matching profile.
databrickscfg.SaveToProfile(context.Background(), &config.Config{ err := databrickscfg.SaveToProfile(context.Background(), &config.Config{
Profile: "abc", Profile: "abc",
Host: "https://abc.cloud.databricks.com", Host: "https://abc.cloud.databricks.com",
}) })
require.NoError(t, err)
_, err := w.Client() _, err = w.Client()
assert.NoError(t, err) assert.NoError(t, err)
}) })
@ -103,12 +107,13 @@ func TestWorkspaceVerifyProfileForHost(t *testing.T) {
setupWorkspaceTest(t) setupWorkspaceTest(t)
// This works if there is a config file with a matching profile. // This works if there is a config file with a matching profile.
databrickscfg.SaveToProfile(context.Background(), &config.Config{ err := databrickscfg.SaveToProfile(context.Background(), &config.Config{
Profile: "abc", Profile: "abc",
Host: "https://def.cloud.databricks.com", Host: "https://def.cloud.databricks.com",
}) })
require.NoError(t, err)
_, err := w.Client() _, err = w.Client()
assert.ErrorContains(t, err, "config host mismatch") assert.ErrorContains(t, err, "config host mismatch")
}) })
@ -116,14 +121,15 @@ func TestWorkspaceVerifyProfileForHost(t *testing.T) {
home := setupWorkspaceTest(t) home := setupWorkspaceTest(t)
// This works if there is a config file with a matching profile. // This works if there is a config file with a matching profile.
databrickscfg.SaveToProfile(context.Background(), &config.Config{ err := databrickscfg.SaveToProfile(context.Background(), &config.Config{
ConfigFile: filepath.Join(home, "customcfg"), ConfigFile: filepath.Join(home, "customcfg"),
Profile: "abc", Profile: "abc",
Host: "https://abc.cloud.databricks.com", Host: "https://abc.cloud.databricks.com",
}) })
require.NoError(t, err)
t.Setenv("DATABRICKS_CONFIG_FILE", filepath.Join(home, "customcfg")) t.Setenv("DATABRICKS_CONFIG_FILE", filepath.Join(home, "customcfg"))
_, err := w.Client() _, err = w.Client()
assert.NoError(t, err) assert.NoError(t, err)
}) })
@ -131,14 +137,15 @@ func TestWorkspaceVerifyProfileForHost(t *testing.T) {
home := setupWorkspaceTest(t) home := setupWorkspaceTest(t)
// This works if there is a config file with a matching profile. // This works if there is a config file with a matching profile.
databrickscfg.SaveToProfile(context.Background(), &config.Config{ err := databrickscfg.SaveToProfile(context.Background(), &config.Config{
ConfigFile: filepath.Join(home, "customcfg"), ConfigFile: filepath.Join(home, "customcfg"),
Profile: "abc", Profile: "abc",
Host: "https://def.cloud.databricks.com", Host: "https://def.cloud.databricks.com",
}) })
require.NoError(t, err)
t.Setenv("DATABRICKS_CONFIG_FILE", filepath.Join(home, "customcfg")) t.Setenv("DATABRICKS_CONFIG_FILE", filepath.Join(home, "customcfg"))
_, err := w.Client() _, err = w.Client()
assert.ErrorContains(t, err, "config host mismatch") assert.ErrorContains(t, err, "config host mismatch")
}) })
} }

View File

@ -15,7 +15,7 @@ func (d *DeferredMutator) Name() string {
return "deferred" return "deferred"
} }
func Defer(mutator Mutator, finally Mutator) Mutator { func Defer(mutator, finally Mutator) Mutator {
return &DeferredMutator{ return &DeferredMutator{
mutator: mutator, mutator: mutator,
finally: finally, finally: finally,

View File

@ -19,7 +19,7 @@ func (t *mutatorWithError) Name() string {
func (t *mutatorWithError) Apply(_ context.Context, b *Bundle) diag.Diagnostics { func (t *mutatorWithError) Apply(_ context.Context, b *Bundle) diag.Diagnostics {
t.applyCalled++ t.applyCalled++
return diag.Errorf(t.errorMsg) return diag.Errorf(t.errorMsg) // nolint:govet
} }
func TestDeferredMutatorWhenAllMutatorsSucceed(t *testing.T) { func TestDeferredMutatorWhenAllMutatorsSucceed(t *testing.T) {

View File

@ -15,8 +15,10 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
) )
const DeploymentStateFileName = "deployment.json" const (
const DeploymentStateVersion = 1 DeploymentStateFileName = "deployment.json"
DeploymentStateVersion = 1
)
type File struct { type File struct {
LocalPath string `json:"local_path"` LocalPath string `json:"local_path"`
@ -132,7 +134,7 @@ func (f Filelist) ToSlice(root vfs.Path) []fileset.File {
return files return files
} }
func isLocalStateStale(local io.Reader, remote io.Reader) bool { func isLocalStateStale(local, remote io.Reader) bool {
localState, err := loadState(local) localState, err := loadState(local)
if err != nil { if err != nil {
return true return true

View File

@ -44,7 +44,7 @@ func (s *statePull) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostic
return diag.FromErr(err) return diag.FromErr(err)
} }
local, err := os.OpenFile(statePath, os.O_CREATE|os.O_RDWR, 0600) local, err := os.OpenFile(statePath, os.O_CREATE|os.O_RDWR, 0o600)
if err != nil { if err != nil {
return diag.FromErr(err) return diag.FromErr(err)
} }
@ -62,8 +62,14 @@ func (s *statePull) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostic
} }
// Truncating the file before writing // Truncating the file before writing
local.Truncate(0) err = local.Truncate(0)
local.Seek(0, 0) if err != nil {
return diag.FromErr(err)
}
_, err = local.Seek(0, 0)
if err != nil {
return diag.FromErr(err)
}
// Write file to disk. // Write file to disk.
log.Infof(ctx, "Writing remote deployment state file to local cache directory") log.Infof(ctx, "Writing remote deployment state file to local cache directory")

View File

@ -99,7 +99,7 @@ func testStatePull(t *testing.T, opts statePullOpts) {
snapshotPath, err := sync.SnapshotPath(opts) snapshotPath, err := sync.SnapshotPath(opts)
require.NoError(t, err) require.NoError(t, err)
err = os.WriteFile(snapshotPath, []byte("snapshot"), 0644) err = os.WriteFile(snapshotPath, []byte("snapshot"), 0o644)
require.NoError(t, err) require.NoError(t, err)
} }
@ -110,7 +110,7 @@ func testStatePull(t *testing.T, opts statePullOpts) {
data, err := json.Marshal(opts.localState) data, err := json.Marshal(opts.localState)
require.NoError(t, err) require.NoError(t, err)
err = os.WriteFile(statePath, data, 0644) err = os.WriteFile(statePath, data, 0o644)
require.NoError(t, err) require.NoError(t, err)
} }

View File

@ -74,7 +74,7 @@ func TestStatePush(t *testing.T) {
data, err := json.Marshal(state) data, err := json.Marshal(state)
require.NoError(t, err) require.NoError(t, err)
err = os.WriteFile(statePath, data, 0644) err = os.WriteFile(statePath, data, 0o644)
require.NoError(t, err) require.NoError(t, err)
diags := bundle.Apply(ctx, b, s) diags := bundle.Apply(ctx, b, s)

View File

@ -17,8 +17,7 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
) )
type stateUpdate struct { type stateUpdate struct{}
}
func (s *stateUpdate) Name() string { func (s *stateUpdate) Name() string {
return "deploy:state-update" return "deploy:state-update"
@ -57,7 +56,7 @@ func (s *stateUpdate) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnost
return diag.FromErr(err) return diag.FromErr(err)
} }
// Write the state back to the file. // Write the state back to the file.
f, err := os.OpenFile(statePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0600) f, err := os.OpenFile(statePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o600)
if err != nil { if err != nil {
log.Infof(ctx, "Unable to open deployment state file: %s", err) log.Infof(ctx, "Unable to open deployment state file: %s", err)
return diag.FromErr(err) return diag.FromErr(err)

View File

@ -119,7 +119,7 @@ func TestStateUpdateWithExistingState(t *testing.T) {
data, err := json.Marshal(state) data, err := json.Marshal(state)
require.NoError(t, err) require.NoError(t, err)
err = os.WriteFile(statePath, data, 0644) err = os.WriteFile(statePath, data, 0o644)
require.NoError(t, err) require.NoError(t, err)
diags := bundle.Apply(ctx, b, s) diags := bundle.Apply(ctx, b, s)

View File

@ -42,8 +42,7 @@ func collectDashboardsFromState(ctx context.Context, b *bundle.Bundle) ([]dashbo
return dashboards, nil return dashboards, nil
} }
type checkDashboardsModifiedRemotely struct { type checkDashboardsModifiedRemotely struct{}
}
func (l *checkDashboardsModifiedRemotely) Name() string { func (l *checkDashboardsModifiedRemotely) Name() string {
return "CheckDashboardsModifiedRemotely" return "CheckDashboardsModifiedRemotely"

View File

@ -139,7 +139,7 @@ func writeFakeDashboardState(t *testing.T, ctx context.Context, b *bundle.Bundle
require.NoError(t, err) require.NoError(t, err)
// Write fake state file. // Write fake state file.
testutil.WriteFile(t, ` testutil.WriteFile(t, filepath.Join(tfDir, TerraformStateFileName), `
{ {
"version": 4, "version": 4,
"terraform_version": "1.5.5", "terraform_version": "1.5.5",
@ -187,5 +187,5 @@ func writeFakeDashboardState(t *testing.T, ctx context.Context, b *bundle.Bundle
} }
] ]
} }
`, filepath.Join(tfDir, TerraformStateFileName)) `)
} }

View File

@ -23,8 +23,7 @@ func (e ErrResourceIsRunning) Error() string {
return fmt.Sprintf("%s %s is running", e.resourceType, e.resourceId) return fmt.Sprintf("%s %s is running", e.resourceType, e.resourceId)
} }
type checkRunningResources struct { type checkRunningResources struct{}
}
func (l *checkRunningResources) Name() string { func (l *checkRunningResources) Name() string {
return "check-running-resources" return "check-running-resources"

View File

@ -43,7 +43,7 @@ func convertToResourceStruct[T any](t *testing.T, resource *T, data any) {
} }
func TestBundleToTerraformJob(t *testing.T) { func TestBundleToTerraformJob(t *testing.T) {
var src = resources.Job{ src := resources.Job{
JobSettings: &jobs.JobSettings{ JobSettings: &jobs.JobSettings{
Name: "my job", Name: "my job",
JobClusters: []jobs.JobCluster{ JobClusters: []jobs.JobCluster{
@ -71,7 +71,7 @@ func TestBundleToTerraformJob(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Jobs: map[string]*resources.Job{ Jobs: map[string]*resources.Job{
"my_job": &src, "my_job": &src,
@ -93,7 +93,7 @@ func TestBundleToTerraformJob(t *testing.T) {
} }
func TestBundleToTerraformJobPermissions(t *testing.T) { func TestBundleToTerraformJobPermissions(t *testing.T) {
var src = resources.Job{ src := resources.Job{
Permissions: []resources.Permission{ Permissions: []resources.Permission{
{ {
Level: "CAN_VIEW", Level: "CAN_VIEW",
@ -102,7 +102,7 @@ func TestBundleToTerraformJobPermissions(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Jobs: map[string]*resources.Job{ Jobs: map[string]*resources.Job{
"my_job": &src, "my_job": &src,
@ -121,7 +121,7 @@ func TestBundleToTerraformJobPermissions(t *testing.T) {
} }
func TestBundleToTerraformJobTaskLibraries(t *testing.T) { func TestBundleToTerraformJobTaskLibraries(t *testing.T) {
var src = resources.Job{ src := resources.Job{
JobSettings: &jobs.JobSettings{ JobSettings: &jobs.JobSettings{
Name: "my job", Name: "my job",
Tasks: []jobs.Task{ Tasks: []jobs.Task{
@ -139,7 +139,7 @@ func TestBundleToTerraformJobTaskLibraries(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Jobs: map[string]*resources.Job{ Jobs: map[string]*resources.Job{
"my_job": &src, "my_job": &src,
@ -158,7 +158,7 @@ func TestBundleToTerraformJobTaskLibraries(t *testing.T) {
} }
func TestBundleToTerraformForEachTaskLibraries(t *testing.T) { func TestBundleToTerraformForEachTaskLibraries(t *testing.T) {
var src = resources.Job{ src := resources.Job{
JobSettings: &jobs.JobSettings{ JobSettings: &jobs.JobSettings{
Name: "my job", Name: "my job",
Tasks: []jobs.Task{ Tasks: []jobs.Task{
@ -182,7 +182,7 @@ func TestBundleToTerraformForEachTaskLibraries(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Jobs: map[string]*resources.Job{ Jobs: map[string]*resources.Job{
"my_job": &src, "my_job": &src,
@ -201,7 +201,7 @@ func TestBundleToTerraformForEachTaskLibraries(t *testing.T) {
} }
func TestBundleToTerraformPipeline(t *testing.T) { func TestBundleToTerraformPipeline(t *testing.T) {
var src = resources.Pipeline{ src := resources.Pipeline{
PipelineSpec: &pipelines.PipelineSpec{ PipelineSpec: &pipelines.PipelineSpec{
Name: "my pipeline", Name: "my pipeline",
Libraries: []pipelines.PipelineLibrary{ Libraries: []pipelines.PipelineLibrary{
@ -239,7 +239,7 @@ func TestBundleToTerraformPipeline(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Pipelines: map[string]*resources.Pipeline{ Pipelines: map[string]*resources.Pipeline{
"my_pipeline": &src, "my_pipeline": &src,
@ -262,7 +262,7 @@ func TestBundleToTerraformPipeline(t *testing.T) {
} }
func TestBundleToTerraformPipelinePermissions(t *testing.T) { func TestBundleToTerraformPipelinePermissions(t *testing.T) {
var src = resources.Pipeline{ src := resources.Pipeline{
Permissions: []resources.Permission{ Permissions: []resources.Permission{
{ {
Level: "CAN_VIEW", Level: "CAN_VIEW",
@ -271,7 +271,7 @@ func TestBundleToTerraformPipelinePermissions(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Pipelines: map[string]*resources.Pipeline{ Pipelines: map[string]*resources.Pipeline{
"my_pipeline": &src, "my_pipeline": &src,
@ -290,7 +290,7 @@ func TestBundleToTerraformPipelinePermissions(t *testing.T) {
} }
func TestBundleToTerraformModel(t *testing.T) { func TestBundleToTerraformModel(t *testing.T) {
var src = resources.MlflowModel{ src := resources.MlflowModel{
Model: &ml.Model{ Model: &ml.Model{
Name: "name", Name: "name",
Description: "description", Description: "description",
@ -307,7 +307,7 @@ func TestBundleToTerraformModel(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Models: map[string]*resources.MlflowModel{ Models: map[string]*resources.MlflowModel{
"my_model": &src, "my_model": &src,
@ -330,7 +330,7 @@ func TestBundleToTerraformModel(t *testing.T) {
} }
func TestBundleToTerraformModelPermissions(t *testing.T) { func TestBundleToTerraformModelPermissions(t *testing.T) {
var src = resources.MlflowModel{ src := resources.MlflowModel{
Model: &ml.Model{ Model: &ml.Model{
Name: "name", Name: "name",
}, },
@ -342,7 +342,7 @@ func TestBundleToTerraformModelPermissions(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Models: map[string]*resources.MlflowModel{ Models: map[string]*resources.MlflowModel{
"my_model": &src, "my_model": &src,
@ -361,13 +361,13 @@ func TestBundleToTerraformModelPermissions(t *testing.T) {
} }
func TestBundleToTerraformExperiment(t *testing.T) { func TestBundleToTerraformExperiment(t *testing.T) {
var src = resources.MlflowExperiment{ src := resources.MlflowExperiment{
Experiment: &ml.Experiment{ Experiment: &ml.Experiment{
Name: "name", Name: "name",
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Experiments: map[string]*resources.MlflowExperiment{ Experiments: map[string]*resources.MlflowExperiment{
"my_experiment": &src, "my_experiment": &src,
@ -384,7 +384,7 @@ func TestBundleToTerraformExperiment(t *testing.T) {
} }
func TestBundleToTerraformExperimentPermissions(t *testing.T) { func TestBundleToTerraformExperimentPermissions(t *testing.T) {
var src = resources.MlflowExperiment{ src := resources.MlflowExperiment{
Experiment: &ml.Experiment{ Experiment: &ml.Experiment{
Name: "name", Name: "name",
}, },
@ -396,7 +396,7 @@ func TestBundleToTerraformExperimentPermissions(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Experiments: map[string]*resources.MlflowExperiment{ Experiments: map[string]*resources.MlflowExperiment{
"my_experiment": &src, "my_experiment": &src,
@ -415,7 +415,7 @@ func TestBundleToTerraformExperimentPermissions(t *testing.T) {
} }
func TestBundleToTerraformModelServing(t *testing.T) { func TestBundleToTerraformModelServing(t *testing.T) {
var src = resources.ModelServingEndpoint{ src := resources.ModelServingEndpoint{
CreateServingEndpoint: &serving.CreateServingEndpoint{ CreateServingEndpoint: &serving.CreateServingEndpoint{
Name: "name", Name: "name",
Config: serving.EndpointCoreConfigInput{ Config: serving.EndpointCoreConfigInput{
@ -439,7 +439,7 @@ func TestBundleToTerraformModelServing(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
ModelServingEndpoints: map[string]*resources.ModelServingEndpoint{ ModelServingEndpoints: map[string]*resources.ModelServingEndpoint{
"my_model_serving_endpoint": &src, "my_model_serving_endpoint": &src,
@ -462,7 +462,7 @@ func TestBundleToTerraformModelServing(t *testing.T) {
} }
func TestBundleToTerraformModelServingPermissions(t *testing.T) { func TestBundleToTerraformModelServingPermissions(t *testing.T) {
var src = resources.ModelServingEndpoint{ src := resources.ModelServingEndpoint{
CreateServingEndpoint: &serving.CreateServingEndpoint{ CreateServingEndpoint: &serving.CreateServingEndpoint{
Name: "name", Name: "name",
@ -492,7 +492,7 @@ func TestBundleToTerraformModelServingPermissions(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
ModelServingEndpoints: map[string]*resources.ModelServingEndpoint{ ModelServingEndpoints: map[string]*resources.ModelServingEndpoint{
"my_model_serving_endpoint": &src, "my_model_serving_endpoint": &src,
@ -511,7 +511,7 @@ func TestBundleToTerraformModelServingPermissions(t *testing.T) {
} }
func TestBundleToTerraformRegisteredModel(t *testing.T) { func TestBundleToTerraformRegisteredModel(t *testing.T) {
var src = resources.RegisteredModel{ src := resources.RegisteredModel{
CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{ CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{
Name: "name", Name: "name",
CatalogName: "catalog", CatalogName: "catalog",
@ -520,7 +520,7 @@ func TestBundleToTerraformRegisteredModel(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
RegisteredModels: map[string]*resources.RegisteredModel{ RegisteredModels: map[string]*resources.RegisteredModel{
"my_registered_model": &src, "my_registered_model": &src,
@ -540,7 +540,7 @@ func TestBundleToTerraformRegisteredModel(t *testing.T) {
} }
func TestBundleToTerraformRegisteredModelGrants(t *testing.T) { func TestBundleToTerraformRegisteredModelGrants(t *testing.T) {
var src = resources.RegisteredModel{ src := resources.RegisteredModel{
CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{ CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{
Name: "name", Name: "name",
CatalogName: "catalog", CatalogName: "catalog",
@ -554,7 +554,7 @@ func TestBundleToTerraformRegisteredModelGrants(t *testing.T) {
}, },
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
RegisteredModels: map[string]*resources.RegisteredModel{ RegisteredModels: map[string]*resources.RegisteredModel{
"my_registered_model": &src, "my_registered_model": &src,
@ -573,14 +573,14 @@ func TestBundleToTerraformRegisteredModelGrants(t *testing.T) {
} }
func TestBundleToTerraformDeletedResources(t *testing.T) { func TestBundleToTerraformDeletedResources(t *testing.T) {
var job1 = resources.Job{ job1 := resources.Job{
JobSettings: &jobs.JobSettings{}, JobSettings: &jobs.JobSettings{},
} }
var job2 = resources.Job{ job2 := resources.Job{
ModifiedStatus: resources.ModifiedStatusDeleted, ModifiedStatus: resources.ModifiedStatusDeleted,
JobSettings: &jobs.JobSettings{}, JobSettings: &jobs.JobSettings{},
} }
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Jobs: map[string]*resources.Job{ Jobs: map[string]*resources.Job{
"my_job1": &job1, "my_job1": &job1,
@ -601,10 +601,10 @@ func TestBundleToTerraformDeletedResources(t *testing.T) {
} }
func TestTerraformToBundleEmptyLocalResources(t *testing.T) { func TestTerraformToBundleEmptyLocalResources(t *testing.T) {
var config = config.Root{ config := config.Root{
Resources: config.Resources{}, Resources: config.Resources{},
} }
var tfState = resourcesState{ tfState := resourcesState{
Resources: []stateResource{ Resources: []stateResource{
{ {
Type: "databricks_job", Type: "databricks_job",
@ -736,7 +736,7 @@ func TestTerraformToBundleEmptyLocalResources(t *testing.T) {
} }
func TestTerraformToBundleEmptyRemoteResources(t *testing.T) { func TestTerraformToBundleEmptyRemoteResources(t *testing.T) {
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Jobs: map[string]*resources.Job{ Jobs: map[string]*resources.Job{
"test_job": { "test_job": {
@ -817,7 +817,7 @@ func TestTerraformToBundleEmptyRemoteResources(t *testing.T) {
}, },
}, },
} }
var tfState = resourcesState{ tfState := resourcesState{
Resources: nil, Resources: nil,
} }
err := TerraformToBundle(&tfState, &config) err := TerraformToBundle(&tfState, &config)
@ -860,7 +860,7 @@ func TestTerraformToBundleEmptyRemoteResources(t *testing.T) {
} }
func TestTerraformToBundleModifiedResources(t *testing.T) { func TestTerraformToBundleModifiedResources(t *testing.T) {
var config = config.Root{ config := config.Root{
Resources: config.Resources{ Resources: config.Resources{
Jobs: map[string]*resources.Job{ Jobs: map[string]*resources.Job{
"test_job": { "test_job": {
@ -996,7 +996,7 @@ func TestTerraformToBundleModifiedResources(t *testing.T) {
}, },
}, },
} }
var tfState = resourcesState{ tfState := resourcesState{
Resources: []stateResource{ Resources: []stateResource{
{ {
Type: "databricks_job", Type: "databricks_job",

View File

@ -145,7 +145,7 @@ func inheritEnvVars(ctx context.Context, environ map[string]string) error {
// This function is used for env vars set by the Databricks VSCode extension. The variables are intended to be used by the CLI // This function is used for env vars set by the Databricks VSCode extension. The variables are intended to be used by the CLI
// bundled with the Databricks VSCode extension, but users can use different CLI versions in the VSCode terminals, in which case we want to ignore // bundled with the Databricks VSCode extension, but users can use different CLI versions in the VSCode terminals, in which case we want to ignore
// the variables if that CLI uses different versions of the dependencies. // the variables if that CLI uses different versions of the dependencies.
func getEnvVarWithMatchingVersion(ctx context.Context, envVarName string, versionVarName string, currentVersion string) (string, error) { func getEnvVarWithMatchingVersion(ctx context.Context, envVarName, versionVarName, currentVersion string) (string, error) {
envValue := env.Get(ctx, envVarName) envValue := env.Get(ctx, envVarName)
versionValue := env.Get(ctx, versionVarName) versionValue := env.Get(ctx, versionVarName)

View File

@ -400,7 +400,7 @@ func TestFindExecPathFromEnvironmentWithCorrectVersionAndBinary(t *testing.T) {
require.Equal(t, tmpBinPath, b.Config.Bundle.Terraform.ExecPath) require.Equal(t, tmpBinPath, b.Config.Bundle.Terraform.ExecPath)
} }
func createTempFile(t *testing.T, dest string, name string, executable bool) string { func createTempFile(t *testing.T, dest, name string, executable bool) string {
binPath := filepath.Join(dest, name) binPath := filepath.Join(dest, name)
f, err := os.Create(binPath) f, err := os.Create(binPath)
require.NoError(t, err) require.NoError(t, err)
@ -409,7 +409,7 @@ func createTempFile(t *testing.T, dest string, name string, executable bool) str
require.NoError(t, err) require.NoError(t, err)
}() }()
if executable { if executable {
err = f.Chmod(0777) err = f.Chmod(0o777)
require.NoError(t, err) require.NoError(t, err)
} }
return binPath return binPath
@ -422,7 +422,7 @@ func TestGetEnvVarWithMatchingVersion(t *testing.T) {
tmp := t.TempDir() tmp := t.TempDir()
file := testutil.Touch(t, tmp, "bar") file := testutil.Touch(t, tmp, "bar")
var tc = []struct { tc := []struct {
envValue string envValue string
versionValue string versionValue string
currentVersion string currentVersion string

View File

@ -10,8 +10,7 @@ import (
"github.com/databricks/cli/libs/dyn/dynvar" "github.com/databricks/cli/libs/dyn/dynvar"
) )
type interpolateMutator struct { type interpolateMutator struct{}
}
func Interpolate() bundle.Mutator { func Interpolate() bundle.Mutator {
return &interpolateMutator{} return &interpolateMutator{}

View File

@ -5,15 +5,19 @@ import (
"github.com/hashicorp/go-version" "github.com/hashicorp/go-version"
) )
const TerraformStateFileName = "terraform.tfstate" const (
const TerraformConfigFileName = "bundle.tf.json" TerraformStateFileName = "terraform.tfstate"
TerraformConfigFileName = "bundle.tf.json"
)
// Users can provide their own terraform binary and databricks terraform provider by setting the following environment variables. // Users can provide their own terraform binary and databricks terraform provider by setting the following environment variables.
// This allows users to use the CLI in an air-gapped environments. See the `debug terraform` command. // This allows users to use the CLI in an air-gapped environments. See the `debug terraform` command.
const TerraformExecPathEnv = "DATABRICKS_TF_EXEC_PATH" const (
const TerraformVersionEnv = "DATABRICKS_TF_VERSION" TerraformExecPathEnv = "DATABRICKS_TF_EXEC_PATH"
const TerraformCliConfigPathEnv = "DATABRICKS_TF_CLI_CONFIG_FILE" TerraformVersionEnv = "DATABRICKS_TF_VERSION"
const TerraformProviderVersionEnv = "DATABRICKS_TF_PROVIDER_VERSION" TerraformCliConfigPathEnv = "DATABRICKS_TF_CLI_CONFIG_FILE"
TerraformProviderVersionEnv = "DATABRICKS_TF_PROVIDER_VERSION"
)
// Terraform CLI version to use and the corresponding checksums for it. The // Terraform CLI version to use and the corresponding checksums for it. The
// checksums are used to verify the integrity of the downloaded binary. Please // checksums are used to verify the integrity of the downloaded binary. Please
@ -26,8 +30,10 @@ const TerraformProviderVersionEnv = "DATABRICKS_TF_PROVIDER_VERSION"
// downloaded Terraform archive. // downloaded Terraform archive.
var TerraformVersion = version.Must(version.NewVersion("1.5.5")) var TerraformVersion = version.Must(version.NewVersion("1.5.5"))
const checksumLinuxArm64 = "b055aefe343d0b710d8a7afd31aeb702b37bbf4493bb9385a709991e48dfbcd2" const (
const checksumLinuxAmd64 = "ad0c696c870c8525357b5127680cd79c0bdf58179af9acd091d43b1d6482da4a" checksumLinuxArm64 = "b055aefe343d0b710d8a7afd31aeb702b37bbf4493bb9385a709991e48dfbcd2"
checksumLinuxAmd64 = "ad0c696c870c8525357b5127680cd79c0bdf58179af9acd091d43b1d6482da4a"
)
type Checksum struct { type Checksum struct {
LinuxArm64 string `json:"linux_arm64"` LinuxArm64 string `json:"linux_arm64"`

View File

@ -14,7 +14,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func downloadAndChecksum(t *testing.T, url string, expectedChecksum string) { func downloadAndChecksum(t *testing.T, url, expectedChecksum string) {
resp, err := http.Get(url) resp, err := http.Get(url)
require.NoError(t, err) require.NoError(t, err)
defer resp.Body.Close() defer resp.Body.Close()

View File

@ -2,7 +2,6 @@ package terraform
import ( import (
"context" "context"
"fmt"
"path/filepath" "path/filepath"
"github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle"
@ -57,7 +56,7 @@ func (p *plan) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
IsEmpty: !notEmpty, IsEmpty: !notEmpty,
} }
log.Debugf(ctx, fmt.Sprintf("Planning complete and persisted at %s\n", planPath)) log.Debugf(ctx, "Planning complete and persisted at %s\n", planPath)
return nil return nil
} }

View File

@ -104,7 +104,7 @@ func (l *statePull) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostic
localState, err := l.localState(ctx, b) localState, err := l.localState(ctx, b)
if errors.Is(err, fs.ErrNotExist) { if errors.Is(err, fs.ErrNotExist) {
log.Infof(ctx, "Local state file does not exist. Using remote Terraform state.") log.Infof(ctx, "Local state file does not exist. Using remote Terraform state.")
err := os.WriteFile(localStatePath, remoteContent, 0600) err := os.WriteFile(localStatePath, remoteContent, 0o600)
return diag.FromErr(err) return diag.FromErr(err)
} }
if err != nil { if err != nil {
@ -114,14 +114,14 @@ func (l *statePull) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostic
// If the lineage does not match, the Terraform state files do not correspond to the same deployment. // If the lineage does not match, the Terraform state files do not correspond to the same deployment.
if localState.Lineage != remoteState.Lineage { if localState.Lineage != remoteState.Lineage {
log.Infof(ctx, "Remote and local state lineages do not match. Using remote Terraform state. Invalidating local Terraform state.") log.Infof(ctx, "Remote and local state lineages do not match. Using remote Terraform state. Invalidating local Terraform state.")
err := os.WriteFile(localStatePath, remoteContent, 0600) err := os.WriteFile(localStatePath, remoteContent, 0o600)
return diag.FromErr(err) return diag.FromErr(err)
} }
// If the remote state is newer than the local state, we should use the remote state. // If the remote state is newer than the local state, we should use the remote state.
if remoteState.Serial > localState.Serial { if remoteState.Serial > localState.Serial {
log.Infof(ctx, "Remote state is newer than local state. Using remote Terraform state.") log.Infof(ctx, "Remote state is newer than local state. Using remote Terraform state.")
err := os.WriteFile(localStatePath, remoteContent, 0600) err := os.WriteFile(localStatePath, remoteContent, 0o600)
return diag.FromErr(err) return diag.FromErr(err)
} }

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertCluster(t *testing.T) { func TestConvertCluster(t *testing.T) {
var src = resources.Cluster{ src := resources.Cluster{
ClusterSpec: &compute.ClusterSpec{ ClusterSpec: &compute.ClusterSpec{
NumWorkers: 3, NumWorkers: 3,
SparkVersion: "13.3.x-scala2.12", SparkVersion: "13.3.x-scala2.12",
@ -93,5 +93,4 @@ func TestConvertCluster(t *testing.T) {
}, },
}, },
}, out.Permissions["cluster_my_cluster"]) }, out.Permissions["cluster_my_cluster"])
} }

View File

@ -17,7 +17,7 @@ const (
) )
// Marshal "serialized_dashboard" as JSON if it is set in the input but not in the output. // Marshal "serialized_dashboard" as JSON if it is set in the input but not in the output.
func marshalSerializedDashboard(vin dyn.Value, vout dyn.Value) (dyn.Value, error) { func marshalSerializedDashboard(vin, vout dyn.Value) (dyn.Value, error) {
// Skip if the "serialized_dashboard" field is already set. // Skip if the "serialized_dashboard" field is already set.
if v := vout.Get(serializedDashboardFieldName); v.IsValid() { if v := vout.Get(serializedDashboardFieldName); v.IsValid() {
return vout, nil return vout, nil

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertDashboard(t *testing.T) { func TestConvertDashboard(t *testing.T) {
var src = resources.Dashboard{ src := resources.Dashboard{
Dashboard: &dashboards.Dashboard{ Dashboard: &dashboards.Dashboard{
DisplayName: "my dashboard", DisplayName: "my dashboard",
WarehouseId: "f00dcafe", WarehouseId: "f00dcafe",
@ -60,7 +60,7 @@ func TestConvertDashboard(t *testing.T) {
} }
func TestConvertDashboardFilePath(t *testing.T) { func TestConvertDashboardFilePath(t *testing.T) {
var src = resources.Dashboard{ src := resources.Dashboard{
FilePath: "some/path", FilePath: "some/path",
} }
@ -84,7 +84,7 @@ func TestConvertDashboardFilePath(t *testing.T) {
} }
func TestConvertDashboardFilePathQuoted(t *testing.T) { func TestConvertDashboardFilePathQuoted(t *testing.T) {
var src = resources.Dashboard{ src := resources.Dashboard{
FilePath: `C:\foo\bar\baz\dashboard.lvdash.json`, FilePath: `C:\foo\bar\baz\dashboard.lvdash.json`,
} }
@ -108,7 +108,7 @@ func TestConvertDashboardFilePathQuoted(t *testing.T) {
} }
func TestConvertDashboardSerializedDashboardString(t *testing.T) { func TestConvertDashboardSerializedDashboardString(t *testing.T) {
var src = resources.Dashboard{ src := resources.Dashboard{
SerializedDashboard: `{ "json": true }`, SerializedDashboard: `{ "json": true }`,
} }
@ -127,7 +127,7 @@ func TestConvertDashboardSerializedDashboardString(t *testing.T) {
} }
func TestConvertDashboardSerializedDashboardAny(t *testing.T) { func TestConvertDashboardSerializedDashboardAny(t *testing.T) {
var src = resources.Dashboard{ src := resources.Dashboard{
SerializedDashboard: map[string]any{ SerializedDashboard: map[string]any{
"pages": []map[string]any{ "pages": []map[string]any{
{ {

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertExperiment(t *testing.T) { func TestConvertExperiment(t *testing.T) {
var src = resources.MlflowExperiment{ src := resources.MlflowExperiment{
Experiment: &ml.Experiment{ Experiment: &ml.Experiment{
Name: "name", Name: "name",
}, },

View File

@ -13,7 +13,7 @@ import (
) )
func TestConvertGrants(t *testing.T) { func TestConvertGrants(t *testing.T) {
var src = resources.RegisteredModel{ src := resources.RegisteredModel{
Grants: []resources.Grant{ Grants: []resources.Grant{
{ {
Privileges: []string{"EXECUTE", "FOO"}, Privileges: []string{"EXECUTE", "FOO"},
@ -45,7 +45,7 @@ func TestConvertGrants(t *testing.T) {
} }
func TestConvertGrantsNil(t *testing.T) { func TestConvertGrantsNil(t *testing.T) {
var src = resources.RegisteredModel{ src := resources.RegisteredModel{
Grants: nil, Grants: nil,
} }
@ -58,7 +58,7 @@ func TestConvertGrantsNil(t *testing.T) {
} }
func TestConvertGrantsEmpty(t *testing.T) { func TestConvertGrantsEmpty(t *testing.T) {
var src = resources.RegisteredModel{ src := resources.RegisteredModel{
Grants: []resources.Grant{}, Grants: []resources.Grant{},
} }

View File

@ -83,7 +83,6 @@ func convertJobResource(ctx context.Context, vin dyn.Value) (dyn.Value, error) {
"libraries": "library", "libraries": "library",
}) })
}) })
if err != nil { if err != nil {
return dyn.InvalidValue, err return dyn.InvalidValue, err
} }

View File

@ -15,7 +15,7 @@ import (
) )
func TestConvertJob(t *testing.T) { func TestConvertJob(t *testing.T) {
var src = resources.Job{ src := resources.Job{
JobSettings: &jobs.JobSettings{ JobSettings: &jobs.JobSettings{
Name: "my job", Name: "my job",
JobClusters: []jobs.JobCluster{ JobClusters: []jobs.JobCluster{

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertModelServingEndpoint(t *testing.T) { func TestConvertModelServingEndpoint(t *testing.T) {
var src = resources.ModelServingEndpoint{ src := resources.ModelServingEndpoint{
CreateServingEndpoint: &serving.CreateServingEndpoint{ CreateServingEndpoint: &serving.CreateServingEndpoint{
Name: "name", Name: "name",
Config: serving.EndpointCoreConfigInput{ Config: serving.EndpointCoreConfigInput{

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertModel(t *testing.T) { func TestConvertModel(t *testing.T) {
var src = resources.MlflowModel{ src := resources.MlflowModel{
Model: &ml.Model{ Model: &ml.Model{
Name: "name", Name: "name",
Description: "description", Description: "description",

View File

@ -13,7 +13,7 @@ import (
) )
func TestConvertPermissions(t *testing.T) { func TestConvertPermissions(t *testing.T) {
var src = resources.Job{ src := resources.Job{
Permissions: []resources.Permission{ Permissions: []resources.Permission{
{ {
Level: "CAN_VIEW", Level: "CAN_VIEW",
@ -59,7 +59,7 @@ func TestConvertPermissions(t *testing.T) {
} }
func TestConvertPermissionsNil(t *testing.T) { func TestConvertPermissionsNil(t *testing.T) {
var src = resources.Job{ src := resources.Job{
Permissions: nil, Permissions: nil,
} }
@ -72,7 +72,7 @@ func TestConvertPermissionsNil(t *testing.T) {
} }
func TestConvertPermissionsEmpty(t *testing.T) { func TestConvertPermissionsEmpty(t *testing.T) {
var src = resources.Job{ src := resources.Job{
Permissions: []resources.Permission{}, Permissions: []resources.Permission{},
} }

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertPipeline(t *testing.T) { func TestConvertPipeline(t *testing.T) {
var src = resources.Pipeline{ src := resources.Pipeline{
PipelineSpec: &pipelines.PipelineSpec{ PipelineSpec: &pipelines.PipelineSpec{
Name: "my pipeline", Name: "my pipeline",
Libraries: []pipelines.PipelineLibrary{ Libraries: []pipelines.PipelineLibrary{

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertQualityMonitor(t *testing.T) { func TestConvertQualityMonitor(t *testing.T) {
var src = resources.QualityMonitor{ src := resources.QualityMonitor{
TableName: "test_table_name", TableName: "test_table_name",
CreateMonitor: &catalog.CreateMonitor{ CreateMonitor: &catalog.CreateMonitor{
AssetsDir: "assets_dir", AssetsDir: "assets_dir",

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertRegisteredModel(t *testing.T) { func TestConvertRegisteredModel(t *testing.T) {
var src = resources.RegisteredModel{ src := resources.RegisteredModel{
CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{ CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{
Name: "name", Name: "name",
CatalogName: "catalog", CatalogName: "catalog",

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertSchema(t *testing.T) { func TestConvertSchema(t *testing.T) {
var src = resources.Schema{ src := resources.Schema{
CreateSchema: &catalog.CreateSchema{ CreateSchema: &catalog.CreateSchema{
Name: "name", Name: "name",
CatalogName: "catalog", CatalogName: "catalog",

View File

@ -14,7 +14,7 @@ import (
) )
func TestConvertVolume(t *testing.T) { func TestConvertVolume(t *testing.T) {
var src = resources.Volume{ src := resources.Volume{
CreateVolumeRequestContent: &catalog.CreateVolumeRequestContent{ CreateVolumeRequestContent: &catalog.CreateVolumeRequestContent{
CatalogName: "catalog", CatalogName: "catalog",
Comment: "comment", Comment: "comment",

View File

@ -11,7 +11,7 @@ import (
// definition uses the plural name. This function can convert between the two. // definition uses the plural name. This function can convert between the two.
func renameKeys(v dyn.Value, rename map[string]string) (dyn.Value, error) { func renameKeys(v dyn.Value, rename map[string]string) (dyn.Value, error) {
var err error var err error
var acc = dyn.V(map[string]dyn.Value{}) acc := dyn.V(map[string]dyn.Value{})
nv, err := dyn.Walk(v, func(p dyn.Path, v dyn.Value) (dyn.Value, error) { nv, err := dyn.Walk(v, func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
if len(p) == 0 { if len(p) == 0 {
@ -36,7 +36,6 @@ func renameKeys(v dyn.Value, rename map[string]string) (dyn.Value, error) {
// Pass through all other values. // Pass through all other values.
return v, dyn.ErrSkip return v, dyn.ErrSkip
}) })
if err != nil { if err != nil {
return dyn.InvalidValue, err return dyn.InvalidValue, err
} }

View File

@ -37,6 +37,6 @@ func (*unbind) Name() string {
return "terraform.Unbind" return "terraform.Unbind"
} }
func Unbind(resourceType string, resourceKey string) bundle.Mutator { func Unbind(resourceType, resourceKey string) bundle.Mutator {
return &unbind{resourceType: resourceType, resourceKey: resourceKey} return &unbind{resourceType: resourceType, resourceKey: resourceKey}
} }

View File

@ -10,7 +10,7 @@ import (
// with the path it is loaded from. // with the path it is loaded from.
func SetLocation(b *bundle.Bundle, prefix string, locations []dyn.Location) { func SetLocation(b *bundle.Bundle, prefix string, locations []dyn.Location) {
start := dyn.MustPathFromString(prefix) start := dyn.MustPathFromString(prefix)
b.Config.Mutate(func(root dyn.Value) (dyn.Value, error) { err := b.Config.Mutate(func(root dyn.Value) (dyn.Value, error) {
return dyn.Walk(root, func(p dyn.Path, v dyn.Value) (dyn.Value, error) { return dyn.Walk(root, func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
// If the path has the given prefix, set the location. // If the path has the given prefix, set the location.
if p.HasPrefix(start) { if p.HasPrefix(start) {
@ -27,4 +27,7 @@ func SetLocation(b *bundle.Bundle, prefix string, locations []dyn.Location) {
return v, dyn.ErrSkip return v, dyn.ErrSkip
}) })
}) })
if err != nil {
panic("Mutate() failed: " + err.Error())
}
} }

View File

@ -48,7 +48,8 @@ func addInterpolationPatterns(typ reflect.Type, s jsonschema.Schema) jsonschema.
{ {
Type: jsonschema.StringType, Type: jsonschema.StringType,
Pattern: interpolationPattern("var"), Pattern: interpolationPattern("var"),
}}, },
},
} }
case jsonschema.IntegerType, jsonschema.NumberType, jsonschema.BooleanType: case jsonschema.IntegerType, jsonschema.NumberType, jsonschema.BooleanType:
// primitives can have variable values, or references like ${bundle.xyz} // primitives can have variable values, or references like ${bundle.xyz}
@ -149,7 +150,7 @@ func main() {
} }
// Write the schema descriptions to the output file. // Write the schema descriptions to the output file.
err = os.WriteFile(outputFile, b, 0644) err = os.WriteFile(outputFile, b, 0o644)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -2,9 +2,8 @@ package generator
import ( import (
"fmt" "fmt"
"strings"
"slices" "slices"
"strings"
tfjson "github.com/hashicorp/terraform-json" tfjson "github.com/hashicorp/terraform-json"
"github.com/iancoleman/strcase" "github.com/iancoleman/strcase"
@ -70,6 +69,25 @@ func nestedBlockKeys(block *tfjson.SchemaBlock) []string {
return keys return keys
} }
func nestedField(name []string, k string, isRef bool) field {
// Collect field properties.
fieldName := strcase.ToCamel(k)
fieldTypePrefix := ""
if isRef {
fieldTypePrefix = "*"
} else {
fieldTypePrefix = "[]"
}
fieldType := fmt.Sprintf("%s%s", fieldTypePrefix, strings.Join(append(name, strcase.ToCamel(k)), ""))
fieldTag := fmt.Sprintf("%s,omitempty", k)
return field{
Name: fieldName,
Type: fieldType,
Tag: fieldTag,
}
}
func (w *walker) walk(block *tfjson.SchemaBlock, name []string) error { func (w *walker) walk(block *tfjson.SchemaBlock, name []string) error {
// Produce nested types before this block itself. // Produce nested types before this block itself.
// This ensures types are defined before they are referenced. // This ensures types are defined before they are referenced.
@ -91,10 +109,24 @@ func (w *walker) walk(block *tfjson.SchemaBlock, name []string) error {
v := block.Attributes[k] v := block.Attributes[k]
// Assert the attribute type is always set. // Assert the attribute type is always set.
if v.AttributeType == cty.NilType { if v.AttributeType == cty.NilType && v.AttributeNestedType == nil {
return fmt.Errorf("unexpected nil type for attribute %s", k) return fmt.Errorf("unexpected nil type for attribute %s", k)
} }
// If there is a nested type, walk it and continue to next attribute.
if v.AttributeNestedType != nil {
nestedBlock := &tfjson.SchemaBlock{
Attributes: v.AttributeNestedType.Attributes,
}
err := w.walk(nestedBlock, append(name, strcase.ToCamel(k)))
if err != nil {
return err
}
// Append to list of fields for type.
typ.Fields = append(typ.Fields, nestedField(name, k, v.AttributeNestedType.NestingMode == tfjson.SchemaNestingModeSingle))
continue
}
// Collect field properties. // Collect field properties.
fieldName := strcase.ToCamel(k) fieldName := strcase.ToCamel(k)
fieldType := processAttributeType(v.AttributeType) fieldType := processAttributeType(v.AttributeType)
@ -117,24 +149,8 @@ func (w *walker) walk(block *tfjson.SchemaBlock, name []string) error {
// Declare nested blocks. // Declare nested blocks.
for _, k := range nestedBlockKeys(block) { for _, k := range nestedBlockKeys(block) {
v := block.NestedBlocks[k] v := block.NestedBlocks[k]
// Collect field properties.
fieldName := strcase.ToCamel(k)
fieldTypePrefix := ""
if v.MaxItems == 1 {
fieldTypePrefix = "*"
} else {
fieldTypePrefix = "[]"
}
fieldType := fmt.Sprintf("%s%s", fieldTypePrefix, strings.Join(append(name, strcase.ToCamel(k)), ""))
fieldTag := fmt.Sprintf("%s,omitempty", k)
// Append to list of fields for type. // Append to list of fields for type.
typ.Fields = append(typ.Fields, field{ typ.Fields = append(typ.Fields, nestedField(name, k, v.MaxItems == 1))
Name: fieldName,
Type: fieldType,
Tag: fieldTag,
})
} }
// Append type to list of structs. // Append type to list of structs.

View File

@ -1,24 +1,27 @@
module github.com/databricks/cli/bundle/internal/tf/codegen module github.com/databricks/cli/bundle/internal/tf/codegen
go 1.21 go 1.23
toolchain go1.23.2
require ( require (
github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/go-version v1.7.0
github.com/hashicorp/hc-install v0.6.3 github.com/hashicorp/hc-install v0.9.0
github.com/hashicorp/terraform-exec v0.20.0 github.com/hashicorp/terraform-exec v0.21.0
github.com/hashicorp/terraform-json v0.21.0 github.com/hashicorp/terraform-json v0.23.0
github.com/iancoleman/strcase v0.3.0 github.com/iancoleman/strcase v0.3.0
github.com/zclconf/go-cty v1.14.2 github.com/zclconf/go-cty v1.15.1
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d
) )
require ( require (
github.com/ProtonMail/go-crypto v1.1.0-alpha.0 // indirect github.com/ProtonMail/go-crypto v1.1.3 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect github.com/cloudflare/circl v1.5.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
golang.org/x/crypto v0.19.0 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
golang.org/x/mod v0.15.0 // indirect golang.org/x/crypto v0.31.0 // indirect
golang.org/x/sys v0.17.0 // indirect golang.org/x/mod v0.22.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
) )

View File

@ -2,67 +2,79 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/ProtonMail/go-crypto v1.1.0-alpha.0 h1:nHGfwXmFvJrSR9xu8qL7BkO4DqTHXE9N5vPhgY2I+j0= github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
github.com/ProtonMail/go-crypto v1.1.0-alpha.0/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/hc-install v0.6.3 h1:yE/r1yJvWbtrJ0STwScgEnCanb0U9v7zp0Gbkmcoxqs= github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/hc-install v0.6.3/go.mod h1:KamGdbodYzlufbWh4r9NRo8y6GLHWZP2GBtdnms1Ln0= github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8JyYF3vpnuEo= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/terraform-json v0.21.0 h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U= github.com/hashicorp/hc-install v0.9.0 h1:2dIk8LcvANwtv3QZLckxcjyF5w8KVtiMxu6G6eLhghE=
github.com/hashicorp/terraform-json v0.21.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= github.com/hashicorp/hc-install v0.9.0/go.mod h1:+6vOP+mf3tuGgMApVYtmsnDoKWMDcFXeTxCACYZ8SFg=
github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ=
github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg=
github.com/hashicorp/terraform-json v0.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI=
github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c=
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/zclconf/go-cty v1.14.2 h1:kTG7lqmBou0Zkx35r6HJHUQTvaRPr5bIAf3AoHS0izI= github.com/zclconf/go-cty v1.15.1 h1:RgQYm4j2EvoBRXOPxhUvxPzRrGDo1eCOhHXuGfrj5S0=
github.com/zclconf/go-cty v1.14.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty v1.15.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=

View File

@ -1,3 +1,3 @@
package schema package schema
const ProviderVersion = "1.59.0" const ProviderVersion = "1.61.0"

View File

@ -25,9 +25,9 @@ const ProviderVersion = "{{ .ProviderVersion }}"
func NewRoot() *Root { func NewRoot() *Root {
return &Root{ return &Root{
Terraform: map[string]interface{}{ Terraform: map[string]any{
"required_providers": map[string]interface{}{ "required_providers": map[string]any{
"databricks": map[string]interface{}{ "databricks": map[string]any{
"source": ProviderSource, "source": ProviderSource,
"version": ProviderVersion, "version": ProviderVersion,
}, },

View File

@ -0,0 +1,107 @@
// Generated from Databricks Terraform provider schema. DO NOT EDIT.
package schema
type DataSourceAppAppActiveDeploymentDeploymentArtifacts struct {
SourceCodePath string `json:"source_code_path,omitempty"`
}
type DataSourceAppAppActiveDeploymentStatus struct {
Message string `json:"message,omitempty"`
State string `json:"state,omitempty"`
}
type DataSourceAppAppActiveDeployment struct {
CreateTime string `json:"create_time,omitempty"`
Creator string `json:"creator,omitempty"`
DeploymentArtifacts *DataSourceAppAppActiveDeploymentDeploymentArtifacts `json:"deployment_artifacts,omitempty"`
DeploymentId string `json:"deployment_id,omitempty"`
Mode string `json:"mode,omitempty"`
SourceCodePath string `json:"source_code_path,omitempty"`
Status *DataSourceAppAppActiveDeploymentStatus `json:"status,omitempty"`
UpdateTime string `json:"update_time,omitempty"`
}
type DataSourceAppAppAppStatus struct {
Message string `json:"message,omitempty"`
State string `json:"state,omitempty"`
}
type DataSourceAppAppComputeStatus struct {
Message string `json:"message,omitempty"`
State string `json:"state,omitempty"`
}
type DataSourceAppAppPendingDeploymentDeploymentArtifacts struct {
SourceCodePath string `json:"source_code_path,omitempty"`
}
type DataSourceAppAppPendingDeploymentStatus struct {
Message string `json:"message,omitempty"`
State string `json:"state,omitempty"`
}
type DataSourceAppAppPendingDeployment struct {
CreateTime string `json:"create_time,omitempty"`
Creator string `json:"creator,omitempty"`
DeploymentArtifacts *DataSourceAppAppPendingDeploymentDeploymentArtifacts `json:"deployment_artifacts,omitempty"`
DeploymentId string `json:"deployment_id,omitempty"`
Mode string `json:"mode,omitempty"`
SourceCodePath string `json:"source_code_path,omitempty"`
Status *DataSourceAppAppPendingDeploymentStatus `json:"status,omitempty"`
UpdateTime string `json:"update_time,omitempty"`
}
type DataSourceAppAppResourcesJob struct {
Id string `json:"id"`
Permission string `json:"permission"`
}
type DataSourceAppAppResourcesSecret struct {
Key string `json:"key"`
Permission string `json:"permission"`
Scope string `json:"scope"`
}
type DataSourceAppAppResourcesServingEndpoint struct {
Name string `json:"name"`
Permission string `json:"permission"`
}
type DataSourceAppAppResourcesSqlWarehouse struct {
Id string `json:"id"`
Permission string `json:"permission"`
}
type DataSourceAppAppResources struct {
Description string `json:"description,omitempty"`
Job *DataSourceAppAppResourcesJob `json:"job,omitempty"`
Name string `json:"name"`
Secret *DataSourceAppAppResourcesSecret `json:"secret,omitempty"`
ServingEndpoint *DataSourceAppAppResourcesServingEndpoint `json:"serving_endpoint,omitempty"`
SqlWarehouse *DataSourceAppAppResourcesSqlWarehouse `json:"sql_warehouse,omitempty"`
}
type DataSourceAppApp struct {
ActiveDeployment *DataSourceAppAppActiveDeployment `json:"active_deployment,omitempty"`
AppStatus *DataSourceAppAppAppStatus `json:"app_status,omitempty"`
ComputeStatus *DataSourceAppAppComputeStatus `json:"compute_status,omitempty"`
CreateTime string `json:"create_time,omitempty"`
Creator string `json:"creator,omitempty"`
DefaultSourceCodePath string `json:"default_source_code_path,omitempty"`
Description string `json:"description,omitempty"`
Name string `json:"name"`
PendingDeployment *DataSourceAppAppPendingDeployment `json:"pending_deployment,omitempty"`
Resources []DataSourceAppAppResources `json:"resources,omitempty"`
ServicePrincipalClientId string `json:"service_principal_client_id,omitempty"`
ServicePrincipalId int `json:"service_principal_id,omitempty"`
ServicePrincipalName string `json:"service_principal_name,omitempty"`
UpdateTime string `json:"update_time,omitempty"`
Updater string `json:"updater,omitempty"`
Url string `json:"url,omitempty"`
}
type DataSourceApp struct {
App *DataSourceAppApp `json:"app,omitempty"`
Name string `json:"name"`
}

View File

@ -0,0 +1,106 @@
// Generated from Databricks Terraform provider schema. DO NOT EDIT.
package schema
type DataSourceAppsAppActiveDeploymentDeploymentArtifacts struct {
SourceCodePath string `json:"source_code_path,omitempty"`
}
type DataSourceAppsAppActiveDeploymentStatus struct {
Message string `json:"message,omitempty"`
State string `json:"state,omitempty"`
}
type DataSourceAppsAppActiveDeployment struct {
CreateTime string `json:"create_time,omitempty"`
Creator string `json:"creator,omitempty"`
DeploymentArtifacts *DataSourceAppsAppActiveDeploymentDeploymentArtifacts `json:"deployment_artifacts,omitempty"`
DeploymentId string `json:"deployment_id,omitempty"`
Mode string `json:"mode,omitempty"`
SourceCodePath string `json:"source_code_path,omitempty"`
Status *DataSourceAppsAppActiveDeploymentStatus `json:"status,omitempty"`
UpdateTime string `json:"update_time,omitempty"`
}
type DataSourceAppsAppAppStatus struct {
Message string `json:"message,omitempty"`
State string `json:"state,omitempty"`
}
type DataSourceAppsAppComputeStatus struct {
Message string `json:"message,omitempty"`
State string `json:"state,omitempty"`
}
type DataSourceAppsAppPendingDeploymentDeploymentArtifacts struct {
SourceCodePath string `json:"source_code_path,omitempty"`
}
type DataSourceAppsAppPendingDeploymentStatus struct {
Message string `json:"message,omitempty"`
State string `json:"state,omitempty"`
}
type DataSourceAppsAppPendingDeployment struct {
CreateTime string `json:"create_time,omitempty"`
Creator string `json:"creator,omitempty"`
DeploymentArtifacts *DataSourceAppsAppPendingDeploymentDeploymentArtifacts `json:"deployment_artifacts,omitempty"`
DeploymentId string `json:"deployment_id,omitempty"`
Mode string `json:"mode,omitempty"`
SourceCodePath string `json:"source_code_path,omitempty"`
Status *DataSourceAppsAppPendingDeploymentStatus `json:"status,omitempty"`
UpdateTime string `json:"update_time,omitempty"`
}
type DataSourceAppsAppResourcesJob struct {
Id string `json:"id"`
Permission string `json:"permission"`
}
type DataSourceAppsAppResourcesSecret struct {
Key string `json:"key"`
Permission string `json:"permission"`
Scope string `json:"scope"`
}
type DataSourceAppsAppResourcesServingEndpoint struct {
Name string `json:"name"`
Permission string `json:"permission"`
}
type DataSourceAppsAppResourcesSqlWarehouse struct {
Id string `json:"id"`
Permission string `json:"permission"`
}
type DataSourceAppsAppResources struct {
Description string `json:"description,omitempty"`
Job *DataSourceAppsAppResourcesJob `json:"job,omitempty"`
Name string `json:"name"`
Secret *DataSourceAppsAppResourcesSecret `json:"secret,omitempty"`
ServingEndpoint *DataSourceAppsAppResourcesServingEndpoint `json:"serving_endpoint,omitempty"`
SqlWarehouse *DataSourceAppsAppResourcesSqlWarehouse `json:"sql_warehouse,omitempty"`
}
type DataSourceAppsApp struct {
ActiveDeployment *DataSourceAppsAppActiveDeployment `json:"active_deployment,omitempty"`
AppStatus *DataSourceAppsAppAppStatus `json:"app_status,omitempty"`
ComputeStatus *DataSourceAppsAppComputeStatus `json:"compute_status,omitempty"`
CreateTime string `json:"create_time,omitempty"`
Creator string `json:"creator,omitempty"`
DefaultSourceCodePath string `json:"default_source_code_path,omitempty"`
Description string `json:"description,omitempty"`
Name string `json:"name"`
PendingDeployment *DataSourceAppsAppPendingDeployment `json:"pending_deployment,omitempty"`
Resources []DataSourceAppsAppResources `json:"resources,omitempty"`
ServicePrincipalClientId string `json:"service_principal_client_id,omitempty"`
ServicePrincipalId int `json:"service_principal_id,omitempty"`
ServicePrincipalName string `json:"service_principal_name,omitempty"`
UpdateTime string `json:"update_time,omitempty"`
Updater string `json:"updater,omitempty"`
Url string `json:"url,omitempty"`
}
type DataSourceApps struct {
App []DataSourceAppsApp `json:"app,omitempty"`
}

View File

@ -69,6 +69,7 @@ type DataSourceFunctionsFunctions struct {
FullDataType string `json:"full_data_type,omitempty"` FullDataType string `json:"full_data_type,omitempty"`
FullName string `json:"full_name,omitempty"` FullName string `json:"full_name,omitempty"`
FunctionId string `json:"function_id,omitempty"` FunctionId string `json:"function_id,omitempty"`
InputParams []DataSourceFunctionsFunctionsInputParams `json:"input_params,omitempty"`
IsDeterministic bool `json:"is_deterministic,omitempty"` IsDeterministic bool `json:"is_deterministic,omitempty"`
IsNullCall bool `json:"is_null_call,omitempty"` IsNullCall bool `json:"is_null_call,omitempty"`
MetastoreId string `json:"metastore_id,omitempty"` MetastoreId string `json:"metastore_id,omitempty"`
@ -76,8 +77,10 @@ type DataSourceFunctionsFunctions struct {
Owner string `json:"owner,omitempty"` Owner string `json:"owner,omitempty"`
ParameterStyle string `json:"parameter_style,omitempty"` ParameterStyle string `json:"parameter_style,omitempty"`
Properties string `json:"properties,omitempty"` Properties string `json:"properties,omitempty"`
ReturnParams []DataSourceFunctionsFunctionsReturnParams `json:"return_params,omitempty"`
RoutineBody string `json:"routine_body,omitempty"` RoutineBody string `json:"routine_body,omitempty"`
RoutineDefinition string `json:"routine_definition,omitempty"` RoutineDefinition string `json:"routine_definition,omitempty"`
RoutineDependencies []DataSourceFunctionsFunctionsRoutineDependencies `json:"routine_dependencies,omitempty"`
SchemaName string `json:"schema_name,omitempty"` SchemaName string `json:"schema_name,omitempty"`
SecurityType string `json:"security_type,omitempty"` SecurityType string `json:"security_type,omitempty"`
SpecificName string `json:"specific_name,omitempty"` SpecificName string `json:"specific_name,omitempty"`
@ -85,14 +88,11 @@ type DataSourceFunctionsFunctions struct {
SqlPath string `json:"sql_path,omitempty"` SqlPath string `json:"sql_path,omitempty"`
UpdatedAt int `json:"updated_at,omitempty"` UpdatedAt int `json:"updated_at,omitempty"`
UpdatedBy string `json:"updated_by,omitempty"` UpdatedBy string `json:"updated_by,omitempty"`
InputParams []DataSourceFunctionsFunctionsInputParams `json:"input_params,omitempty"`
ReturnParams []DataSourceFunctionsFunctionsReturnParams `json:"return_params,omitempty"`
RoutineDependencies []DataSourceFunctionsFunctionsRoutineDependencies `json:"routine_dependencies,omitempty"`
} }
type DataSourceFunctions struct { type DataSourceFunctions struct {
CatalogName string `json:"catalog_name"` CatalogName string `json:"catalog_name"`
Functions []DataSourceFunctionsFunctions `json:"functions,omitempty"`
IncludeBrowse bool `json:"include_browse,omitempty"` IncludeBrowse bool `json:"include_browse,omitempty"`
SchemaName string `json:"schema_name"` SchemaName string `json:"schema_name"`
Functions []DataSourceFunctionsFunctions `json:"functions,omitempty"`
} }

Some files were not shown because too many files have changed in this diff Show More