Skip to content

Commit bd5cb0a

Browse files
committed
update
1 parent 7afc952 commit bd5cb0a

File tree

10 files changed

+76
-69
lines changed

10 files changed

+76
-69
lines changed

acceptance/bundle/deployment/migrate/basic/output.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
>>> musterr [CLI] bundle deployment migrate
3-
Error: no existing state found
3+
This command migrate existing terraform state file to direct deployment engine state. However, no existing local or remote state found.
4+
5+
To start using direct engine, deploy with DATABRICKS_BUNDLE_ENGINE=direct env var or bundle.engine="direct" in databricks.yml.
46

57
>>> DATABRICKS_BUNDLE_ENGINE=terraform [CLI] bundle deploy
68
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/migrate-basic-test/default/files...
@@ -101,3 +103,4 @@ Deployment complete!
101103
=== Should show that it's already migrated
102104
>>> musterr [CLI] bundle deployment migrate
103105
Error: already using direct engine
106+
Details: <local direct state serial=4 lineage="[UUID]">

acceptance/bundle/deployment/migrate/basic/script

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Migrating without state, should fail
1+
# Migrating without state, should print a message about missing state.
22
trace musterr $CLI bundle deployment migrate
33

44
trace DATABRICKS_BUNDLE_ENGINE=terraform $CLI bundle deploy

bundle/statemgmt/state_pull.go

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,19 @@ type StateDesc struct {
2929
Lineage string `json:"lineage"`
3030

3131
// additional fields describing state:
32-
content []byte
33-
isDirect bool `json:"-"`
34-
isLocal bool `json:"-"`
32+
Content []byte
33+
34+
IsDirect bool `json:"-"`
35+
IsLocal bool `json:"-"`
3536
}
3637

3738
func (s *StateDesc) String() string {
3839
kind := "terraform"
39-
if s.isDirect {
40+
if s.IsDirect {
4041
kind = "direct"
4142
}
4243
source := "remote"
43-
if s.isLocal {
44+
if s.IsLocal {
4445
source = "local"
4546
}
4647
return fmt.Sprintf("<%s %s state serial=%d lineage=%q>", source, kind, s.Serial, s.Lineage)
@@ -61,8 +62,8 @@ func localRead(ctx context.Context, fullPath string, isDirect bool) *StateDesc {
6162
logdiag.LogError(ctx, fmt.Errorf("parsing %s: %w", filepath.ToSlash(fullPath), err))
6263
}
6364

64-
state.isDirect = isDirect
65-
state.isLocal = true
65+
state.IsDirect = isDirect
66+
state.IsLocal = true
6667
// not populating .content, not needed for local
6768

6869
return state
@@ -88,8 +89,8 @@ func _filerRead(ctx context.Context, f filer.Filer, path string) (*StateDesc, er
8889
return nil, fmt.Errorf("parsing state: %w", err)
8990
}
9091

91-
state.isLocal = false
92-
state.content = content
92+
state.IsLocal = false
93+
state.Content = content
9394
return state, nil
9495
}
9596

@@ -99,19 +100,19 @@ func filerRead(ctx context.Context, f filer.Filer, path string, isDirect bool) *
99100
logdiag.LogError(ctx, fmt.Errorf("reading %s: %w", path, err))
100101
} else if state != nil {
101102
log.Debugf(ctx, "read %s: %s", path, state.String())
102-
state.isDirect = isDirect
103+
state.IsDirect = isDirect
103104
}
104105
return state
105106
}
106107

