Skip to content

Commit f380640

Browse files
committed
Update the backend.Backend interface to use diagnostics as return value from StateMgr method
1 parent 62b3ba5 commit f380640

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+640
-599
lines changed

internal/backend/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ type Backend interface {
9191
// If the named workspace doesn't exist, or if it has no state, it will
9292
// be created either immediately on this call or the first time
9393
// PersistState is called, depending on the state manager implementation.
94-
StateMgr(workspace string) (statemgr.Full, error)
94+
StateMgr(workspace string) (statemgr.Full, tfdiags.Diagnostics)
9595

9696
// DeleteWorkspace removes the workspace with the given name if it exists.
9797
//

internal/backend/local/backend.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,18 +257,20 @@ func (b *Local) DeleteWorkspace(name string, force bool) tfdiags.Diagnostics {
257257
return diags
258258
}
259259

260-
func (b *Local) StateMgr(name string) (statemgr.Full, error) {
260+
func (b *Local) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {
261+
var diags tfdiags.Diagnostics
262+
261263
// If we have a backend handling state, delegate to that.
262264
if b.Backend != nil {
263265
return b.Backend.StateMgr(name)
264266
}
265267

266268
if s, ok := b.states[name]; ok {
267-
return s, nil
269+
return s, diags
268270
}
269271

270272
if err := b.createState(name); err != nil {
271-
return nil, err
273+
return nil, diags.Append(err)
272274
}
273275

274276
statePath, stateOutPath, backupPath := b.StatePaths(name)
@@ -283,7 +285,7 @@ func (b *Local) StateMgr(name string) (statemgr.Full, error) {
283285
b.states = map[string]statemgr.Full{}
284286
}
285287
b.states[name] = s
286-
return s, nil
288+
return s, diags
287289
}
288290

289291
// Operation implements backendrun.OperationsBackend

internal/backend/local/backend_apply_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ type backendWithFailingState struct {
347347
Local
348348
}
349349

350-
func (b *backendWithFailingState) StateMgr(name string) (statemgr.Full, error) {
350+
func (b *backendWithFailingState) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {
351351
return &failingState{
352352
statemgr.NewFilesystem("failing-state.tfstate"),
353353
}, nil

internal/backend/local/backend_local.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ func (b *Local) localRun(op *backendrun.Operation) (*backendrun.LocalRun, *confi
4646

4747
// Get the latest state.
4848
log.Printf("[TRACE] backend/local: requesting state manager for workspace %q", op.Workspace)
49-
s, err := b.StateMgr(op.Workspace)
50-
if err != nil {
51-
diags = diags.Append(fmt.Errorf("error loading state: %w", err))
49+
s, sDiags := b.StateMgr(op.Workspace)
50+
if sDiags.HasErrors() {
51+
diags = diags.Append(fmt.Errorf("error loading state: %w", sDiags.Err()))
5252
return nil, nil, nil, diags
5353
}
5454
log.Printf("[TRACE] backend/local: requesting state lock for workspace %q", op.Workspace)

internal/backend/local/backend_local_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,9 @@ func TestLocalRun_stalePlan(t *testing.T) {
140140
}
141141

142142
// Refresh the state
143-
sm, err := b.StateMgr("")
144-
if err != nil {
145-
t.Fatalf("unexpected error: %s", err)
143+
sm, sDiags := b.StateMgr("")
144+
if sDiags.HasErrors() {
145+
t.Fatalf("unexpected error: %s", sDiags.Err())
146146
}
147147
if err := sm.RefreshState(); err != nil {
148148
t.Fatalf("unexpected error refreshing state: %s", err)
@@ -214,7 +214,7 @@ type backendWithStateStorageThatFailsRefresh struct {
214214

215215
var _ backend.Backend = backendWithStateStorageThatFailsRefresh{}
216216

217-
func (b backendWithStateStorageThatFailsRefresh) StateMgr(workspace string) (statemgr.Full, error) {
217+
func (b backendWithStateStorageThatFailsRefresh) StateMgr(workspace string) (statemgr.Full, tfdiags.Diagnostics) {
218218
return &stateStorageThatFailsRefresh{}, nil
219219
}
220220

internal/backend/local/backend_test.go

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ func TestLocal_useOfPathAttribute(t *testing.T) {
116116

117117
// State file at the `path` location doesn't exist yet
118118
workspace := backend.DefaultStateName
119-
stmgr, err := b.StateMgr(workspace)
120-
if err != nil {
121-
t.Fatalf("unexpected error returned from StateMgr")
119+
stmgr, sDiags := b.StateMgr(workspace)
120+
if sDiags.HasErrors() {
121+
t.Fatalf("unexpected error returned from StateMgr: %w", sDiags.Err())
122122
}
123123
defaultStatePath := fmt.Sprintf("%s/%s", td, path)
124124
if _, err := os.Stat(defaultStatePath); !strings.Contains(err.Error(), "no such file or directory") {
@@ -137,7 +137,7 @@ func TestLocal_useOfPathAttribute(t *testing.T) {
137137
Value: cty.StringVal("foobar"),
138138
},
139139
}
140-
err = stmgr.WriteState(s)
140+
err := stmgr.WriteState(s)
141141
if err != nil {
142142
t.Fatalf("unexpected error returned from WriteState")
143143
}
@@ -186,17 +186,17 @@ func TestLocal_pathAttributeWrongExtension(t *testing.T) {
186186

187187
// Writing to the default workspace's state creates a file
188188
workspace := backend.DefaultStateName
189-
stmgr, err := b.StateMgr(workspace)
190-
if err != nil {
191-
t.Fatalf("unexpected error returned from StateMgr")
189+
stmgr, sDiags := b.StateMgr(workspace)
190+
if sDiags.HasErrors() {
191+
t.Fatalf("unexpected error returned from StateMgr: %w", sDiags.Err())
192192
}
193193
s := states.NewState()
194194
s.RootOutputValues = map[string]*states.OutputValue{
195195
"foobar": {
196196
Value: cty.StringVal("foobar"),
197197
},
198198
}
199-
err = stmgr.WriteState(s)
199+
err := stmgr.WriteState(s)
200200
if err != nil {
201201
t.Fatalf("unexpected error returned from WriteState")
202202
}
@@ -233,17 +233,17 @@ func TestLocal_useOfWorkspaceDirAttribute(t *testing.T) {
233233
// Unaffected by the `workspace_dir` location.
234234
workspace := backend.DefaultStateName
235235
defaultStatePath := fmt.Sprintf("%s/terraform.tfstate", td)
236-
stmgr, err := b.StateMgr(workspace)
237-
if err != nil {
238-
t.Fatalf("unexpected error returned from StateMgr")
236+
stmgr, sDiags := b.StateMgr(workspace)
237+
if sDiags.HasErrors() {
238+
t.Fatalf("unexpected error returned from StateMgr: %w", sDiags.Err())
239239
}
240240
s := states.NewState()
241241
s.RootOutputValues = map[string]*states.OutputValue{
242242
"foobar": {
243243
Value: cty.StringVal("foobar"),
244244
},
245245
}
246-
err = stmgr.WriteState(s)
246+
err := stmgr.WriteState(s)
247247
if err != nil {
248248
t.Fatalf("unexpected error returned from WriteState")
249249
}
@@ -324,8 +324,8 @@ func TestLocal_addAndRemoveStates(t *testing.T) {
324324

325325
// Calling StateMgr with a new workspace name creates that workspace's state file.
326326
expectedA := "test_A"
327-
if _, err := b.StateMgr(expectedA); err != nil {
328-
t.Fatal(err)
327+
if _, sDiags := b.StateMgr(expectedA); sDiags.HasErrors() {
328+
t.Fatal(sDiags)
329329
}
330330

331331
states, wDiags = b.Workspaces()
@@ -340,8 +340,8 @@ func TestLocal_addAndRemoveStates(t *testing.T) {
340340

341341
// Creating another workspace appends it to the list of present workspaces.
342342
expectedB := "test_B"
343-
if _, err := b.StateMgr(expectedB); err != nil {
344-
t.Fatal(err)
343+
if _, sDiags := b.StateMgr(expectedB); sDiags.HasErrors() {
344+
t.Fatal(sDiags.Err())
345345
}
346346

347347
states, wDiags = b.Workspaces()
@@ -626,8 +626,9 @@ func (b *testDelegateBackend) Configure(obj cty.Value) tfdiags.Diagnostics {
626626
return diags.Append(errTestDelegateConfigure)
627627
}
628628

629-
func (b *testDelegateBackend) StateMgr(name string) (statemgr.Full, error) {
630-
return nil, errTestDelegateState
629+
func (b *testDelegateBackend) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {
630+
var diags tfdiags.Diagnostics
631+
return nil, diags.Append(errTestDelegateState)
631632
}
632633

633634
func (b *testDelegateBackend) Workspaces() ([]string, tfdiags.Diagnostics) {
@@ -661,7 +662,7 @@ func TestLocal_callsMethodsOnStateBackend(t *testing.T) {
661662
t.Fatal("expected errTestDelegateConfigure error, got:", diags.Err())
662663
}
663664

664-
if _, err := b.StateMgr("test"); err != errTestDelegateState {
665+
if _, sDiags := b.StateMgr("test"); err != errTestDelegateState {
665666
t.Fatal("expected errTestDelegateState, got:", err)
666667
}
667668

internal/backend/local/testing.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,10 @@ func (b *TestLocalSingleState) DeleteWorkspace(string, bool) tfdiags.Diagnostics
126126
return tfdiags.Diagnostics{}.Append(backend.ErrWorkspacesNotSupported)
127127
}
128128

129-
func (b *TestLocalSingleState) StateMgr(name string) (statemgr.Full, error) {
129+
func (b *TestLocalSingleState) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {
130+
var diags tfdiags.Diagnostics
130131
if name != backend.DefaultStateName {
131-
return nil, backend.ErrWorkspacesNotSupported
132+
return nil, diags.Append(backend.ErrWorkspacesNotSupported)
132133
}
133134

134135
return b.Local.StateMgr(name)
@@ -172,9 +173,10 @@ func (b *TestLocalNoDefaultState) DeleteWorkspace(name string, force bool) tfdia
172173
return b.Local.DeleteWorkspace(name, force)
173174
}
174175

175-
func (b *TestLocalNoDefaultState) StateMgr(name string) (statemgr.Full, error) {
176+
func (b *TestLocalNoDefaultState) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {
177+
var diags tfdiags.Diagnostics
176178
if name == backend.DefaultStateName {
177-
return nil, backend.ErrDefaultWorkspaceNotSupported
179+
return nil, diags.Append(backend.ErrDefaultWorkspaceNotSupported)
178180
}
179181
return b.Local.StateMgr(name)
180182
}

internal/backend/pluggable/pluggable.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func (p *Pluggable) DeleteWorkspace(workspace string, force bool) tfdiags.Diagno
133133
// state storage provider to interact with state.
134134
//
135135
// StateMgr implements backend.Backend
136-
func (p *Pluggable) StateMgr(workspace string) (statemgr.Full, error) {
136+
func (p *Pluggable) StateMgr(workspace string) (statemgr.Full, tfdiags.Diagnostics) {
137137
// repackages the provider's methods inside a state manager,
138138
// to be passed to the calling code that expects a statemgr.Full
139139
return remote.NewRemoteGRPC(p.provider, p.typeName, workspace), nil

internal/backend/remote-state/azure/backend_state.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ func (b *Backend) DeleteWorkspace(name string, _ bool) tfdiags.Diagnostics {
8585
return diags
8686
}
8787

88-
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
88+
func (b *Backend) StateMgr(name string) (statemgr.Full, tfdiags.Diagnostics) {
8989
ctx := newCtx()
90+
var diags tfdiags.Diagnostics
91+
9092
blobClient, err := b.apiClient.getBlobClient(ctx)
9193
if err != nil {
92-
return nil, err
94+
return nil, diags.Append(err)
9395
}
9496

9597
client := &RemoteClient{
@@ -104,7 +106,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
104106

105107
// Grab the value
106108
if err := stateMgr.RefreshState(); err != nil {
107-
return nil, err
109+
return nil, diags.Append(err)
108110
}
109111
//if this isn't the default state name, we need to create the object so
110112
//it's listed by States.
@@ -114,7 +116,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
114116
lockInfo.Operation = "init"
115117
lockId, err := client.Lock(lockInfo)
116118
if err != nil {
117-
return nil, fmt.Errorf("failed to lock azure state: %s", err)
119+
return nil, diags.Append(fmt.Errorf("failed to lock azure state: %s", err))
118120
}
119121

120122
// Local helper function so we can call it multiple places
@@ -128,29 +130,29 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
128130
// Grab the value
129131
if err := stateMgr.RefreshState(); err != nil {
130132
err = lockUnlock(err)
131-
return nil, err
133+
return nil, diags.Append(err)
132134
}
133135
//if this isn't the default state name, we need to create the object so
134136
//it's listed by States.
135137
if v := stateMgr.State(); v == nil {
136138
// If we have no state, we have to create an empty state
137139
if err := stateMgr.WriteState(states.NewState()); err != nil {
138140
err = lockUnlock(err)
139-
return nil, err
141+
return nil, diags.Append(err)
140142
}
141143
if err := stateMgr.PersistState(nil); err != nil {
142144
err = lockUnlock(err)
143-
return nil, err
145+
return nil, diags.Append(err)
144146
}
145147

146148
// Unlock, the state should now be initialized
147149
if err := lockUnlock(nil); err != nil {
148-
return nil, err
150+
return nil, diags.Append(err)
149151
}
150152
}
151153
}
152154

153-
return stateMgr, nil
155+
return stateMgr, diags
154156
}
155157

156158
func (b *Backend) client() *RemoteClient {

internal/backend/remote-state/azure/client_test.go

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ func TestRemoteClientAccessKeyBasic(t *testing.T) {
3838
"environment": m.env.Name,
3939
})).(*Backend)
4040

41-
state, err := b.StateMgr(backend.DefaultStateName)
42-
if err != nil {
43-
t.Fatal(err)
41+
state, sDiags := b.StateMgr(backend.DefaultStateName)
42+
if sDiags.HasErrors() {
43+
t.Fatal(sDiags.Err())
4444
}
4545

4646
remote.TestClient(t, state.(*remote.State).Client)
@@ -73,9 +73,9 @@ func TestRemoteClientManagedServiceIdentityBasic(t *testing.T) {
7373
"environment": m.env.Name,
7474
})).(*Backend)
7575

76-
state, err := b.StateMgr(backend.DefaultStateName)
77-
if err != nil {
78-
t.Fatal(err)
76+
state, sDiags := b.StateMgr(backend.DefaultStateName)
77+
if sDiags.HasErrors() {
78+
t.Fatal(sDiags.Err())
7979
}
8080

8181
remote.TestClient(t, state.(*remote.State).Client)
@@ -110,9 +110,9 @@ func TestRemoteClientSasTokenBasic(t *testing.T) {
110110
"environment": m.env.Name,
111111
})).(*Backend)
112112

113-
state, err := b.StateMgr(backend.DefaultStateName)
114-
if err != nil {
115-
t.Fatal(err)
113+
state, sDiags := b.StateMgr(backend.DefaultStateName)
114+
if sDiags.HasErrors() {
115+
t.Fatal(sDiags.Err())
116116
}
117117

118118
remote.TestClient(t, state.(*remote.State).Client)
@@ -146,9 +146,9 @@ func TestRemoteClientServicePrincipalBasic(t *testing.T) {
146146
"environment": m.env.Name,
147147
})).(*Backend)
148148

149-
state, err := b.StateMgr(backend.DefaultStateName)
150-
if err != nil {
151-
t.Fatal(err)
149+
state, sDiags := b.StateMgr(backend.DefaultStateName)
150+
if sDiags.HasErrors() {
151+
t.Fatal(sDiags.Err())
152152
}
153153

154154
remote.TestClient(t, state.(*remote.State).Client)
@@ -187,14 +187,14 @@ func TestRemoteClientAccessKeyLocks(t *testing.T) {
187187
"environment": m.env.Name,
188188
})).(*Backend)
189189

190-
s1, err := b1.StateMgr(backend.DefaultStateName)
191-
if err != nil {
192-
t.Fatal(err)
190+
s1, sDiags := b1.StateMgr(backend.DefaultStateName)
191+
if sDiags.HasErrors() {
192+
t.Fatal(sDiags.Err())
193193
}
194194

195-
s2, err := b2.StateMgr(backend.DefaultStateName)
196-
if err != nil {
197-
t.Fatal(err)
195+
s2, sDiags := b2.StateMgr(backend.DefaultStateName)
196+
if sDiags.HasErrors() {
197+
t.Fatal(sDiags.Err())
198198
}
199199

200200
remote.TestRemoteLocks(t, s1.(*remote.State).Client, s2.(*remote.State).Client)
@@ -241,14 +241,14 @@ func TestRemoteClientServicePrincipalLocks(t *testing.T) {
241241
"environment": m.env.Name,
242242
})).(*Backend)
243243

244-
s1, err := b1.StateMgr(backend.DefaultStateName)
245-
if err != nil {
246-
t.Fatal(err)
244+
s1, sDiags := b1.StateMgr(backend.DefaultStateName)
245+
if sDiags.HasErrors() {
246+
t.Fatal(sDiags.Err())
247247
}
248248

249-
s2, err := b2.StateMgr(backend.DefaultStateName)
250-
if err != nil {
251-
t.Fatal(err)
249+
s2, sDiags := b2.StateMgr(backend.DefaultStateName)
250+
if sDiags.HasErrors() {
251+
t.Fatal(sDiags.Err())
252252
}
253253

254254
remote.TestRemoteLocks(t, s1.(*remote.State).Client, s2.(*remote.State).Client)

0 commit comments

Comments
 (0)