Skip to content

Commit a3403f2

Browse files
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout Terraform, there isn't a great way to switch them out gradually. As a consequence, this huge commit gets us from the old world to a _compilable_ new world, but still has a large number of known test failures due to key functionality being stubbed out. The stubs here are for anything that interacts with providers, since we now need to do the follow-up work to similarly replace the old terraform.ResourceProvider interface with its replacement in the new "providers" package. That work, along with work to fix the remaining failing tests, will follow in subsequent commits. The aim here was to replace all references to terraform.State and its downstream types with states.State, terraform.Plan with plans.Plan, state.State with statemgr.State, and switch to the new implementations of the state and plan file formats. However, due to the number of times those types are used, this also ended up affecting numerous other parts of core such as terraform.Hook, the backend.Backend interface, and most of the CLI commands. Just as with 5861dbf before, I apologize in advance to the person who inevitably just found this huge commit while spelunking through the commit history.
1 parent cf68922 commit a3403f2

File tree

206 files changed

+7763
-10445
lines changed

Some content is hidden

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

206 files changed

+7763
-10445
lines changed

addrs/parse_ref_test.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ func TestParseRef(t *testing.T) {
2828
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
2929
End: tfdiags.SourcePos{Line: 1, Column: 12, Byte: 11},
3030
},
31-
Remaining: hcl.Traversal{},
3231
},
3332
``,
3433
},
@@ -80,7 +79,6 @@ func TestParseRef(t *testing.T) {
8079
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
8180
End: tfdiags.SourcePos{Line: 1, Column: 18, Byte: 17},
8281
},
83-
Remaining: hcl.Traversal{},
8482
},
8583
``,
8684
},
@@ -152,7 +150,6 @@ func TestParseRef(t *testing.T) {
152150
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
153151
End: tfdiags.SourcePos{Line: 1, Column: 25, Byte: 24},
154152
},
155-
Remaining: hcl.Traversal{},
156153
},
157154
``,
158155
},
@@ -178,7 +175,6 @@ func TestParseRef(t *testing.T) {
178175
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
179176
End: tfdiags.SourcePos{Line: 1, Column: 10, Byte: 9},
180177
},
181-
Remaining: hcl.Traversal{},
182178
},
183179
``,
184180
},
@@ -250,7 +246,6 @@ func TestParseRef(t *testing.T) {
250246
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
251247
End: tfdiags.SourcePos{Line: 1, Column: 11, Byte: 10},
252248
},
253-
Remaining: hcl.Traversal{},
254249
},
255250
``,
256251
},
@@ -269,7 +264,6 @@ func TestParseRef(t *testing.T) {
269264
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
270265
End: tfdiags.SourcePos{Line: 1, Column: 15, Byte: 14},
271266
},
272-
Remaining: hcl.Traversal{},
273267
},
274268
``,
275269
},
@@ -313,7 +307,6 @@ func TestParseRef(t *testing.T) {
313307
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
314308
End: tfdiags.SourcePos{Line: 1, Column: 18, Byte: 17},
315309
},
316-
Remaining: hcl.Traversal{},
317310
},
318311
``,
319312
},
@@ -333,7 +326,6 @@ func TestParseRef(t *testing.T) {
333326
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
334327
End: tfdiags.SourcePos{Line: 1, Column: 22, Byte: 21},
335328
},
336-
Remaining: hcl.Traversal{},
337329
},
338330
``,
339331
},
@@ -387,7 +379,6 @@ func TestParseRef(t *testing.T) {
387379
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
388380
End: tfdiags.SourcePos{Line: 1, Column: 12, Byte: 11},
389381
},
390-
Remaining: hcl.Traversal{},
391382
},
392383
``,
393384
},
@@ -433,7 +424,6 @@ func TestParseRef(t *testing.T) {
433424
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
434425
End: tfdiags.SourcePos{Line: 1, Column: 5, Byte: 4},
435426
},
436-
Remaining: hcl.Traversal{},
437427
},
438428
``,
439429
},
@@ -469,7 +459,6 @@ func TestParseRef(t *testing.T) {
469459
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
470460
End: tfdiags.SourcePos{Line: 1, Column: 20, Byte: 19},
471461
},
472-
Remaining: hcl.Traversal{},
473462
},
474463
``,
475464
},
@@ -517,7 +506,6 @@ func TestParseRef(t *testing.T) {
517506
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
518507
End: tfdiags.SourcePos{Line: 1, Column: 8, Byte: 7},
519508
},
520-
Remaining: hcl.Traversal{},
521509
},
522510
``,
523511
},
@@ -569,7 +557,6 @@ func TestParseRef(t *testing.T) {
569557
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
570558
End: tfdiags.SourcePos{Line: 1, Column: 18, Byte: 17},
571559
},
572-
Remaining: hcl.Traversal{},
573560
},
574561
``,
575562
},
@@ -641,7 +628,6 @@ func TestParseRef(t *testing.T) {
641628
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
642629
End: tfdiags.SourcePos{Line: 1, Column: 25, Byte: 24},
643630
},
644-
Remaining: hcl.Traversal{},
645631
},
646632
``,
647633
},

