mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
backend/remote: Filter environment variables when loading context (#23358)
* 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 https://github.com/hashicorp/terraform/issues/23283.
This commit is contained in:
parent
b09626b0cc
commit
af77d1d22c
@ -116,8 +116,10 @@ func (b *Remote) Context(op *backend.Operation) (*terraform.Context, statemgr.Fu
|
|||||||
op.Variables = make(map[string]backend.UnparsedVariableValue)
|
op.Variables = make(map[string]backend.UnparsedVariableValue)
|
||||||
}
|
}
|
||||||
for _, v := range tfeVariables.Items {
|
for _, v := range tfeVariables.Items {
|
||||||
op.Variables[v.Key] = &remoteStoredVariableValue{
|
if v.Category == tfe.CategoryTerraform {
|
||||||
definition: v,
|
op.Variables[v.Key] = &remoteStoredVariableValue{
|
||||||
|
definition: v,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
tfe "github.com/hashicorp/go-tfe"
|
tfe "github.com/hashicorp/go-tfe"
|
||||||
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
|
"github.com/hashicorp/terraform/internal/initwd"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -27,6 +27,7 @@ type mockClient struct {
|
|||||||
PolicyChecks *mockPolicyChecks
|
PolicyChecks *mockPolicyChecks
|
||||||
Runs *mockRuns
|
Runs *mockRuns
|
||||||
StateVersions *mockStateVersions
|
StateVersions *mockStateVersions
|
||||||
|
Variables *mockVariables
|
||||||
Workspaces *mockWorkspaces
|
Workspaces *mockWorkspaces
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ func newMockClient() *mockClient {
|
|||||||
c.PolicyChecks = newMockPolicyChecks(c)
|
c.PolicyChecks = newMockPolicyChecks(c)
|
||||||
c.Runs = newMockRuns(c)
|
c.Runs = newMockRuns(c)
|
||||||
c.StateVersions = newMockStateVersions(c)
|
c.StateVersions = newMockStateVersions(c)
|
||||||
|
c.Variables = newMockVariables(c)
|
||||||
c.Workspaces = newMockWorkspaces(c)
|
c.Workspaces = newMockWorkspaces(c)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@ -945,6 +947,63 @@ func (m *mockStateVersions) Download(ctx context.Context, url string) ([]byte, e
|
|||||||
return state, nil
|
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 {
|
type mockWorkspaces struct {
|
||||||
client *mockClient
|
client *mockClient
|
||||||
workspaceIDs map[string]*tfe.Workspace
|
workspaceIDs map[string]*tfe.Workspace
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
tfe "github.com/hashicorp/go-tfe"
|
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/auth"
|
||||||
"github.com/hashicorp/terraform-svchost/disco"
|
"github.com/hashicorp/terraform-svchost/disco"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
@ -123,6 +123,7 @@ func testBackend(t *testing.T, obj cty.Value) (*Remote, func()) {
|
|||||||
b.client.PolicyChecks = mc.PolicyChecks
|
b.client.PolicyChecks = mc.PolicyChecks
|
||||||
b.client.Runs = mc.Runs
|
b.client.Runs = mc.Runs
|
||||||
b.client.StateVersions = mc.StateVersions
|
b.client.StateVersions = mc.StateVersions
|
||||||
|
b.client.Variables = mc.Variables
|
||||||
b.client.Workspaces = mc.Workspaces
|
b.client.Workspaces = mc.Workspaces
|
||||||
|
|
||||||
b.ShowDiagnostics = func(vals ...interface{}) {
|
b.ShowDiagnostics = func(vals ...interface{}) {
|
||||||
|
Loading…
Reference in New Issue
Block a user