mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
Signed-off-by: Nathan Baulch <nathan.baulch@gmail.com> Signed-off-by: Christian Mesh <christianmesh1@gmail.com> Co-authored-by: Christian Mesh <christianmesh1@gmail.com>
336 lines
11 KiB
Go
336 lines
11 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package config
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/hcltest"
|
|
"github.com/opentofu/opentofu/internal/configs/hcl2shim"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
func TestMergeMethodConfigs(t *testing.T) {
|
|
makeMethodConfig := func(typeName, name, key, value string) MethodConfig {
|
|
return MethodConfig{
|
|
Type: typeName,
|
|
Name: name,
|
|
Body: hcl2shim.SynthBody("method", map[string]cty.Value{
|
|
key: cty.StringVal(value),
|
|
}),
|
|
}
|
|
}
|
|
|
|
schema := &hcl.BodySchema{Attributes: []hcl.AttributeSchema{{Name: "key"}}}
|
|
|
|
tests := []struct {
|
|
name string
|
|
configSchema *hcl.BodySchema
|
|
input []MethodConfig
|
|
override []MethodConfig
|
|
expected []MethodConfig
|
|
}{
|
|
{
|
|
name: "empty",
|
|
configSchema: nil,
|
|
input: []MethodConfig{},
|
|
override: []MethodConfig{},
|
|
expected: []MethodConfig{},
|
|
},
|
|
{
|
|
name: "override one method config body",
|
|
configSchema: schema,
|
|
input: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "value"),
|
|
},
|
|
override: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "override"),
|
|
},
|
|
expected: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "override"),
|
|
},
|
|
},
|
|
{
|
|
name: "initial config is empty",
|
|
configSchema: schema,
|
|
input: []MethodConfig{},
|
|
override: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "override"),
|
|
},
|
|
expected: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "override"),
|
|
},
|
|
},
|
|
{
|
|
name: "override multiple method configs",
|
|
configSchema: schema,
|
|
input: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "value"),
|
|
makeMethodConfig("type", "name2", "key", "value"),
|
|
makeMethodConfig("type", "name3", "key", "value"),
|
|
},
|
|
override: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "override1"),
|
|
makeMethodConfig("type", "name2", "key", "override2"),
|
|
},
|
|
expected: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "override1"),
|
|
makeMethodConfig("type", "name2", "key", "override2"),
|
|
makeMethodConfig("type", "name3", "key", "value"),
|
|
},
|
|
},
|
|
{
|
|
name: "override config is empty",
|
|
configSchema: schema,
|
|
input: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "value"),
|
|
},
|
|
override: []MethodConfig{},
|
|
expected: []MethodConfig{
|
|
makeMethodConfig("type", "name", "key", "value"),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
output := mergeMethodConfigs(test.input, test.override)
|
|
|
|
// for each of the expected methods, check if it exists in the output
|
|
for _, expectedMethod := range test.expected {
|
|
found := false
|
|
for _, method := range output {
|
|
if method.Type == expectedMethod.Type && method.Name == expectedMethod.Name {
|
|
found = true
|
|
expectedContent, _ := expectedMethod.Body.Content(test.configSchema)
|
|
actualContent, diags := method.Body.Content(test.configSchema)
|
|
if diags.HasErrors() {
|
|
t.Fatalf("unexpected diagnostics: %v", diags)
|
|
}
|
|
// Only compare the attributes here, so that we don't look at things like the MissingItemRange on the hcl.Body
|
|
if !reflect.DeepEqual(expectedContent.Attributes, actualContent.Attributes) {
|
|
t.Errorf("expected %v, got %v", spew.Sdump(expectedContent.Attributes), spew.Sdump(actualContent.Attributes))
|
|
}
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("expected method %v not found in output", spew.Sdump(expectedMethod))
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMergeKeyProviderConfigs(t *testing.T) {
|
|
makeKeyProviderConfig := func(typeName, name, key, value string) KeyProviderConfig {
|
|
return KeyProviderConfig{
|
|
Type: typeName,
|
|
Name: name,
|
|
Body: hcl2shim.SynthBody("key_provider", map[string]cty.Value{
|
|
key: cty.StringVal(value),
|
|
}),
|
|
}
|
|
}
|
|
|
|
schema := &hcl.BodySchema{Attributes: []hcl.AttributeSchema{{Name: "key"}}}
|
|
|
|
tests := []struct {
|
|
name string
|
|
configSchema *hcl.BodySchema
|
|
input []KeyProviderConfig
|
|
override []KeyProviderConfig
|
|
expected []KeyProviderConfig
|
|
}{
|
|
{
|
|
name: "empty",
|
|
configSchema: nil,
|
|
input: []KeyProviderConfig{},
|
|
override: []KeyProviderConfig{},
|
|
expected: []KeyProviderConfig{},
|
|
},
|
|
{
|
|
name: "override one key provider config body",
|
|
configSchema: schema,
|
|
input: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "value"),
|
|
},
|
|
override: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "override"),
|
|
},
|
|
expected: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "override"),
|
|
},
|
|
},
|
|
{
|
|
name: "initial config is empty",
|
|
configSchema: schema,
|
|
input: []KeyProviderConfig{},
|
|
override: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "override"),
|
|
},
|
|
expected: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "override"),
|
|
},
|
|
},
|
|
{
|
|
name: "override multiple key provider configs",
|
|
configSchema: schema,
|
|
input: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "value"),
|
|
makeKeyProviderConfig("type", "name2", "key", "value"),
|
|
},
|
|
override: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "override1"),
|
|
makeKeyProviderConfig("type", "name2", "key", "override2"),
|
|
},
|
|
expected: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "override1"),
|
|
makeKeyProviderConfig("type", "name2", "key", "override2"),
|
|
},
|
|
},
|
|
{
|
|
name: "override config is empty",
|
|
configSchema: schema,
|
|
input: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "value"),
|
|
},
|
|
override: []KeyProviderConfig{},
|
|
expected: []KeyProviderConfig{
|
|
makeKeyProviderConfig("type", "name", "key", "value"),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
output := mergeKeyProviderConfigs(test.input, test.override)
|
|
|
|
// for each of the expected key providers, check if it exists in the output
|
|
for _, expectedKeyProvider := range test.expected {
|
|
found := false
|
|
for _, keyProvider := range output {
|
|
if keyProvider.Type == expectedKeyProvider.Type && keyProvider.Name == expectedKeyProvider.Name {
|
|
found = true
|
|
expectedContent, _ := expectedKeyProvider.Body.Content(test.configSchema)
|
|
actualContent, diags := keyProvider.Body.Content(test.configSchema)
|
|
if diags.HasErrors() {
|
|
t.Fatalf("unexpected diagnostics: %v", diags)
|
|
}
|
|
// Only compare the attributes here, so that we don't look at things like the MissingItemRange on the hcl.Body
|
|
if !reflect.DeepEqual(expectedContent.Attributes, actualContent.Attributes) {
|
|
t.Errorf("expected %v, got %v", spew.Sdump(expectedContent.Attributes), spew.Sdump(actualContent.Attributes))
|
|
}
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("expected key provider %v not found in output", spew.Sdump(expectedKeyProvider))
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMergeTargetConfigs(t *testing.T) {
|
|
makeTargetConfig := func(enforced bool, method hcl.Expression, fallback *TargetConfig) *TargetConfig {
|
|
return &TargetConfig{
|
|
Method: method,
|
|
Fallback: fallback,
|
|
}
|
|
}
|
|
|
|
makeEnforceableTargetConfig := func(enforced bool, method hcl.Expression, fallback *TargetConfig) *EnforceableTargetConfig {
|
|
return &EnforceableTargetConfig{
|
|
Enforced: enforced,
|
|
Method: method,
|
|
Fallback: fallback,
|
|
}
|
|
}
|
|
|
|
expressionOne := hcltest.MockExprLiteral(cty.UnknownVal(cty.Set(cty.String)))
|
|
expressionTwo := hcltest.MockExprLiteral(cty.UnknownVal(cty.Set(cty.Bool)))
|
|
|
|
tests := []struct {
|
|
name string
|
|
input *EnforceableTargetConfig
|
|
override *EnforceableTargetConfig
|
|
expected *EnforceableTargetConfig
|
|
}{
|
|
{
|
|
name: "both nil",
|
|
input: nil,
|
|
override: nil,
|
|
expected: nil,
|
|
},
|
|
{
|
|
name: "input is nil",
|
|
input: nil,
|
|
override: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
expected: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
},
|
|
{
|
|
name: "override is nil",
|
|
input: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
override: nil,
|
|
expected: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
},
|
|
{
|
|
name: "override target config method",
|
|
input: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
override: makeEnforceableTargetConfig(true, expressionTwo, nil),
|
|
expected: makeEnforceableTargetConfig(true, expressionTwo, nil),
|
|
},
|
|
{
|
|
name: "override target config fallback",
|
|
input: makeEnforceableTargetConfig(true, expressionOne, makeTargetConfig(true, expressionOne, nil)),
|
|
override: makeEnforceableTargetConfig(true, expressionOne, makeTargetConfig(true, expressionTwo, nil)),
|
|
expected: makeEnforceableTargetConfig(true, expressionOne, makeTargetConfig(true, expressionTwo, nil)),
|
|
},
|
|
{
|
|
name: "override target config fallback",
|
|
input: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
override: makeEnforceableTargetConfig(true, expressionOne, makeTargetConfig(true, expressionTwo, nil)),
|
|
expected: makeEnforceableTargetConfig(true, expressionOne, makeTargetConfig(true, expressionTwo, nil)),
|
|
},
|
|
{
|
|
name: "override target config enforced - should be true if any are true",
|
|
input: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
override: makeEnforceableTargetConfig(false, expressionOne, nil),
|
|
expected: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
},
|
|
{
|
|
name: "override target config enforced - should be true if any are true",
|
|
input: makeEnforceableTargetConfig(false, expressionOne, nil),
|
|
override: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
expected: makeEnforceableTargetConfig(true, expressionOne, nil),
|
|
},
|
|
{
|
|
name: "override target config enforced - should be false if both are false",
|
|
input: makeEnforceableTargetConfig(false, expressionOne, nil),
|
|
override: makeEnforceableTargetConfig(false, expressionOne, nil),
|
|
expected: makeEnforceableTargetConfig(false, expressionOne, nil),
|
|
},
|
|
{
|
|
name: "override enforced, method and fallback",
|
|
input: makeEnforceableTargetConfig(false, expressionOne, makeTargetConfig(true, expressionOne, nil)),
|
|
override: makeEnforceableTargetConfig(true, expressionTwo, makeTargetConfig(true, expressionTwo, nil)),
|
|
expected: makeEnforceableTargetConfig(true, expressionTwo, makeTargetConfig(true, expressionTwo, nil)),
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
output := mergeEnforceableTargetConfigs(test.input, test.override)
|
|
|
|
if !reflect.DeepEqual(output, test.expected) {
|
|
t.Errorf("expected %v, got %v", spew.Sdump(test.expected), spew.Sdump(output))
|
|
}
|
|
})
|
|
}
|
|
}
|