Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions internal/backend/local/backend_local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,9 @@ func TestLocalRun_stalePlan(t *testing.T) {
UIMode: plans.NormalMode,
Changes: plans.NewChangesSrc(),
Backend: &plans.Backend{
Type: "local",
Config: backendConfigRaw,
Type: "local",
Config: backendConfigRaw,
Workspace: "default",
},
PrevRunState: states.NewState(),
PriorState: states.NewState(),
Expand Down
40 changes: 24 additions & 16 deletions internal/backend/local/backend_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,9 @@ func TestLocal_planOutputsChanged(t *testing.T) {
}
op.PlanOutBackend = &plans.Backend{
// Just a placeholder so that we can generate a valid plan file.
Type: "local",
Config: cfgRaw,
Type: "local",
Config: cfgRaw,
Workspace: "default",
}
run, err := b.Operation(context.Background(), op)
if err != nil {
Expand Down Expand Up @@ -263,8 +264,9 @@ func TestLocal_planModuleOutputsChanged(t *testing.T) {
t.Fatal(err)
}
op.PlanOutBackend = &plans.Backend{
Type: "local",
Config: cfgRaw,
Type: "local",
Config: cfgRaw,
Workspace: "default",
}
run, err := b.Operation(context.Background(), op)
if err != nil {
Expand Down Expand Up @@ -305,8 +307,9 @@ func TestLocal_planTainted(t *testing.T) {
}
op.PlanOutBackend = &plans.Backend{
// Just a placeholder so that we can generate a valid plan file.
Type: "local",
Config: cfgRaw,
Type: "local",
Config: cfgRaw,
Workspace: "default",
}
run, err := b.Operation(context.Background(), op)
if err != nil {
Expand Down Expand Up @@ -384,8 +387,9 @@ func TestLocal_planDeposedOnly(t *testing.T) {
}
op.PlanOutBackend = &plans.Backend{
// Just a placeholder so that we can generate a valid plan file.
Type: "local",
Config: cfgRaw,
Type: "local",
Config: cfgRaw,
Workspace: "default",
}
run, err := b.Operation(context.Background(), op)
if err != nil {
Expand Down Expand Up @@ -475,8 +479,9 @@ func TestLocal_planTainted_createBeforeDestroy(t *testing.T) {
}
op.PlanOutBackend = &plans.Backend{
// Just a placeholder so that we can generate a valid plan file.
Type: "local",
Config: cfgRaw,
Type: "local",
Config: cfgRaw,
Workspace: "default",
}
run, err := b.Operation(context.Background(), op)
if err != nil {
Expand Down Expand Up @@ -566,8 +571,9 @@ func TestLocal_planDestroy(t *testing.T) {
}
op.PlanOutBackend = &plans.Backend{
// Just a placeholder so that we can generate a valid plan file.
Type: "local",
Config: cfgRaw,
Type: "local",
Config: cfgRaw,
Workspace: "default",
}

run, err := b.Operation(context.Background(), op)
Expand Down Expand Up @@ -618,8 +624,9 @@ func TestLocal_planDestroy_withDataSources(t *testing.T) {
}
op.PlanOutBackend = &plans.Backend{
// Just a placeholder so that we can generate a valid plan file.
Type: "local",
Config: cfgRaw,
Type: "local",
Config: cfgRaw,
Workspace: "default",
}

run, err := b.Operation(context.Background(), op)
Expand Down Expand Up @@ -690,8 +697,9 @@ func TestLocal_planOutPathNoChange(t *testing.T) {
}
op.PlanOutBackend = &plans.Backend{
// Just a placeholder so that we can generate a valid plan file.
Type: "local",
Config: cfgRaw,
Type: "local",
Config: cfgRaw,
Workspace: "default",
}
op.PlanRefresh = true

Expand Down
5 changes: 3 additions & 2 deletions internal/command/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1087,8 +1087,9 @@ func TestApply_plan_remoteState(t *testing.T) {
}
planPath := testPlanFile(t, snap, state, &plans.Plan{
Backend: &plans.Backend{
Type: "http",
Config: backendConfigRaw,
Type: "http",
Config: backendConfigRaw,
Workspace: "default",
},
Changes: plans.NewChangesSrc(),
})
Expand Down
5 changes: 3 additions & 2 deletions internal/command/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ func testPlan(t *testing.T) *plans.Plan {
// This is just a placeholder so that the plan file can be written
// out. Caller may wish to override it to something more "real"
// where the plan will actually be subsequently applied.
Type: "local",
Config: backendConfigRaw,
Type: "local",
Config: backendConfigRaw,
Workspace: "default",
},
Changes: plans.NewChangesSrc(),

Expand Down
5 changes: 3 additions & 2 deletions internal/command/graph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,9 @@ func TestGraph_applyPhaseSavedPlan(t *testing.T) {
// Doesn't actually matter since we aren't going to activate the backend
// for this command anyway, but we need something here for the plan
// file writer to succeed.
Type: "placeholder",
Config: emptyObj,
Type: "placeholder",
Config: emptyObj,
Workspace: "default",
}
_, configSnap := testModuleWithSnapshot(t, "graph")

Expand Down
61 changes: 57 additions & 4 deletions internal/plans/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
package plans

import (
"errors"
"fmt"
"sort"
"time"

Expand Down Expand Up @@ -256,6 +258,22 @@ func NewBackend(typeName string, config cty.Value, configSchema *configschema.Bl
}, nil
}

func (b *Backend) Validate() error {
if b == nil {
return errors.New("plan contains a nil Backend")
}
if b.Type == "" {
return fmt.Errorf("plan's description of a backend has an unset Type: %#v", b)
}
if b.Workspace == "" {
return fmt.Errorf("plan's description of a backend has the Workspace unset: %#v", b)
}
if len(b.Config) == 0 {
return fmt.Errorf("plan's description of a backend includes no Config: %#v", b)
}
return nil
}

// StateStore represents the state store-related configuration and other data as it
// existed when a plan was created.
type StateStore struct {
Expand All @@ -264,8 +282,8 @@ type StateStore struct {

Provider *Provider

// Config is the configuration of the state store, whose schema is obtained
// from the host provider's GetProviderSchema response.
// Config is the configuration of the state store, excluding the nested provider block.
// The schema is determined by the state store's type and data received via GetProviderSchema RPC.
Config DynamicValue

// Workspace is the name of the workspace that was active when the plan
Expand All @@ -277,15 +295,50 @@ type StateStore struct {
Workspace string
}

func (s *StateStore) Validate() error {
if s == nil {
return errors.New("plan contains a nil StateStore")
}
if s.Type == "" {
return fmt.Errorf("plan's description of a state store has an unset Type: %#v", s)
}
if len(s.Config) == 0 {
return fmt.Errorf("plan's description of a state store includes no Config: %#v", s)
}
if err := s.Provider.Validate(); err != nil {
return err
}
if s.Workspace == "" {
return fmt.Errorf("plan's description of a state store has an unset Workspace: %#v", s)
}
return nil
}

type Provider struct {
Version *version.Version // The specific provider version used for the state store. Should be set using a getproviders.Version, etc.
Source *tfaddr.Provider // The FQN/fully-qualified name of the provider.

// Config is the configuration of the state store, whose schema is obtained
// from the host provider's GetProviderSchema response.
// Config is the configuration of the provider block nested within state_store.
// The schema is determined by data received via GetProviderSchema RPC.
Config DynamicValue
}

func (p *Provider) Validate() error {
if p == nil {
return errors.New("plan's description of a state store contains a nil Provider")
}
if p.Version == nil {
return fmt.Errorf("plan's description of a state store contains a nil provider Version: %#v", p)
}
if p.Source == nil {
return fmt.Errorf("plan's description of a state store contains a nil provider Source: %#v", p)
}
if len(p.Config) == 0 {
return fmt.Errorf("plan's description of a state store includes no provider Config: %#v", p)
}
return nil
}

func NewStateStore(typeName string, ver *version.Version, source *tfaddr.Provider, storeConfig cty.Value, storeSchema *configschema.Block, providerConfig cty.Value, providerSchema *configschema.Block, workspaceName string) (*StateStore, error) {
sdv, err := NewDynamicValue(storeConfig, storeSchema.ImpliedType())
if err != nil {
Expand Down
Loading