Skip to content

Commit

Permalink
backend/remote: Filter environment variables when loading context (#2…
Browse files Browse the repository at this point in the history
…3358)

* backend/remote: Filter environment variables when loading context

Following up on #23122, the remote system (Terraform Cloud or
Enterprise) serves environment and Terraform variables using a single
type of object. We only should load Terraform variables into the
Terraform context.

Fixes #23283.
  • Loading branch information
beekus authored and Pam Selle committed Nov 13, 2019
1 parent b09626b commit af77d1d
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 3 deletions.
6 changes: 4 additions & 2 deletions backend/remote/backend_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ func (b *Remote) Context(op *backend.Operation) (*terraform.Context, statemgr.Fu
op.Variables = make(map[string]backend.UnparsedVariableValue)
}
for _, v := range tfeVariables.Items {
op.Variables[v.Key] = &remoteStoredVariableValue{
definition: v,
if v.Category == tfe.CategoryTerraform {
op.Variables[v.Key] = &remoteStoredVariableValue{
definition: v,
}
}
}
}
Expand Down
71 changes: 71 additions & 0 deletions backend/remote/backend_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"testing"

tfe "github.com/hashicorp/go-tfe"
"github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/internal/initwd"
"github.com/zclconf/go-cty/cty"
)

Expand Down Expand Up @@ -141,3 +143,72 @@ func TestRemoteStoredVariableValue(t *testing.T) {
})
}
}

func TestRemoteContextWithVars(t *testing.T) {
catTerraform := tfe.CategoryTerraform
catEnv := tfe.CategoryEnv

tests := map[string]struct {
Opts *tfe.VariableCreateOptions
WantError string
}{
"Terraform variable": {
&tfe.VariableCreateOptions{
Category: &catTerraform,
},
`Value for undeclared variable: A variable named "key" was assigned a value, but the root module does not declare a variable of that name. To use this value, add a "variable" block to the configuration.`,
},
"environment variable": {
&tfe.VariableCreateOptions{
Category: &catEnv,
},
``,
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
configDir := "./testdata/empty"

b, bCleanup := testBackendDefault(t)
defer bCleanup()

_, configLoader, configCleanup := initwd.MustLoadConfigForTests(t, configDir)
defer configCleanup()

op := &backend.Operation{
ConfigDir: configDir,
ConfigLoader: configLoader,
Workspace: backend.DefaultStateName,
}

v := test.Opts
if v.Key == nil {
key := "key"
v.Key = &key
}
if v.Workspace == nil {
v.Workspace = &tfe.Workspace{
Name: b.workspace,
}
}
b.client.Variables.Create(nil, *v)

_, _, diags := b.Context(op)

if test.WantError != "" {
if !diags.HasErrors() {
t.Fatalf("missing expected error\ngot: <no error>\nwant: %s", test.WantError)
}
errStr := diags.Err().Error()
if errStr != test.WantError {
t.Fatalf("wrong error\ngot: %s\nwant: %s", errStr, test.WantError)
}
} else {
if diags.HasErrors() {
t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error())
}
}
})
}
}
59 changes: 59 additions & 0 deletions backend/remote/backend_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type mockClient struct {
PolicyChecks *mockPolicyChecks
Runs *mockRuns
StateVersions *mockStateVersions
Variables *mockVariables
Workspaces *mockWorkspaces
}

Expand All @@ -40,6 +41,7 @@ func newMockClient() *mockClient {
c.PolicyChecks = newMockPolicyChecks(c)
c.Runs = newMockRuns(c)
c.StateVersions = newMockStateVersions(c)
c.Variables = newMockVariables(c)
c.Workspaces = newMockWorkspaces(c)
return c
}
Expand Down Expand Up @@ -945,6 +947,63 @@ func (m *mockStateVersions) Download(ctx context.Context, url string) ([]byte, e
return state, nil
}

type mockVariables struct {
client *mockClient
workspaces map[string]*tfe.VariableList
}

func newMockVariables(client *mockClient) *mockVariables {
return &mockVariables{
client: client,
workspaces: make(map[string]*tfe.VariableList),
}
}

func (m *mockVariables) List(ctx context.Context, options tfe.VariableListOptions) (*tfe.VariableList, error) {
vl := m.workspaces[*options.Workspace]
return vl, nil
}

func (m *mockVariables) Create(ctx context.Context, options tfe.VariableCreateOptions) (*tfe.Variable, error) {
v := &tfe.Variable{
ID: generateID("var-"),
Key: *options.Key,
Category: *options.Category,
}
if options.Value != nil {
v.Value = *options.Value
}
if options.HCL != nil {
v.HCL = *options.HCL
}
if options.Sensitive != nil {
v.Sensitive = *options.Sensitive
}

workspace := options.Workspace.Name

if m.workspaces[workspace] == nil {
m.workspaces[workspace] = &tfe.VariableList{}
}

vl := m.workspaces[workspace]
vl.Items = append(vl.Items, v)

return v, nil
}

func (m *mockVariables) Read(ctx context.Context, variableID string) (*tfe.Variable, error) {
panic("not implemented")
}

func (m *mockVariables) Update(ctx context.Context, variableID string, options tfe.VariableUpdateOptions) (*tfe.Variable, error) {
panic("not implemented")
}

func (m *mockVariables) Delete(ctx context.Context, variableID string) error {
panic("not implemented")
}

type mockWorkspaces struct {
client *mockClient
workspaceIDs map[string]*tfe.Workspace
Expand Down
3 changes: 2 additions & 1 deletion backend/remote/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"testing"

tfe "github.com/hashicorp/go-tfe"
"github.com/hashicorp/terraform-svchost"
svchost "github.com/hashicorp/terraform-svchost"
"github.com/hashicorp/terraform-svchost/auth"
"github.com/hashicorp/terraform-svchost/disco"
"github.com/hashicorp/terraform/backend"
Expand Down Expand Up @@ -123,6 +123,7 @@ func testBackend(t *testing.T, obj cty.Value) (*Remote, func()) {
b.client.PolicyChecks = mc.PolicyChecks
b.client.Runs = mc.Runs
b.client.StateVersions = mc.StateVersions
b.client.Variables = mc.Variables
b.client.Workspaces = mc.Workspaces

b.ShowDiagnostics = func(vals ...interface{}) {
Expand Down

0 comments on commit af77d1d

Please sign in to comment.