cloud: Backend implements new version of the backend.Local interface

This makes the new backend compatible with the new terraform.Context API,
which has changed in main.
This commit is contained in:
Martin Atkins 2021-08-30 15:27:58 -07:00 committed by Chris Arcand
parent 18d54c1129
commit f4758803fe
3 changed files with 21 additions and 15 deletions

View File

@ -90,6 +90,8 @@ type Cloud struct {
}
var _ backend.Backend = (*Cloud)(nil)
var _ backend.Enhanced = (*Cloud)(nil)
var _ backend.Local = (*Cloud)(nil)
// New creates a new initialized cloud backend.
func New(services *disco.Disco) *Cloud {

View File

@ -6,7 +6,6 @@ import (
"log"
"strings"
"github.com/hashicorp/errwrap"
tfe "github.com/hashicorp/go-tfe"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
@ -18,9 +17,15 @@ import (
"github.com/zclconf/go-cty/cty"
)
// Context implements backend.Enhanced.
func (b *Cloud) Context(op *backend.Operation) (*terraform.Context, statemgr.Full, tfdiags.Diagnostics) {
// LocalRun implements backend.Local
func (b *Cloud) LocalRun(op *backend.Operation) (*backend.LocalRun, statemgr.Full, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
ret := &backend.LocalRun{
PlanOpts: &terraform.PlanOpts{
Mode: op.PlanMode,
Targets: op.Targets,
},
}
op.StateLocker = op.StateLocker.WithContext(context.Background())
@ -31,7 +36,7 @@ func (b *Cloud) Context(op *backend.Operation) (*terraform.Context, statemgr.Ful
log.Printf("[TRACE] cloud: requesting state manager for workspace %q", remoteWorkspaceName)
stateMgr, err := b.StateMgr(op.Workspace)
if err != nil {
diags = diags.Append(errwrap.Wrapf("Error loading state: {{err}}", err))
diags = diags.Append(fmt.Errorf("error loading state: %w", err))
return nil, nil, diags
}
@ -50,7 +55,7 @@ func (b *Cloud) Context(op *backend.Operation) (*terraform.Context, statemgr.Ful
log.Printf("[TRACE] cloud: reading remote state for workspace %q", remoteWorkspaceName)
if err := stateMgr.RefreshState(); err != nil {
diags = diags.Append(errwrap.Wrapf("Error loading state: {{err}}", err))
diags = diags.Append(fmt.Errorf("error loading state: %w", err))
return nil, nil, diags
}
@ -61,15 +66,13 @@ func (b *Cloud) Context(op *backend.Operation) (*terraform.Context, statemgr.Ful
}
// Copy set options from the operation
opts.PlanMode = op.PlanMode
opts.Targets = op.Targets
opts.UIInput = op.UIIn
// Load the latest state. If we enter contextFromPlanFile below then the
// state snapshot in the plan file must match this, or else it'll return
// error diagnostics.
log.Printf("[TRACE] cloud: retrieving remote state snapshot for workspace %q", remoteWorkspaceName)
opts.State = stateMgr.State()
ret.InputState = stateMgr.State()
log.Printf("[TRACE] cloud: loading configuration for the current working directory")
config, configDiags := op.ConfigLoader.LoadConfig(op.ConfigDir)
@ -77,21 +80,21 @@ func (b *Cloud) Context(op *backend.Operation) (*terraform.Context, statemgr.Ful
if configDiags.HasErrors() {
return nil, nil, diags
}
opts.Config = config
ret.Config = config
// The underlying API expects us to use the opaque workspace id to request
// variables, so we'll need to look that up using our organization name
// and workspace name.
remoteWorkspaceID, err := b.getRemoteWorkspaceID(context.Background(), op.Workspace)
if err != nil {
diags = diags.Append(errwrap.Wrapf("Error finding remote workspace: {{err}}", err))
diags = diags.Append(fmt.Errorf("error finding remote workspace: %w", err))
return nil, nil, diags
}
log.Printf("[TRACE] cloud: retrieving variables from workspace %s/%s (%s)", remoteWorkspaceName, b.organization, remoteWorkspaceID)
tfeVariables, err := b.client.Variables.List(context.Background(), remoteWorkspaceID, tfe.VariableListOptions{})
if err != nil && err != tfe.ErrResourceNotFound {
diags = diags.Append(errwrap.Wrapf("Error loading variables: {{err}}", err))
diags = diags.Append(fmt.Errorf("error loading variables: %w", err))
return nil, nil, diags
}
@ -100,7 +103,7 @@ func (b *Cloud) Context(op *backend.Operation) (*terraform.Context, statemgr.Ful
// more lax about them, stubbing out any unset ones as unknown.
// This gives us enough information to produce a consistent context,
// but not enough information to run a real operation (plan, apply, etc)
opts.Variables = stubAllVariables(op.Variables, config.Module.Variables)
ret.PlanOpts.SetVariables = stubAllVariables(op.Variables, config.Module.Variables)
} else {
if tfeVariables != nil {
if op.Variables == nil {
@ -121,16 +124,17 @@ func (b *Cloud) Context(op *backend.Operation) (*terraform.Context, statemgr.Ful
if diags.HasErrors() {
return nil, nil, diags
}
opts.Variables = variables
ret.PlanOpts.SetVariables = variables
}
}
tfCtx, ctxDiags := terraform.NewContext(&opts)
diags = diags.Append(ctxDiags)
ret.Core = tfCtx
log.Printf("[TRACE] cloud: finished building terraform.Context")
return tfCtx, stateMgr, diags
return ret, stateMgr, diags
}
func (b *Cloud) getRemoteWorkspaceName(localWorkspaceName string) string {

View File

@ -204,7 +204,7 @@ func TestRemoteContextWithVars(t *testing.T) {
}
b.client.Variables.Create(context.TODO(), workspaceID, *v)
_, _, diags := b.Context(op)
_, _, diags := b.LocalRun(op)
if test.WantError != "" {
if !diags.HasErrors() {