cloud: Align local and remote workspace name with 'name' strategy
This changes the 'name' strategy to always align the local configured workspace name and the remote Terraform Cloud workspace, rather than the implicit use of the 'default' unnamed workspace being used instead. What this essentially means is that the Cloud integration does not fully support workspaces when configured for a single TFC workspace (as was the case with the 'remote' backend), but *does* use the backend.Workspaces() interface to allow for normal local behaviors like terraform.workspace to resolve to the correct name. It does this by always setting the local workspace name when the 'name' strategy is used, as a part of initialization. Part of the diff here is exporting all the previously unexported types for mapping workspaces. The command package (and init in particular) needs to be able to handle setting the local workspace in this particular scenario.
This commit is contained in:
parent
a94b2405b1
commit
d2b6b5f2b3
|
@ -64,9 +64,9 @@ type Cloud struct {
|
|||
// organization is the organization that contains the target workspaces.
|
||||
organization string
|
||||
|
||||
// workspaceMapping contains strategies for mapping CLI workspaces in the working directory
|
||||
// WorkspaceMapping contains strategies for mapping CLI workspaces in the working directory
|
||||
// to remote Terraform Cloud workspaces.
|
||||
workspaceMapping workspaceMapping
|
||||
WorkspaceMapping WorkspaceMapping
|
||||
|
||||
// services is used for service discovery
|
||||
services *disco.Disco
|
||||
|
@ -157,28 +157,28 @@ func (b *Cloud) PrepareConfig(obj cty.Value) (cty.Value, tfdiags.Diagnostics) {
|
|||
diags = diags.Append(invalidOrganizationConfigMissingValue)
|
||||
}
|
||||
|
||||
workspaceMapping := workspaceMapping{}
|
||||
WorkspaceMapping := WorkspaceMapping{}
|
||||
if workspaces := obj.GetAttr("workspaces"); !workspaces.IsNull() {
|
||||
if val := workspaces.GetAttr("name"); !val.IsNull() {
|
||||
workspaceMapping.name = val.AsString()
|
||||
WorkspaceMapping.Name = val.AsString()
|
||||
}
|
||||
if val := workspaces.GetAttr("prefix"); !val.IsNull() {
|
||||
workspaceMapping.prefix = val.AsString()
|
||||
WorkspaceMapping.Prefix = val.AsString()
|
||||
}
|
||||
if val := workspaces.GetAttr("tags"); !val.IsNull() {
|
||||
err := gocty.FromCtyValue(val, &workspaceMapping.tags)
|
||||
err := gocty.FromCtyValue(val, &WorkspaceMapping.Tags)
|
||||
if err != nil {
|
||||
log.Panicf("An unxpected error occurred: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch workspaceMapping.strategy() {
|
||||
switch WorkspaceMapping.Strategy() {
|
||||
// Make sure have a workspace mapping strategy present
|
||||
case workspaceNoneStrategy:
|
||||
case WorkspaceNoneStrategy:
|
||||
diags = diags.Append(invalidWorkspaceConfigMissingValues)
|
||||
// Make sure that only one of workspace name or a prefix is configured.
|
||||
case workspaceInvalidStrategy:
|
||||
case WorkspaceInvalidStrategy:
|
||||
diags = diags.Append(invalidWorkspaceConfigMisconfiguration)
|
||||
}
|
||||
|
||||
|
@ -335,10 +335,10 @@ func (b *Cloud) setConfigurationFields(obj cty.Value) tfdiags.Diagnostics {
|
|||
|
||||
// PrepareConfig checks that you cannot set both of these.
|
||||
if val := workspaces.GetAttr("name"); !val.IsNull() {
|
||||
b.workspaceMapping.name = val.AsString()
|
||||
b.WorkspaceMapping.Name = val.AsString()
|
||||
}
|
||||
if val := workspaces.GetAttr("prefix"); !val.IsNull() {
|
||||
b.workspaceMapping.prefix = val.AsString()
|
||||
b.WorkspaceMapping.Prefix = val.AsString()
|
||||
}
|
||||
if val := workspaces.GetAttr("tags"); !val.IsNull() {
|
||||
var tags []string
|
||||
|
@ -347,7 +347,7 @@ func (b *Cloud) setConfigurationFields(obj cty.Value) tfdiags.Diagnostics {
|
|||
log.Panicf("An unxpected error occurred: %s", err)
|
||||
}
|
||||
|
||||
b.workspaceMapping.tags = tags
|
||||
b.WorkspaceMapping.Tags = tags
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,31 +530,30 @@ func (b *Cloud) retryLogHook(attemptNum int, resp *http.Response) {
|
|||
}
|
||||
}
|
||||
|
||||
// Workspaces implements backend.Enhanced.
|
||||
// Workspaces implements backend.Enhanced, returning a filtered list of workspace names according to
|
||||
// the workspace mapping strategy configured.
|
||||
func (b *Cloud) Workspaces() ([]string, error) {
|
||||
if b.workspaceMapping.strategy() == workspaceNameStrategy {
|
||||
return nil, backend.ErrWorkspacesNotSupported
|
||||
}
|
||||
return b.workspaces()
|
||||
}
|
||||
|
||||
// workspaces returns a filtered list of remote workspace names according to the workspace mapping
|
||||
// strategy configured.
|
||||
func (b *Cloud) workspaces() ([]string, error) {
|
||||
options := tfe.WorkspaceListOptions{}
|
||||
switch b.workspaceMapping.strategy() {
|
||||
case workspaceNameStrategy:
|
||||
options.Search = tfe.String(b.workspaceMapping.name)
|
||||
case workspacePrefixStrategy:
|
||||
options.Search = tfe.String(b.workspaceMapping.prefix)
|
||||
case workspaceTagsStrategy:
|
||||
taglist := strings.Join(b.workspaceMapping.tags, ",")
|
||||
options.Tags = &taglist
|
||||
}
|
||||
|
||||
// Create a slice to contain all the names.
|
||||
var names []string
|
||||
|
||||
// If configured for a single workspace, return that exact name only. The StateMgr for this
|
||||
// backend will automatically create the remote workspace if it does not yet exist.
|
||||
if b.WorkspaceMapping.Strategy() == WorkspaceNameStrategy {
|
||||
names = append(names, b.WorkspaceMapping.Name)
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// Otherwise, multiple workspaces are being mapped. Query Terraform Cloud for all the remote
|
||||
// workspaces by the provided mapping strategy.
|
||||
options := tfe.WorkspaceListOptions{}
|
||||
switch b.WorkspaceMapping.Strategy() {
|
||||
case WorkspacePrefixStrategy:
|
||||
options.Search = tfe.String(b.WorkspaceMapping.Prefix)
|
||||
case WorkspaceTagsStrategy:
|
||||
taglist := strings.Join(b.WorkspaceMapping.Tags, ",")
|
||||
options.Tags = &taglist
|
||||
}
|
||||
|
||||
for {
|
||||
wl, err := b.client.Workspaces.List(context.Background(), b.organization, options)
|
||||
if err != nil {
|
||||
|
@ -562,20 +561,15 @@ func (b *Cloud) workspaces() ([]string, error) {
|
|||
}
|
||||
|
||||
for _, w := range wl.Items {
|
||||
switch b.workspaceMapping.strategy() {
|
||||
case workspaceNameStrategy:
|
||||
if w.Name == b.workspaceMapping.name {
|
||||
names = append(names, backend.DefaultStateName)
|
||||
continue
|
||||
}
|
||||
case workspacePrefixStrategy:
|
||||
if strings.HasPrefix(w.Name, b.workspaceMapping.prefix) {
|
||||
names = append(names, strings.TrimPrefix(w.Name, b.workspaceMapping.prefix))
|
||||
switch b.WorkspaceMapping.Strategy() {
|
||||
case WorkspacePrefixStrategy:
|
||||
if strings.HasPrefix(w.Name, b.WorkspaceMapping.Prefix) {
|
||||
names = append(names, strings.TrimPrefix(w.Name, b.WorkspaceMapping.Prefix))
|
||||
continue
|
||||
}
|
||||
default:
|
||||
// Pass-through. "name" and "prefix" strategies are naive and do
|
||||
// client-side filtering above, but for tags and any other future
|
||||
// Pass-through. The "prefix" strategy is naive and does
|
||||
// client-side filtering, but for tags and any other future
|
||||
// strategy this filtering should be left to the API.
|
||||
names = append(names, w.Name)
|
||||
}
|
||||
|
@ -598,19 +592,18 @@ func (b *Cloud) workspaces() ([]string, error) {
|
|||
|
||||
// DeleteWorkspace implements backend.Enhanced.
|
||||
func (b *Cloud) DeleteWorkspace(name string) error {
|
||||
if b.workspaceMapping.strategy() != workspaceNameStrategy && name == backend.DefaultStateName {
|
||||
if name == backend.DefaultStateName {
|
||||
return backend.ErrDefaultWorkspaceNotSupported
|
||||
}
|
||||
if b.workspaceMapping.strategy() == workspaceNameStrategy && name != backend.DefaultStateName {
|
||||
|
||||
if b.WorkspaceMapping.Strategy() == WorkspaceNameStrategy {
|
||||
return backend.ErrWorkspacesNotSupported
|
||||
}
|
||||
|
||||
// Configure the remote workspace name.
|
||||
switch {
|
||||
case name == backend.DefaultStateName:
|
||||
name = b.workspaceMapping.name
|
||||
case b.workspaceMapping.strategy() == workspacePrefixStrategy && !strings.HasPrefix(name, b.workspaceMapping.prefix):
|
||||
name = b.workspaceMapping.prefix + name
|
||||
case b.WorkspaceMapping.Strategy() == WorkspacePrefixStrategy && !strings.HasPrefix(name, b.WorkspaceMapping.Prefix):
|
||||
name = b.WorkspaceMapping.Prefix + name
|
||||
}
|
||||
|
||||
client := &remoteClient{
|
||||
|
@ -626,19 +619,17 @@ func (b *Cloud) DeleteWorkspace(name string) error {
|
|||
|
||||
// StateMgr implements backend.Enhanced.
|
||||
func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
|
||||
if b.workspaceMapping.strategy() != workspaceNameStrategy && name == backend.DefaultStateName {
|
||||
if name == backend.DefaultStateName {
|
||||
return nil, backend.ErrDefaultWorkspaceNotSupported
|
||||
}
|
||||
if b.workspaceMapping.strategy() == workspaceNameStrategy && name != backend.DefaultStateName {
|
||||
|
||||
if b.WorkspaceMapping.Strategy() == WorkspaceNameStrategy && name != b.WorkspaceMapping.Name {
|
||||
return nil, backend.ErrWorkspacesNotSupported
|
||||
}
|
||||
|
||||
// Configure the remote workspace name.
|
||||
switch {
|
||||
case name == backend.DefaultStateName:
|
||||
name = b.workspaceMapping.name
|
||||
case b.workspaceMapping.strategy() == workspacePrefixStrategy && !strings.HasPrefix(name, b.workspaceMapping.prefix):
|
||||
name = b.workspaceMapping.prefix + name
|
||||
// If the prefix strategy is used, translate the local name to the TFC workspace name.
|
||||
if b.WorkspaceMapping.Strategy() == WorkspacePrefixStrategy {
|
||||
name = b.WorkspaceMapping.Prefix + name
|
||||
}
|
||||
|
||||
workspace, err := b.client.Workspaces.Read(context.Background(), b.organization, name)
|
||||
|
@ -652,7 +643,7 @@ func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
|
|||
}
|
||||
|
||||
var tags []*tfe.Tag
|
||||
for _, tag := range b.workspaceMapping.tags {
|
||||
for _, tag := range b.WorkspaceMapping.Tags {
|
||||
t := tfe.Tag{Name: tag}
|
||||
tags = append(tags, &t)
|
||||
}
|
||||
|
@ -698,13 +689,11 @@ func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
|
|||
|
||||
// Operation implements backend.Enhanced.
|
||||
func (b *Cloud) Operation(ctx context.Context, op *backend.Operation) (*backend.RunningOperation, error) {
|
||||
// Get the remote workspace name.
|
||||
name := op.Workspace
|
||||
switch {
|
||||
case op.Workspace == backend.DefaultStateName:
|
||||
name = b.workspaceMapping.name
|
||||
case b.workspaceMapping.strategy() == workspacePrefixStrategy && !strings.HasPrefix(op.Workspace, b.workspaceMapping.prefix):
|
||||
name = b.workspaceMapping.prefix + op.Workspace
|
||||
|
||||
// If the prefix strategy is used, translate the local name to the TFC workspace name.
|
||||
if b.WorkspaceMapping.Strategy() == WorkspacePrefixStrategy {
|
||||
name = b.WorkspaceMapping.Prefix + op.Workspace
|
||||
}
|
||||
|
||||
// Retrieve the workspace for this operation.
|
||||
|
@ -1014,35 +1003,35 @@ func (b *Cloud) cliColorize() *colorstring.Colorize {
|
|||
}
|
||||
}
|
||||
|
||||
type workspaceMapping struct {
|
||||
name string
|
||||
prefix string
|
||||
tags []string
|
||||
type WorkspaceMapping struct {
|
||||
Name string
|
||||
Prefix string
|
||||
Tags []string
|
||||
}
|
||||
|
||||
type workspaceStrategy string
|
||||
|
||||
const (
|
||||
workspaceTagsStrategy workspaceStrategy = "tags"
|
||||
workspaceNameStrategy workspaceStrategy = "name"
|
||||
workspacePrefixStrategy workspaceStrategy = "prefix"
|
||||
workspaceNoneStrategy workspaceStrategy = "none"
|
||||
workspaceInvalidStrategy workspaceStrategy = "invalid"
|
||||
WorkspaceTagsStrategy workspaceStrategy = "tags"
|
||||
WorkspaceNameStrategy workspaceStrategy = "name"
|
||||
WorkspacePrefixStrategy workspaceStrategy = "prefix"
|
||||
WorkspaceNoneStrategy workspaceStrategy = "none"
|
||||
WorkspaceInvalidStrategy workspaceStrategy = "invalid"
|
||||
)
|
||||
|
||||
func (wm workspaceMapping) strategy() workspaceStrategy {
|
||||
func (wm WorkspaceMapping) Strategy() workspaceStrategy {
|
||||
switch {
|
||||
case len(wm.tags) > 0 && wm.name == "" && wm.prefix == "":
|
||||
return workspaceTagsStrategy
|
||||
case len(wm.tags) == 0 && wm.name != "" && wm.prefix == "":
|
||||
return workspaceNameStrategy
|
||||
case len(wm.tags) == 0 && wm.name == "" && wm.prefix != "":
|
||||
return workspacePrefixStrategy
|
||||
case len(wm.tags) == 0 && wm.name == "" && wm.prefix == "":
|
||||
return workspaceNoneStrategy
|
||||
case len(wm.Tags) > 0 && wm.Name == "" && wm.Prefix == "":
|
||||
return WorkspaceTagsStrategy
|
||||
case len(wm.Tags) == 0 && wm.Name != "" && wm.Prefix == "":
|
||||
return WorkspaceNameStrategy
|
||||
case len(wm.Tags) == 0 && wm.Name == "" && wm.Prefix != "":
|
||||
return WorkspacePrefixStrategy
|
||||
case len(wm.Tags) == 0 && wm.Name == "" && wm.Prefix == "":
|
||||
return WorkspaceNoneStrategy
|
||||
default:
|
||||
// Any other combination is invalid as each strategy is mutually exclusive
|
||||
return workspaceInvalidStrategy
|
||||
return WorkspaceInvalidStrategy
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ func TestCloud_applyBasic(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -97,7 +97,7 @@ func TestCloud_applyBasic(t *testing.T) {
|
|||
t.Fatalf("expected apply summery in output: %s", output)
|
||||
}
|
||||
|
||||
stateMgr, _ := b.StateMgr(backend.DefaultStateName)
|
||||
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after apply: %s", err.Error())
|
||||
|
@ -112,7 +112,7 @@ func TestCloud_applyCanceled(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -127,7 +127,7 @@ func TestCloud_applyCanceled(t *testing.T) {
|
|||
t.Fatal("expected apply operation to fail")
|
||||
}
|
||||
|
||||
stateMgr, _ := b.StateMgr(backend.DefaultStateName)
|
||||
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after cancelling apply: %s", err.Error())
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ func TestCloud_applyWithoutPermissions(t *testing.T) {
|
|||
context.Background(),
|
||||
b.organization,
|
||||
tfe.WorkspaceCreateOptions{
|
||||
Name: tfe.String(b.workspaceMapping.prefix + "prod"),
|
||||
Name: tfe.String(b.WorkspaceMapping.Prefix + "prod"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -182,7 +182,7 @@ func TestCloud_applyWithVCS(t *testing.T) {
|
|||
context.Background(),
|
||||
b.organization,
|
||||
tfe.WorkspaceCreateOptions{
|
||||
Name: tfe.String(b.workspaceMapping.prefix + "prod"),
|
||||
Name: tfe.String(b.WorkspaceMapping.Prefix + "prod"),
|
||||
VCSRepo: &tfe.VCSRepoOptions{},
|
||||
},
|
||||
)
|
||||
|
@ -226,7 +226,7 @@ func TestCloud_applyWithParallelism(t *testing.T) {
|
|||
b.ContextOpts = &terraform.ContextOpts{}
|
||||
}
|
||||
b.ContextOpts.Parallelism = 3
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -253,7 +253,7 @@ func TestCloud_applyWithPlan(t *testing.T) {
|
|||
defer configCleanup()
|
||||
|
||||
op.PlanFile = &planfile.Reader{}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -284,7 +284,7 @@ func TestCloud_applyWithoutRefresh(t *testing.T) {
|
|||
defer done(t)
|
||||
|
||||
op.PlanRefresh = false
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -322,7 +322,7 @@ func TestCloud_applyWithoutRefreshIncompatibleAPIVersion(t *testing.T) {
|
|||
b.client.SetFakeRemoteAPIVersion("2.3")
|
||||
|
||||
op.PlanRefresh = false
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -353,7 +353,7 @@ func TestCloud_applyWithRefreshOnly(t *testing.T) {
|
|||
defer done(t)
|
||||
|
||||
op.PlanMode = plans.RefreshOnlyMode
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -391,7 +391,7 @@ func TestCloud_applyWithRefreshOnlyIncompatibleAPIVersion(t *testing.T) {
|
|||
b.client.SetFakeRemoteAPIVersion("2.3")
|
||||
|
||||
op.PlanMode = plans.RefreshOnlyMode
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -424,7 +424,7 @@ func TestCloud_applyWithTarget(t *testing.T) {
|
|||
addr, _ := addrs.ParseAbsResourceStr("null_resource.foo")
|
||||
|
||||
op.Targets = []addrs.Targetable{addr}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -466,7 +466,7 @@ func TestCloud_applyWithTargetIncompatibleAPIVersion(t *testing.T) {
|
|||
addr, _ := addrs.ParseAbsResourceStr("null_resource.foo")
|
||||
|
||||
op.Targets = []addrs.Targetable{addr}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -499,7 +499,7 @@ func TestCloud_applyWithReplace(t *testing.T) {
|
|||
addr, _ := addrs.ParseAbsResourceInstanceStr("null_resource.foo")
|
||||
|
||||
op.ForceReplace = []addrs.AbsResourceInstance{addr}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -539,7 +539,7 @@ func TestCloud_applyWithReplaceIncompatibleAPIVersion(t *testing.T) {
|
|||
addr, _ := addrs.ParseAbsResourceInstanceStr("null_resource.foo")
|
||||
|
||||
op.ForceReplace = []addrs.AbsResourceInstance{addr}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -569,7 +569,7 @@ func TestCloud_applyWithVariables(t *testing.T) {
|
|||
defer configCleanup()
|
||||
|
||||
op.Variables = testVariables(terraform.ValueFromNamedFile, "foo", "bar")
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -595,7 +595,7 @@ func TestCloud_applyNoConfig(t *testing.T) {
|
|||
op, configCleanup, done := testOperationApply(t, "./testdata/empty")
|
||||
defer configCleanup()
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -616,7 +616,7 @@ func TestCloud_applyNoConfig(t *testing.T) {
|
|||
t.Fatalf("expected configuration files error, got: %v", errOutput)
|
||||
}
|
||||
|
||||
stateMgr, _ := b.StateMgr(backend.DefaultStateName)
|
||||
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after failed apply: %s", err.Error())
|
||||
|
@ -631,7 +631,7 @@ func TestCloud_applyNoChanges(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -668,7 +668,7 @@ func TestCloud_applyNoApprove(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -709,7 +709,7 @@ func TestCloud_applyAutoApprove(t *testing.T) {
|
|||
op.AutoApprove = true
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -754,7 +754,7 @@ func TestCloud_applyApprovedExternally(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
|
@ -828,7 +828,7 @@ func TestCloud_applyDiscardedExternally(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
|
@ -898,7 +898,7 @@ func TestCloud_applyWithAutoApply(t *testing.T) {
|
|||
b.organization,
|
||||
tfe.WorkspaceCreateOptions{
|
||||
AutoApply: tfe.Bool(true),
|
||||
Name: tfe.String(b.workspaceMapping.prefix + "prod"),
|
||||
Name: tfe.String(b.WorkspaceMapping.Prefix + "prod"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -967,7 +967,7 @@ func TestCloud_applyForceLocal(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
streams, done := terminal.StreamsForTesting(t)
|
||||
view := views.NewOperation(arguments.ViewHuman, false, views.NewView(streams))
|
||||
|
@ -1013,7 +1013,7 @@ func TestCloud_applyWorkspaceWithoutOperations(t *testing.T) {
|
|||
ctx,
|
||||
b.organization,
|
||||
tfe.WorkspaceCreateOptions{
|
||||
Name: tfe.String(b.workspaceMapping.prefix + "no-operations"),
|
||||
Name: tfe.String(b.WorkspaceMapping.Prefix + "no-operations"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -1072,7 +1072,7 @@ func TestCloud_applyLockTimeout(t *testing.T) {
|
|||
ctx := context.Background()
|
||||
|
||||
// Retrieve the workspace used to run this operation in.
|
||||
w, err := b.client.Workspaces.Read(ctx, b.organization, b.workspaceMapping.name)
|
||||
w, err := b.client.Workspaces.Read(ctx, b.organization, b.WorkspaceMapping.Name)
|
||||
if err != nil {
|
||||
t.Fatalf("error retrieving workspace: %v", err)
|
||||
}
|
||||
|
@ -1103,7 +1103,7 @@ func TestCloud_applyLockTimeout(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
_, err = b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1154,7 +1154,7 @@ func TestCloud_applyDestroy(t *testing.T) {
|
|||
op.PlanMode = plans.DestroyMode
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1200,7 +1200,7 @@ func TestCloud_applyDestroyNoConfig(t *testing.T) {
|
|||
op.PlanMode = plans.DestroyMode
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1234,7 +1234,7 @@ func TestCloud_applyPolicyPass(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1281,7 +1281,7 @@ func TestCloud_applyPolicyHardFail(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1337,7 +1337,7 @@ func TestCloud_applyPolicySoftFail(t *testing.T) {
|
|||
op.AutoApprove = false
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1383,7 +1383,7 @@ func TestCloud_applyPolicySoftFailAutoApproveSuccess(t *testing.T) {
|
|||
op.AutoApprove = true
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1432,7 +1432,7 @@ func TestCloud_applyPolicySoftFailAutoApply(t *testing.T) {
|
|||
b.organization,
|
||||
tfe.WorkspaceCreateOptions{
|
||||
AutoApply: tfe.Bool(true),
|
||||
Name: tfe.String(b.workspaceMapping.prefix + "prod"),
|
||||
Name: tfe.String(b.WorkspaceMapping.Prefix + "prod"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -1492,7 +1492,7 @@ func TestCloud_applyWithRemoteError(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1581,7 +1581,7 @@ func TestCloud_applyVersionCheck(t *testing.T) {
|
|||
_, err := b.client.Workspaces.Update(
|
||||
ctx,
|
||||
b.organization,
|
||||
b.workspaceMapping.name,
|
||||
b.WorkspaceMapping.Name,
|
||||
tfe.WorkspaceUpdateOptions{
|
||||
Operations: tfe.Bool(tc.hasOperations),
|
||||
TerraformVersion: tfe.String(tc.remoteVersion),
|
||||
|
@ -1606,7 +1606,7 @@ func TestCloud_applyVersionCheck(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(ctx, op)
|
||||
if err != nil {
|
||||
|
|
|
@ -143,9 +143,9 @@ func (b *Cloud) getRemoteWorkspaceName(localWorkspaceName string) string {
|
|||
// The default workspace name is a special case, for when the backend
|
||||
// is configured to with to an exact remote workspace rather than with
|
||||
// a remote workspace _prefix_.
|
||||
return b.workspaceMapping.name
|
||||
case b.workspaceMapping.prefix != "" && !strings.HasPrefix(localWorkspaceName, b.workspaceMapping.prefix):
|
||||
return b.workspaceMapping.prefix + localWorkspaceName
|
||||
return b.WorkspaceMapping.Name
|
||||
case b.WorkspaceMapping.Prefix != "" && !strings.HasPrefix(localWorkspaceName, b.WorkspaceMapping.Prefix):
|
||||
return b.WorkspaceMapping.Prefix + localWorkspaceName
|
||||
default:
|
||||
return localWorkspaceName
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ func TestRemoteContextWithVars(t *testing.T) {
|
|||
_, configLoader, configCleanup := initwd.MustLoadConfigForTests(t, configDir)
|
||||
defer configCleanup()
|
||||
|
||||
workspaceID, err := b.getRemoteWorkspaceID(context.Background(), backend.DefaultStateName)
|
||||
workspaceID, err := b.getRemoteWorkspaceID(context.Background(), testBackendSingleWorkspaceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ func TestRemoteContextWithVars(t *testing.T) {
|
|||
ConfigDir: configDir,
|
||||
ConfigLoader: configLoader,
|
||||
StateLocker: clistate.NewLocker(0, view),
|
||||
Workspace: backend.DefaultStateName,
|
||||
Workspace: testBackendSingleWorkspaceName,
|
||||
}
|
||||
|
||||
v := test.Opts
|
||||
|
@ -216,7 +216,7 @@ func TestRemoteContextWithVars(t *testing.T) {
|
|||
}
|
||||
// When Context() returns an error, it should unlock the state,
|
||||
// so re-locking it is expected to succeed.
|
||||
stateMgr, _ := b.StateMgr(backend.DefaultStateName)
|
||||
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state: %s", err.Error())
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ func TestRemoteContextWithVars(t *testing.T) {
|
|||
t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error())
|
||||
}
|
||||
// When Context() succeeds, this should fail w/ "workspace already locked"
|
||||
stateMgr, _ := b.StateMgr(backend.DefaultStateName)
|
||||
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil {
|
||||
t.Fatal("unexpected success locking state after Context")
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ func TestCloud_planBasic(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -82,7 +82,7 @@ func TestCloud_planBasic(t *testing.T) {
|
|||
t.Fatalf("expected plan summary in output: %s", output)
|
||||
}
|
||||
|
||||
stateMgr, _ := b.StateMgr(backend.DefaultStateName)
|
||||
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after the operation finished
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
|
||||
|
@ -97,7 +97,7 @@ func TestCloud_planCanceled(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -112,7 +112,7 @@ func TestCloud_planCanceled(t *testing.T) {
|
|||
t.Fatal("expected plan operation to fail")
|
||||
}
|
||||
|
||||
stateMgr, _ := b.StateMgr(backend.DefaultStateName)
|
||||
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after the operation finished
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after cancelled plan: %s", err.Error())
|
||||
|
@ -127,7 +127,7 @@ func TestCloud_planLongLine(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -160,7 +160,7 @@ func TestCloud_planWithoutPermissions(t *testing.T) {
|
|||
context.Background(),
|
||||
b.organization,
|
||||
tfe.WorkspaceCreateOptions{
|
||||
Name: tfe.String(b.workspaceMapping.prefix + "prod"),
|
||||
Name: tfe.String(b.WorkspaceMapping.Prefix + "prod"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -201,7 +201,7 @@ func TestCloud_planWithParallelism(t *testing.T) {
|
|||
b.ContextOpts = &terraform.ContextOpts{}
|
||||
}
|
||||
b.ContextOpts.Parallelism = 3
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -228,7 +228,7 @@ func TestCloud_planWithPlan(t *testing.T) {
|
|||
defer configCleanup()
|
||||
|
||||
op.PlanFile = &planfile.Reader{}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -258,7 +258,7 @@ func TestCloud_planWithPath(t *testing.T) {
|
|||
defer configCleanup()
|
||||
|
||||
op.PlanOutPath = "./testdata/plan"
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -289,7 +289,7 @@ func TestCloud_planWithoutRefresh(t *testing.T) {
|
|||
defer done(t)
|
||||
|
||||
op.PlanRefresh = false
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -327,7 +327,7 @@ func TestCloud_planWithoutRefreshIncompatibleAPIVersion(t *testing.T) {
|
|||
b.client.SetFakeRemoteAPIVersion("2.3")
|
||||
|
||||
op.PlanRefresh = false
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -358,7 +358,7 @@ func TestCloud_planWithRefreshOnly(t *testing.T) {
|
|||
defer done(t)
|
||||
|
||||
op.PlanMode = plans.RefreshOnlyMode
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -396,7 +396,7 @@ func TestCloud_planWithRefreshOnlyIncompatibleAPIVersion(t *testing.T) {
|
|||
b.client.SetFakeRemoteAPIVersion("2.3")
|
||||
|
||||
op.PlanMode = plans.RefreshOnlyMode
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -452,7 +452,7 @@ func TestCloud_planWithTarget(t *testing.T) {
|
|||
addr, _ := addrs.ParseAbsResourceStr("null_resource.foo")
|
||||
|
||||
op.Targets = []addrs.Targetable{addr}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -501,7 +501,7 @@ func TestCloud_planWithTargetIncompatibleAPIVersion(t *testing.T) {
|
|||
addr, _ := addrs.ParseAbsResourceStr("null_resource.foo")
|
||||
|
||||
op.Targets = []addrs.Targetable{addr}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -534,7 +534,7 @@ func TestCloud_planWithReplace(t *testing.T) {
|
|||
addr, _ := addrs.ParseAbsResourceInstanceStr("null_resource.foo")
|
||||
|
||||
op.ForceReplace = []addrs.AbsResourceInstance{addr}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -574,7 +574,7 @@ func TestCloud_planWithReplaceIncompatibleAPIVersion(t *testing.T) {
|
|||
addr, _ := addrs.ParseAbsResourceInstanceStr("null_resource.foo")
|
||||
|
||||
op.ForceReplace = []addrs.AbsResourceInstance{addr}
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -604,7 +604,7 @@ func TestCloud_planWithVariables(t *testing.T) {
|
|||
defer configCleanup()
|
||||
|
||||
op.Variables = testVariables(terraform.ValueFromCLIArg, "foo", "bar")
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -630,7 +630,7 @@ func TestCloud_planNoConfig(t *testing.T) {
|
|||
op, configCleanup, done := testOperationPlan(t, "./testdata/empty")
|
||||
defer configCleanup()
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -660,7 +660,7 @@ func TestCloud_planNoChanges(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -699,7 +699,7 @@ func TestCloud_planForceLocal(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
streams, done := terminal.StreamsForTesting(t)
|
||||
view := views.NewOperation(arguments.ViewHuman, false, views.NewView(streams))
|
||||
|
@ -735,7 +735,7 @@ func TestCloud_planWithoutOperationsEntitlement(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
streams, done := terminal.StreamsForTesting(t)
|
||||
view := views.NewOperation(arguments.ViewHuman, false, views.NewView(streams))
|
||||
|
@ -774,7 +774,7 @@ func TestCloud_planWorkspaceWithoutOperations(t *testing.T) {
|
|||
ctx,
|
||||
b.organization,
|
||||
tfe.WorkspaceCreateOptions{
|
||||
Name: tfe.String(b.workspaceMapping.prefix + "no-operations"),
|
||||
Name: tfe.String(b.WorkspaceMapping.Prefix + "no-operations"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -820,7 +820,7 @@ func TestCloud_planLockTimeout(t *testing.T) {
|
|||
ctx := context.Background()
|
||||
|
||||
// Retrieve the workspace used to run this operation in.
|
||||
w, err := b.client.Workspaces.Read(ctx, b.organization, b.workspaceMapping.name)
|
||||
w, err := b.client.Workspaces.Read(ctx, b.organization, b.WorkspaceMapping.Name)
|
||||
if err != nil {
|
||||
t.Fatalf("error retrieving workspace: %v", err)
|
||||
}
|
||||
|
@ -851,7 +851,7 @@ func TestCloud_planLockTimeout(t *testing.T) {
|
|||
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
_, err = b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -893,7 +893,7 @@ func TestCloud_planDestroy(t *testing.T) {
|
|||
defer done(t)
|
||||
|
||||
op.PlanMode = plans.DestroyMode
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -918,7 +918,7 @@ func TestCloud_planDestroyNoConfig(t *testing.T) {
|
|||
defer done(t)
|
||||
|
||||
op.PlanMode = plans.DestroyMode
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -943,7 +943,7 @@ func TestCloud_planWithWorkingDirectory(t *testing.T) {
|
|||
}
|
||||
|
||||
// Configure the workspace to use a custom working directory.
|
||||
_, err := b.client.Workspaces.Update(context.Background(), b.organization, b.workspaceMapping.name, options)
|
||||
_, err := b.client.Workspaces.Update(context.Background(), b.organization, b.WorkspaceMapping.Name, options)
|
||||
if err != nil {
|
||||
t.Fatalf("error configuring working directory: %v", err)
|
||||
}
|
||||
|
@ -952,7 +952,7 @@ func TestCloud_planWithWorkingDirectory(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -988,7 +988,7 @@ func TestCloud_planWithWorkingDirectoryFromCurrentPath(t *testing.T) {
|
|||
}
|
||||
|
||||
// Configure the workspace to use a custom working directory.
|
||||
_, err := b.client.Workspaces.Update(context.Background(), b.organization, b.workspaceMapping.name, options)
|
||||
_, err := b.client.Workspaces.Update(context.Background(), b.organization, b.WorkspaceMapping.Name, options)
|
||||
if err != nil {
|
||||
t.Fatalf("error configuring working directory: %v", err)
|
||||
}
|
||||
|
@ -1011,7 +1011,7 @@ func TestCloud_planWithWorkingDirectoryFromCurrentPath(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1043,7 +1043,7 @@ func TestCloud_planCostEstimation(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1078,7 +1078,7 @@ func TestCloud_planPolicyPass(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1112,7 +1112,7 @@ func TestCloud_planPolicyHardFail(t *testing.T) {
|
|||
op, configCleanup, done := testOperationPlan(t, "./testdata/plan-policy-hard-failed")
|
||||
defer configCleanup()
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1152,7 +1152,7 @@ func TestCloud_planPolicySoftFail(t *testing.T) {
|
|||
op, configCleanup, done := testOperationPlan(t, "./testdata/plan-policy-soft-failed")
|
||||
defer configCleanup()
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
@ -1193,7 +1193,7 @@ func TestCloud_planWithRemoteError(t *testing.T) {
|
|||
defer configCleanup()
|
||||
defer done(t)
|
||||
|
||||
op.Workspace = backend.DefaultStateName
|
||||
op.Workspace = testBackendSingleWorkspaceName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/backend"
|
||||
"github.com/hashicorp/terraform/internal/states"
|
||||
"github.com/hashicorp/terraform/internal/states/remote"
|
||||
"github.com/hashicorp/terraform/internal/states/statefile"
|
||||
|
@ -24,12 +23,12 @@ func TestRemoteClient_stateLock(t *testing.T) {
|
|||
b, bCleanup := testBackendDefault(t)
|
||||
defer bCleanup()
|
||||
|
||||
s1, err := b.StateMgr(backend.DefaultStateName)
|
||||
s1, err := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
s2, err := b.StateMgr(backend.DefaultStateName)
|
||||
s2, err := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
|
|
|
@ -24,13 +24,30 @@ func TestCloud(t *testing.T) {
|
|||
var _ backend.CLI = New(nil)
|
||||
}
|
||||
|
||||
func TestCloud_backendDefault(t *testing.T) {
|
||||
func TestCloud_backendWithName(t *testing.T) {
|
||||
b, bCleanup := testBackendDefault(t)
|
||||
defer bCleanup()
|
||||
|
||||
backend.TestBackendStates(t, b)
|
||||
backend.TestBackendStateLocks(t, b, b)
|
||||
backend.TestBackendStateForceUnlock(t, b, b)
|
||||
workspaces, err := b.Workspaces()
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
if len(workspaces) != 1 || workspaces[0] != testBackendSingleWorkspaceName {
|
||||
t.Fatalf("should only have a single configured workspace matching the configured 'name' strategy, but got: %#v", workspaces)
|
||||
}
|
||||
|
||||
if _, err := b.StateMgr("foo"); err != backend.ErrWorkspacesNotSupported {
|
||||
t.Fatalf("expected fetching a state which is NOT the single configured workspace to have an ErrWorkspacesNotSupported error, but got: %v", err)
|
||||
}
|
||||
|
||||
if err := b.DeleteWorkspace(testBackendSingleWorkspaceName); err != backend.ErrWorkspacesNotSupported {
|
||||
t.Fatalf("expected deleting the single configured workspace name to result in an error, but got: %v", err)
|
||||
}
|
||||
|
||||
if err := b.DeleteWorkspace("foo"); err != backend.ErrWorkspacesNotSupported {
|
||||
t.Fatalf("expected deleting a workspace which is NOT the configured workspace name to result in an error, but got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloud_backendWithPrefix(t *testing.T) {
|
||||
|
@ -428,15 +445,15 @@ func TestCloud_setConfigurationFields(t *testing.T) {
|
|||
if tc.expectedOrganziation != "" && b.organization != tc.expectedOrganziation {
|
||||
t.Fatalf("%s: expected organization (%s) to match configured organization (%s)", name, b.organization, tc.expectedOrganziation)
|
||||
}
|
||||
if tc.expectedWorkspacePrefix != "" && b.workspaceMapping.prefix != tc.expectedWorkspacePrefix {
|
||||
t.Fatalf("%s: expected workspace prefix mapping (%s) to match configured workspace prefix (%s)", name, b.workspaceMapping.prefix, tc.expectedWorkspacePrefix)
|
||||
if tc.expectedWorkspacePrefix != "" && b.WorkspaceMapping.Prefix != tc.expectedWorkspacePrefix {
|
||||
t.Fatalf("%s: expected workspace prefix mapping (%s) to match configured workspace prefix (%s)", name, b.WorkspaceMapping.Prefix, tc.expectedWorkspacePrefix)
|
||||
}
|
||||
if tc.expectedWorkspaceName != "" && b.workspaceMapping.name != tc.expectedWorkspaceName {
|
||||
t.Fatalf("%s: expected workspace name mapping (%s) to match configured workspace name (%s)", name, b.workspaceMapping.name, tc.expectedWorkspaceName)
|
||||
if tc.expectedWorkspaceName != "" && b.WorkspaceMapping.Name != tc.expectedWorkspaceName {
|
||||
t.Fatalf("%s: expected workspace name mapping (%s) to match configured workspace name (%s)", name, b.WorkspaceMapping.Name, tc.expectedWorkspaceName)
|
||||
}
|
||||
if len(tc.expectedWorkspaceTags) > 0 {
|
||||
presentSet := make(map[string]struct{})
|
||||
for _, tag := range b.workspaceMapping.tags {
|
||||
for _, tag := range b.WorkspaceMapping.Tags {
|
||||
presentSet[tag] = struct{}{}
|
||||
}
|
||||
|
||||
|
@ -454,18 +471,18 @@ func TestCloud_setConfigurationFields(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
for _, actual := range b.workspaceMapping.tags {
|
||||
for _, actual := range b.WorkspaceMapping.Tags {
|
||||
if _, ok := expectedSet[actual]; !ok {
|
||||
unexpected = append(missing, actual)
|
||||
}
|
||||
}
|
||||
|
||||
if len(missing) > 0 {
|
||||
t.Fatalf("%s: expected workspace tag mapping (%s) to contain the following tags: %s", name, b.workspaceMapping.tags, missing)
|
||||
t.Fatalf("%s: expected workspace tag mapping (%s) to contain the following tags: %s", name, b.WorkspaceMapping.Tags, missing)
|
||||
}
|
||||
|
||||
if len(unexpected) > 0 {
|
||||
t.Fatalf("%s: expected workspace tag mapping (%s) to NOT contain the following tags: %s", name, b.workspaceMapping.tags, unexpected)
|
||||
t.Fatalf("%s: expected workspace tag mapping (%s) to NOT contain the following tags: %s", name, b.WorkspaceMapping.Tags, unexpected)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -575,28 +592,16 @@ func TestCloud_addAndRemoveWorkspacesDefault(t *testing.T) {
|
|||
b, bCleanup := testBackendDefault(t)
|
||||
defer bCleanup()
|
||||
|
||||
if _, err := b.Workspaces(); err != backend.ErrWorkspacesNotSupported {
|
||||
t.Fatalf("expected error %v, got %v", backend.ErrWorkspacesNotSupported, err)
|
||||
}
|
||||
|
||||
if _, err := b.StateMgr(backend.DefaultStateName); err != nil {
|
||||
if _, err := b.StateMgr(testBackendSingleWorkspaceName); err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if _, err := b.StateMgr("prod"); err != backend.ErrWorkspacesNotSupported {
|
||||
t.Fatalf("expected error %v, got %v", backend.ErrWorkspacesNotSupported, err)
|
||||
}
|
||||
|
||||
if err := b.DeleteWorkspace(backend.DefaultStateName); err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
if err := b.DeleteWorkspace("prod"); err != backend.ErrWorkspacesNotSupported {
|
||||
if err := b.DeleteWorkspace(testBackendSingleWorkspaceName); err != backend.ErrWorkspacesNotSupported {
|
||||
t.Fatalf("expected error %v, got %v", backend.ErrWorkspacesNotSupported, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloud_addAndRemoveWorkspacesNoDefault(t *testing.T) {
|
||||
func TestCloud_addAndRemoveWorkspacesWithPrefix(t *testing.T) {
|
||||
b, bCleanup := testBackendWithPrefix(t)
|
||||
defer bCleanup()
|
||||
|
||||
|
@ -808,7 +813,7 @@ func TestCloud_StateMgr_versionCheck(t *testing.T) {
|
|||
if _, err := b.client.Workspaces.Update(
|
||||
context.Background(),
|
||||
b.organization,
|
||||
b.workspaceMapping.name,
|
||||
b.WorkspaceMapping.Name,
|
||||
tfe.WorkspaceUpdateOptions{
|
||||
TerraformVersion: tfe.String(v0140.String()),
|
||||
},
|
||||
|
@ -817,7 +822,7 @@ func TestCloud_StateMgr_versionCheck(t *testing.T) {
|
|||
}
|
||||
|
||||
// This should succeed
|
||||
if _, err := b.StateMgr(backend.DefaultStateName); err != nil {
|
||||
if _, err := b.StateMgr(testBackendSingleWorkspaceName); err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
|
||||
|
@ -825,7 +830,7 @@ func TestCloud_StateMgr_versionCheck(t *testing.T) {
|
|||
if _, err := b.client.Workspaces.Update(
|
||||
context.Background(),
|
||||
b.organization,
|
||||
b.workspaceMapping.name,
|
||||
b.WorkspaceMapping.Name,
|
||||
tfe.WorkspaceUpdateOptions{
|
||||
TerraformVersion: tfe.String(v0135.String()),
|
||||
},
|
||||
|
@ -835,7 +840,7 @@ func TestCloud_StateMgr_versionCheck(t *testing.T) {
|
|||
|
||||
// This should fail
|
||||
want := `Remote workspace Terraform version "0.13.5" does not match local Terraform version "0.14.0"`
|
||||
if _, err := b.StateMgr(backend.DefaultStateName); err.Error() != want {
|
||||
if _, err := b.StateMgr(testBackendSingleWorkspaceName); err.Error() != want {
|
||||
t.Fatalf("wrong error\n got: %v\nwant: %v", err.Error(), want)
|
||||
}
|
||||
}
|
||||
|
@ -865,7 +870,7 @@ func TestCloud_StateMgr_versionCheckLatest(t *testing.T) {
|
|||
if _, err := b.client.Workspaces.Update(
|
||||
context.Background(),
|
||||
b.organization,
|
||||
b.workspaceMapping.name,
|
||||
b.WorkspaceMapping.Name,
|
||||
tfe.WorkspaceUpdateOptions{
|
||||
TerraformVersion: tfe.String("latest"),
|
||||
},
|
||||
|
@ -874,7 +879,7 @@ func TestCloud_StateMgr_versionCheckLatest(t *testing.T) {
|
|||
}
|
||||
|
||||
// This should succeed despite not being a string match
|
||||
if _, err := b.StateMgr(backend.DefaultStateName); err != nil {
|
||||
if _, err := b.StateMgr(testBackendSingleWorkspaceName); err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -923,7 +928,7 @@ func TestCloud_VerifyWorkspaceTerraformVersion(t *testing.T) {
|
|||
if _, err := b.client.Workspaces.Update(
|
||||
context.Background(),
|
||||
b.organization,
|
||||
b.workspaceMapping.name,
|
||||
b.WorkspaceMapping.Name,
|
||||
tfe.WorkspaceUpdateOptions{
|
||||
Operations: tfe.Bool(tc.operations),
|
||||
TerraformVersion: tfe.String(tc.remote),
|
||||
|
@ -974,7 +979,7 @@ func TestCloud_VerifyWorkspaceTerraformVersion_workspaceErrors(t *testing.T) {
|
|||
if _, err := b.client.Workspaces.Update(
|
||||
context.Background(),
|
||||
b.organization,
|
||||
b.workspaceMapping.name,
|
||||
b.WorkspaceMapping.Name,
|
||||
tfe.WorkspaceUpdateOptions{
|
||||
TerraformVersion: tfe.String("1.0.cheetarah"),
|
||||
},
|
||||
|
@ -1022,7 +1027,7 @@ func TestCloud_VerifyWorkspaceTerraformVersion_ignoreFlagSet(t *testing.T) {
|
|||
if _, err := b.client.Workspaces.Update(
|
||||
context.Background(),
|
||||
b.organization,
|
||||
b.workspaceMapping.name,
|
||||
b.WorkspaceMapping.Name,
|
||||
tfe.WorkspaceUpdateOptions{
|
||||
TerraformVersion: tfe.String(remote.String()),
|
||||
},
|
||||
|
@ -1041,7 +1046,7 @@ func TestCloud_VerifyWorkspaceTerraformVersion_ignoreFlagSet(t *testing.T) {
|
|||
if got, want := diags[0].Description().Summary, "Terraform version mismatch"; got != want {
|
||||
t.Errorf("wrong summary: got %s, want %s", got, want)
|
||||
}
|
||||
wantDetail := "The local Terraform version (0.14.0) does not match the configured version for remote workspace hashicorp/prod (0.13.5)."
|
||||
wantDetail := "The local Terraform version (0.14.0) does not match the configured version for remote workspace hashicorp/app-prod (0.13.5)."
|
||||
if got := diags[0].Description().Detail; got != wantDetail {
|
||||
t.Errorf("wrong summary: got %s, want %s", got, wantDetail)
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ var (
|
|||
credsSrc = auth.StaticCredentialsSource(map[svchost.Hostname]map[string]interface{}{
|
||||
tfeHost: {"token": testCred},
|
||||
})
|
||||
testBackendSingleWorkspaceName = "app-prod"
|
||||
)
|
||||
|
||||
// mockInput is a mock implementation of terraform.UIInput.
|
||||
|
@ -70,7 +71,7 @@ func testBackendDefault(t *testing.T) (*Cloud, func()) {
|
|||
"organization": cty.StringVal("hashicorp"),
|
||||
"token": cty.NullVal(cty.String),
|
||||
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.StringVal("prod"),
|
||||
"name": cty.StringVal(testBackendSingleWorkspaceName),
|
||||
"prefix": cty.NullVal(cty.String),
|
||||
"tags": cty.NullVal(cty.Set(cty.String)),
|
||||
}),
|
||||
|
@ -116,7 +117,7 @@ func testBackendNoOperations(t *testing.T) (*Cloud, func()) {
|
|||
"organization": cty.StringVal("no-operations"),
|
||||
"token": cty.NullVal(cty.String),
|
||||
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.StringVal("prod"),
|
||||
"name": cty.StringVal(testBackendSingleWorkspaceName),
|
||||
"prefix": cty.NullVal(cty.String),
|
||||
"tags": cty.NullVal(cty.Set(cty.String)),
|
||||
}),
|
||||
|
@ -128,7 +129,7 @@ func testRemoteClient(t *testing.T) remote.Client {
|
|||
b, bCleanup := testBackendDefault(t)
|
||||
defer bCleanup()
|
||||
|
||||
raw, err := b.StateMgr(backend.DefaultStateName)
|
||||
raw, err := b.StateMgr(testBackendSingleWorkspaceName)
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
@ -182,9 +183,9 @@ func testBackend(t *testing.T, obj cty.Value) (*Cloud, func()) {
|
|||
}
|
||||
|
||||
// Create the default workspace if required.
|
||||
if b.workspaceMapping.name != "" {
|
||||
if b.WorkspaceMapping.Name != "" {
|
||||
_, err = b.client.Workspaces.Create(ctx, b.organization, tfe.WorkspaceCreateOptions{
|
||||
Name: tfe.String(b.workspaceMapping.name),
|
||||
Name: tfe.String(b.WorkspaceMapping.Name),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
|
|
Loading…
Reference in New Issue