Skip to content

Commit 969c201

Browse files
committed
deployment migrate: drop plan check and --noplancheck flag
The command now reads from the local TF state file without invoking the Terraform binary, so there is nothing for the plan check to verify. Also simplify getCommonArgs to return only the display string (the args slice was only needed to forward to the plan subprocess). Co-authored-by: Isaac
1 parent 3a11350 commit 969c201

4 files changed

Lines changed: 14 additions & 93 deletions

File tree

bundle/direct/bundle_apply.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ func (b *DeploymentBundle) Apply(ctx context.Context, client *databricks.Workspa
106106

107107
// TODO: redo calcDiff to downgrade planned action if possible (?)
108108
err = d.Deploy(ctx, &b.StateDB, sv.Value, action, entry)
109-
110109
if err != nil {
111110
logdiag.LogError(ctx, fmt.Errorf("%s: %w", errorPrefix, err))
112111
return false

bundle/migrate/resolve_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,5 @@ func TestResolveFieldRefBool(t *testing.T) {
7474
s := &target{}
7575
err = structaccess.Set(s, fieldPath, value)
7676
assert.NoError(t, err, "Set should parse string %q into bool field", value)
77-
assert.Equal(t, true, s.AlwaysRunning)
77+
assert.True(t, s.AlwaysRunning)
7878
}

bundle/migrate/tf_state.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,9 @@ func ParseTFStateAttrs(path string) (TFStateAttrs, error) {
5757

5858
// tfSchemaTypeMap maps TF resource type name → schema struct type (via AllResources json tags).
5959
var tfSchemaTypeMap = sync.OnceValue(func() map[string]reflect.Type {
60-
t := reflect.TypeOf(tfschema.AllResources{})
60+
t := reflect.TypeFor[tfschema.AllResources]()
6161
m := make(map[string]reflect.Type, t.NumField())
62-
for i := range t.NumField() {
63-
f := t.Field(i)
62+
for f := range t.Fields() {
6463
tag := strings.Split(f.Tag.Get("json"), ",")[0]
6564
if tag != "" && tag != "-" {
6665
m[tag] = f.Type

cmd/bundle/deployment/migrate.go

Lines changed: 11 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package deployment
22

33
import (
4-
"bytes"
54
"context"
65
"encoding/json"
76
"errors"
87
"fmt"
98
"os"
10-
"os/exec"
119
"strings"
1210

1311
"github.com/databricks/cli/bundle"
@@ -28,95 +26,31 @@ import (
2826

2927
const backupSuffix = ".backup"
3028

31-
// runPlanCheck runs bundle plan and checks if there are any actions planned.
32-
// Returns error if plan fails or if there are actions planned.
33-
func runPlanCheck(cmd *cobra.Command, extraArgs []string, extraArgsStr string) error {
34-
ctx := cmd.Context()
35-
36-
executable, err := os.Executable()
37-
if err != nil {
38-
return fmt.Errorf("failed to get executable path: %w", err)
39-
}
40-
41-
args := []string{"bundle", "plan"}
42-
args = append(args, extraArgs...)
43-
44-
planCmd := exec.CommandContext(ctx, executable, args...)
45-
var stdout bytes.Buffer
46-
planCmd.Stdout = &stdout
47-
planCmd.Stderr = cmd.ErrOrStderr()
48-
49-
// Use the engine encoded in the state
50-
planCmd.Env = append(os.Environ(), "DATABRICKS_BUNDLE_ENGINE=terraform")
51-
52-
err = planCmd.Run()
53-
54-
// Output the plan stdout as is
55-
output := stdout.String()
56-
fmt.Fprint(cmd.OutOrStdout(), output)
57-
58-
if err != nil {
59-
msg := ""
60-
if exitErr, ok := errors.AsType[*exec.ExitError](err); ok {
61-
msg = fmt.Sprintf("exit code %d", exitErr.ExitCode())
62-
} else {
63-
msg = err.Error()
64-
}
65-
return fmt.Errorf("bundle plan failed with %s, aborting migration. To proceed with migration anyway, re-run the command with --noplancheck option", msg)
66-
}
67-
68-
if !strings.Contains(output, "Plan:") {
69-
return fmt.Errorf("cannot parse 'databricks bundle plan%s' output, aborting migration. Skip plan check with --noplancheck option", extraArgsStr)
70-
}
71-
72-
if !strings.Contains(output, "Plan: 0 to add, 0 to change, 0 to delete") {
73-
return fmt.Errorf("'databricks bundle plan%s' shows actions planned, aborting migration. Please run 'databricks bundle deploy%s' first to ensure your bundle is up to date, If actions persist after deploy, skip plan check with --noplancheck option", extraArgsStr, extraArgsStr)
74-
}
75-
76-
return nil
77-
}
78-
79-
func getCommonArgs(cmd *cobra.Command) ([]string, string) {
80-
var args []string
29+
func getCommonArgs(cmd *cobra.Command) string {
8130
var quotedArgs []string
8231

8332
if flag := cmd.Flag("target"); flag != nil && flag.Changed {
84-
target := flag.Value.String()
85-
if target != "" {
86-
args = append(args, "-t")
87-
args = append(args, target)
88-
quotedArgs = append(quotedArgs, "-t")
89-
quotedArgs = append(quotedArgs, shellquote.BashArg(target))
33+
if target := flag.Value.String(); target != "" {
34+
quotedArgs = append(quotedArgs, "-t", shellquote.BashArg(target))
9035
}
9136
}
9237
if flag := cmd.Flag("profile"); flag != nil && flag.Changed {
93-
profile := flag.Value.String()
94-
if profile != "" {
95-
args = append(args, "-p")
96-
args = append(args, profile)
97-
quotedArgs = append(quotedArgs, "-p")
98-
quotedArgs = append(quotedArgs, shellquote.BashArg(profile))
38+
if profile := flag.Value.String(); profile != "" {
39+
quotedArgs = append(quotedArgs, "-p", shellquote.BashArg(profile))
9940
}
10041
}
10142
if flag := cmd.Flag("var"); flag != nil && flag.Changed {
102-
varValues, err := cmd.Flags().GetStringSlice("var")
103-
if err == nil {
43+
if varValues, err := cmd.Flags().GetStringSlice("var"); err == nil {
10444
for _, v := range varValues {
105-
args = append(args, "--var")
106-
args = append(args, v)
107-
quotedArgs = append(quotedArgs, "--var")
108-
quotedArgs = append(quotedArgs, shellquote.BashArg(v))
45+
quotedArgs = append(quotedArgs, "--var", shellquote.BashArg(v))
10946
}
11047
}
11148
}
11249

113-
argsStr := ""
114-
115-
if len(quotedArgs) > 0 {
116-
argsStr = " " + strings.Join(quotedArgs, " ")
50+
if len(quotedArgs) == 0 {
51+
return ""
11752
}
118-
119-
return args, argsStr
53+
return " " + strings.Join(quotedArgs, " ")
12054
}
12155

12256
func newMigrateCommand() *cobra.Command {
@@ -134,11 +68,8 @@ to the workspace so that subsequent deploys of this bundle use direct deployment
13468
Args: root.NoArgs,
13569
}
13670

137-
var noPlanCheck bool
138-
cmd.Flags().BoolVar(&noPlanCheck, "noplancheck", false, "Skip running bundle plan before migration.")
139-
14071
cmd.RunE = func(cmd *cobra.Command, args []string) error {
141-
extraArgs, extraArgsStr := getCommonArgs(cmd)
72+
extraArgsStr := getCommonArgs(cmd)
14273

14374
// Clear the engine env var so migrate always uses terraform engine to read existing state,
14475
// regardless of what the user may have set in their environment.
@@ -199,14 +130,6 @@ To start using direct engine, set "engine: direct" under bundle in your databric
199130
return fmt.Errorf("state file %s already exists", localPath)
200131
}
201132

202-
// Run plan check unless --noplancheck is set
203-
if !noPlanCheck {
204-
cmdio.LogString(ctx, "Note: Migration should be done after a full deploy. Running plan now to verify that deployment was done:")
205-
if err = runPlanCheck(cmd, extraArgs, extraArgsStr); err != nil {
206-
return err
207-
}
208-
}
209-
210133
tfAttrs, err := migrate.ParseTFStateAttrs(localTerraformPath)
211134
if err != nil {
212135
return fmt.Errorf("failed to read terraform state attributes: %w", err)

0 commit comments

Comments
 (0)