backend/atlas/backend.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ type Backend struct {
5050
opLock sync.Mutex
5151
}
5252

53+
var _ backend.Backend = (*Backend)(nil)
54+
5355
func (b *Backend) ConfigSchema() *configschema.Block {
5456
return &configschema.Block{
5557
Attributes: map[string]*configschema.Attribute{
@@ -160,15 +162,15 @@ func (b *Backend) Configure(obj cty.Value) tfdiags.Diagnostics {
160162
return diags
161163
}
162164

163-
func (b *Backend) States() ([]string, error) {
165+
func (b *Backend) Workspaces() ([]string, error) {
164166
return nil, backend.ErrNamedStatesNotSupported
165167
}
166168

167-
func (b *Backend) DeleteState(name string) error {
169+
func (b *Backend) DeleteWorkspace(name string) error {
168170
return backend.ErrNamedStatesNotSupported
169171
}
170172

171-
func (b *Backend) State(name string) (state.State, error) {
173+
func (b *Backend) StateMgr(name string) (state.State, error) {
172174
if name != backend.DefaultStateName {
173175
return nil, backend.ErrNamedStatesNotSupported
174176
}

backend/backend.go

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ import (
1313

1414
"github.com/hashicorp/terraform/addrs"
1515
"github.com/hashicorp/terraform/command/clistate"
16-
"github.com/hashicorp/terraform/configs/configschema"
1716
"github.com/hashicorp/terraform/configs"
1817
"github.com/hashicorp/terraform/configs/configload"
19-
"github.com/hashicorp/terraform/state"
18+
"github.com/hashicorp/terraform/configs/configschema"
19+
"github.com/hashicorp/terraform/plans"
20+
"github.com/hashicorp/terraform/plans/planfile"
21+
"github.com/hashicorp/terraform/states"
22+
"github.com/hashicorp/terraform/states/statemgr"
2023
"github.com/hashicorp/terraform/terraform"
2124
"github.com/hashicorp/terraform/tfdiags"
2225
)
@@ -25,25 +28,18 @@ import (
2528
// backend must have. This state cannot be deleted.
2629
const DefaultStateName = "default"
2730

28-
// This must be returned rather than a custom error so that the Terraform
29-
// CLI can detect it and handle it appropriately.
30-
var (
31-
// ErrDefaultStateNotSupported is returned when an operation does not support
32-
// using the default state, but requires a named state to be selected.
33-
ErrDefaultStateNotSupported = errors.New("default state not supported\n" +
34-
"You can create a new workspace with the \"workspace new\" command.")
35-
36-
// ErrNamedStatesNotSupported is returned when a named state operation
37-
// isn't supported.
38-
ErrNamedStatesNotSupported = errors.New("named states not supported")
39-
40-
// ErrOperationNotSupported is returned when an unsupported operation
41-
// is detected by the configured backend.
42-
ErrOperationNotSupported = errors.New("operation not supported")
43-
)
31+
// ErrWorkspacesNotSupported is an error returned when a caller attempts
32+
// to perform an operation on a workspace other than "default" for a
33+
// backend that doesn't support multiple workspaces.
34+
//
35+
// The caller can detect this to do special fallback behavior or produce
36+
// a specific, helpful error message.
37+
var ErrWorkspacesNotSupported = errors.New("workspaces not supported")
4438

45-
// InitFn is used to initialize a new backend.
46-
type InitFn func() Backend
39+
// ErrNamedStatesNotSupported is an older name for ErrWorkspacesNotSupported.
40+
//
41+
// Deprecated: Use ErrWorkspacesNotSupported instead.
42+
var ErrNamedStatesNotSupported = ErrWorkspacesNotSupported
4743

4844
// Backend is the minimal interface that must be implemented to enable Terraform.
4945
type Backend interface {
@@ -87,25 +83,26 @@ type Backend interface {
8783
// is undefined and no other methods may be called.
8884
Configure(cty.Value) tfdiags.Diagnostics
8985

90-
// State returns the current state for this environment. This state may
91-
// not be loaded locally: the proper APIs should be called on state.State
92-
// to load the state. If the state.State is a state.Locker, it's up to the
93-
// caller to call Lock and Unlock as needed.
86+
// StateMgr returns the state manager for the given workspace name.
9487
//
95-
// If the named state doesn't exist it will be created. The "default" state
96-
// is always assumed to exist.
97-
State(name string) (state.State, error)
98-
99-
// DeleteState removes the named state if it exists. It is an error
100-
// to delete the default state.
88+
// If the returned state manager also implements statemgr.Locker then
89+
// it's the caller's responsibility to call Lock and Unlock as appropriate.
10190
//
102-
// DeleteState does not prevent deleting a state that is in use. It is the
103-
// responsibility of the caller to hold a Lock on the state when calling
104-
// this method.
105-
DeleteState(name string) error
91+
// If the named workspace doesn't exist, or if it has no state, it will
92+
// be created either immediately on this call or the first time
93+
// PersistState is called, depending on the state manager implementation.
94+
StateMgr(workspace string) (statemgr.Full, error)
10695

107-
// States returns a list of configured named states.
108-
States() ([]string, error)
96+
// DeleteWorkspace removes the workspace with the given name if it exists.
97+
//
98+
// DeleteWorkspace cannot prevent deleting a state that is in use. It is
99+
// the responsibility of the caller to hold a Lock for the state manager
100+
// belonging to this workspace before calling this method.
101+
DeleteWorkspace(name string) error
102+
103+
// States returns a list of the names of all of the workspaces that exist
104+
// in this backend.
105+
Workspaces() ([]string, error)
109106
}
110107

111108
// Enhanced implements additional behavior on top of a normal backend.
@@ -136,7 +133,7 @@ type Enhanced interface {
136133
type Local interface {
137134
// Context returns a runnable terraform Context. The operation parameter
138135
// doesn't need a Type set but it needs other options set such as Module.
139-
Context(*Operation) (*terraform.Context, state.State, tfdiags.Diagnostics)
136+
Context(*Operation) (*terraform.Context, statemgr.Full, tfdiags.Diagnostics)
140137
}
141138

142139
// An operation represents an operation for Terraform to execute.
@@ -166,7 +163,7 @@ type Operation struct {
166163
PlanId string
167164
PlanRefresh bool // PlanRefresh will do a refresh before a plan
168165
PlanOutPath string // PlanOutPath is the path to save the plan
169-
PlanOutBackend *terraform.BackendState
166+
PlanOutBackend *plans.Backend
170167

171168
// ConfigDir is the path to the directory containing the configuration's
172169
// root module.
@@ -178,11 +175,10 @@ type Operation struct {
178175

179176
// Plan is a plan that was passed as an argument. This is valid for
180177
// plan and apply arguments but may not work for all backends.
181-
Plan *terraform.Plan
178+
PlanFile *planfile.Reader
182179

183180
// The options below are more self-explanatory and affect the runtime
184181
// behavior of the operation.
185-
AutoApprove bool
186182
Destroy bool
187183
Targets []addrs.Targetable
188184
Variables map[string]UnparsedVariableValue
@@ -259,7 +255,7 @@ type RunningOperation struct {
259255
// State is the final state after the operation completed. Persisting
260256
// this state is managed by the backend. This should only be read
261257
// after the operation completes to avoid read/write races.
262-
State *terraform.State
258+
State *states.State
263259
}
264260

265261
// OperationResult describes the result status of an operation.

0 commit comments

Comments
 (0)