107-
func PullResourcesState(ctx context.Context, b *bundle.Bundle, alwaysPull AlwaysPull) (context.Context, bool) {
108+
func PullResourcesState(ctx context.Context, b *bundle.Bundle, alwaysPull AlwaysPull) (context.Context, *StateDesc) {
108109
_, localPathDirect := b.StateFilenameDirect(ctx)
109110
_, localPathTerraform := b.StateFilenameTerraform(ctx)
110111

111112
states := readStates(ctx, b, alwaysPull)
112113

113114
if logdiag.HasError(ctx) {
114-
return ctx, false
115+
return ctx, nil
115116
}
116117

117118
var winner *StateDesc
@@ -122,12 +123,16 @@ func PullResourcesState(ctx context.Context, b *bundle.Bundle, alwaysPull Always
122123
isDirect, err := getDirectDeploymentEnv(ctx)
123124
if err != nil {
124125
logdiag.LogError(ctx, err)
125-
return ctx, false
126+
return ctx, nil
127+
}
128+
winner = &StateDesc{
129+
IsDirect: isDirect,
130+
IsLocal: true,
131+
// Lineage and Serial are empty
126132
}
127-
directDeployment = isDirect
128133
} else {
129134
winner = states[len(states)-1]
130-
directDeployment = winner.isDirect
135+
directDeployment = winner.IsDirect
131136
}
132137

133138
engine := "direct"
@@ -139,9 +144,9 @@ func PullResourcesState(ctx context.Context, b *bundle.Bundle, alwaysPull Always
139144
// Set the engine in the user agent
140145
ctx = useragent.InContext(ctx, "engine", engine)
141146

142-
if winner == nil {
143-
log.Infof(ctx, "No existing resource state found")
144-
return ctx, directDeployment
147+
if len(states) == 0 {
148+
// nothing to migrate, return
149+
return ctx, winner
145150
}
146151

147152
var stateStrs []string
@@ -158,20 +163,20 @@ func PullResourcesState(ctx context.Context, b *bundle.Bundle, alwaysPull Always
158163
lastLineage = state
159164
} else if lastLineage.Lineage != state.Lineage {
160165
logdiag.LogError(ctx, fmt.Errorf("lineage mismatch in state files: %s", strings.Join(stateStrs, ", ")))
161-
return ctx, directDeployment
166+
return ctx, winner
162167
}
163168
}
164169

165-
if winner.isLocal {
170+
if winner.IsLocal {
166171
// local state is fresh, nothing to do
167-
return ctx, directDeployment
172+
return ctx, winner
168173
}
169174

170-
if !winner.isLocal {
175+
if !winner.IsLocal {
171176
log.Info(ctx, "Remote state is newer than local state. Using remote resources state.")
172177

173178
localStatePath := localPathTerraform
174-
if winner.isDirect {
179+
if winner.IsDirect {
175180
localStatePath = localPathDirect
176181
}
177182

@@ -180,18 +185,18 @@ func PullResourcesState(ctx context.Context, b *bundle.Bundle, alwaysPull Always
180185
err := os.MkdirAll(localStateDir, 0o700)
181186
if err != nil {
182187
logdiag.LogError(ctx, err)
183-
return ctx, directDeployment
188+
return ctx, winner
184189
}
185190

186191
// TODO: write + rename
187-
err = os.WriteFile(localStatePath, winner.content, 0o600)
192+
err = os.WriteFile(localStatePath, winner.Content, 0o600)
188193
if err != nil {
189194
logdiag.LogError(ctx, err)
190-
return ctx, directDeployment
195+
return ctx, winner
191196
}
192197
}
193198

194-
return ctx, directDeployment
199+
return ctx, winner
195200
}
196201

197202
func readStates(ctx context.Context, b *bundle.Bundle, alwaysPull AlwaysPull) []*StateDesc {

cmd/bundle/debug/plan.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ func NewPlanCommand() *cobra.Command {
2424
Build: true,
2525
}
2626

27-
b, isDirectEngine, err := utils.ProcessBundleRet(cmd, opts)
27+
b, stateDesc, err := utils.ProcessBundleRet(cmd, opts)
2828
if err != nil {
2929
return err
3030
}
3131
ctx := cmd.Context()
32-
plan := phases.Plan(ctx, b, isDirectEngine)
32+
plan := phases.Plan(ctx, b, stateDesc.IsDirect)
3333
if logdiag.HasError(ctx) {
3434
return root.ErrAlreadyPrinted
3535
}

cmd/bundle/deployment/migrate.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package deployment
22

33
import (
4-
"errors"
54
"fmt"
65

76
"github.com/databricks/cli/bundle/deploy/terraform"
@@ -50,18 +49,21 @@ proper state management as it may cause resource conflicts.`,
5049
Build: true,
5150
}
5251

53-
b, err := utils.ProcessBundleWithOut(cmd, &opts)
52+
b, stateDesc, err := utils.ProcessBundleRet(cmd, opts)
5453
if err != nil {
5554
return err
5655
}
5756
ctx := cmd.Context()
5857

59-
if opts.Winner == nil {
60-
return errors.New("no existing state found")
58+
if stateDesc.Lineage == "" {
59+
cmdio.LogString(ctx, `This command migrate existing terraform state file to direct deployment engine state. However, no existing local or remote state found.
60+
61+
To start using direct engine, deploy with DATABRICKS_BUNDLE_ENGINE=direct env var or bundle.engine="direct" in databricks.yml.`)
62+
return root.ErrAlreadyPrinted
6163
}
6264

63-
if *b.DirectDeployment {
64-
return errors.New("already using direct engine")
65+
if stateDesc.IsDirect {
66+
return fmt.Errorf("already using direct engine\nDetails: %s", stateDesc.String())
6567
}
6668

6769
terraformResources, err := terraform.ParseResourcesState(ctx, b)
@@ -88,10 +90,9 @@ proper state management as it may cause resource conflicts.`,
8890
return fmt.Errorf("failed to create deployment plan: %w", err)
8991
}
9092

91-
// Create direct state with resource IDs from terraform
9293
directDB := dstate.Database{
93-
Serial: int(opts.Winner.Serial + 1), // Increment serial (convert int64 to int)
94-
Lineage: opts.Winner.Lineage, // Same lineage
94+
Serial: int(stateDesc.Serial + 1),
95+
Lineage: stateDesc.Lineage,
9596
State: make(map[string]dstate.ResourceEntry),
9697
}
9798

cmd/bundle/destroy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ func CommandBundleDestroy(cmd *cobra.Command, args []string, autoApprove, forceD
6565
// Do we need initialize phase here?
6666
}
6767

68-
b, isDirectEngine, err := utils.ProcessBundleRet(cmd, opts)
68+
b, stateDesc, err := utils.ProcessBundleRet(cmd, opts)
6969
if err != nil {
7070
return err
7171
}
7272

73-
phases.Destroy(cmd.Context(), b, isDirectEngine)
73+
phases.Destroy(cmd.Context(), b, stateDesc.IsDirect)
7474
if logdiag.HasError(cmd.Context()) {
7575
return root.ErrAlreadyPrinted
7676
}

cmd/bundle/generate/dashboard.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,13 +377,13 @@ func (d *dashboard) runForResource(ctx context.Context, b *bundle.Bundle) {
377377
return
378378
}
379379

380-
ctx, directDeployment := statemgmt.PullResourcesState(ctx, b, statemgmt.AlwaysPull(true))
380+
ctx, stateDesc := statemgmt.PullResourcesState(ctx, b, statemgmt.AlwaysPull(true))
381381
if logdiag.HasError(ctx) {
382382
return
383383
}
384384

385385
bundle.ApplySeqContext(ctx, b,
386-
statemgmt.Load(directDeployment),
386+
statemgmt.Load(stateDesc.IsDirect),
387387
)
388388
if logdiag.HasError(ctx) {
389389
return

cmd/bundle/plan.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ It is useful for previewing changes before running 'bundle deploy'.`,
5959
Build: true,
6060
}
6161

62-
b, isDirectEngine, err := utils.ProcessBundleRet(cmd, opts)
62+
b, stateDesc, err := utils.ProcessBundleRet(cmd, opts)
6363
if err != nil {
6464
return err
6565
}
6666
ctx := cmd.Context()
6767

68-
plan := phases.Plan(ctx, b, isDirectEngine)
68+
plan := phases.Plan(ctx, b, stateDesc.IsDirect)
6969
if logdiag.HasError(ctx) {
7070
return root.ErrAlreadyPrinted
7171
}

cmd/bundle/run.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,14 @@ Example usage:
166166
return executeScript(content, cmd, b)
167167
}
168168

169-
ctx, directDeployment := statemgmt.PullResourcesState(ctx, b, statemgmt.AlwaysPull(true))
169+
ctx, stateDesc := statemgmt.PullResourcesState(ctx, b, statemgmt.AlwaysPull(true))
170170
if logdiag.HasError(ctx) {
171171
return root.ErrAlreadyPrinted
172172
}
173173
cmd.SetContext(ctx)
174174

175175
bundle.ApplySeqContext(ctx, b,
176-
statemgmt.Load(directDeployment, statemgmt.ErrorOnEmptyState),
176+
statemgmt.Load(stateDesc.IsDirect, statemgmt.ErrorOnEmptyState),
177177
)
178178
if logdiag.HasError(ctx) {
179179
return root.ErrAlreadyPrinted

0 commit comments

Comments
 (0)