mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
e43ef0a979
Earlier this evening I tried to run the Go [modernize](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/modernize) analyzer on OPA. That didn't go as planned: - https://github.com/golang/go/issues/73661 - https://github.com/golang/go/issues/73663 While we wait for that to be fixed, I figured an old-fashioned search-and-replace across the repo may work for at least the `interface{}` to `any` conversion. That should help make it easier to see the other fixes as applied by the modernize tool once it has had those issues resolved. Signed-off-by: Anders Eknert <anders@styra.com>
487 lines
11 KiB
Go
487 lines
11 KiB
Go
// Copyright 2016 The OPA Authors. All rights reserved.
|
|
// Use of this source code is governed by an Apache2
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// nolint: goconst // string duplication is for test readability.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"sigs.k8s.io/yaml"
|
|
|
|
"github.com/open-policy-agent/opa/v1/util/test"
|
|
)
|
|
|
|
func setTestEnvVar(t *testing.T, name, value string) string {
|
|
envKey := fmt.Sprintf("%s_%s", t.Name(), name)
|
|
t.Setenv(envKey, value)
|
|
return envKey
|
|
}
|
|
|
|
func TestSubEnvVarsVarsSubOne(t *testing.T) {
|
|
envKey := setTestEnvVar(t, "var1", "foo")
|
|
configYaml := fmt.Sprintf("field1: ${%s}", envKey)
|
|
|
|
expected := "field1: foo"
|
|
|
|
actual := subEnvVars(configYaml)
|
|
|
|
if actual != expected {
|
|
t.Errorf("Expected: '%s'\nActual: '%s'", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestSubEnvVarsVarsSubMulti(t *testing.T) {
|
|
urlEnvKey := setTestEnvVar(t, "SERVICE_URL", "https://example.com/control-plane-api/v1")
|
|
tokenEnvKey := setTestEnvVar(t, "BEARER_TOKEN", "bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm")
|
|
configYaml := fmt.Sprintf(`
|
|
services:
|
|
- name: acmecorp
|
|
url: ${%s}
|
|
credentials:
|
|
bearer:
|
|
token: "${%s}"
|
|
|
|
discovery:
|
|
name: /example/discovery
|
|
prefix: configuration`, urlEnvKey, tokenEnvKey)
|
|
|
|
expected := `
|
|
services:
|
|
- name: acmecorp
|
|
url: https://example.com/control-plane-api/v1
|
|
credentials:
|
|
bearer:
|
|
token: "bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm"
|
|
|
|
discovery:
|
|
name: /example/discovery
|
|
prefix: configuration`
|
|
|
|
actual := subEnvVars(configYaml)
|
|
|
|
if actual != expected {
|
|
t.Errorf("\nExpected: '%s'\nActual: '%s'", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestSubEnvVarsVarsNoVars(t *testing.T) {
|
|
configYaml := "field1: foo"
|
|
expected := "field1: foo"
|
|
|
|
actual := subEnvVars(configYaml)
|
|
|
|
if actual != expected {
|
|
t.Errorf("Expected: '%s'\nActual: '%s'", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestSubEnvVarsVarsEmptyString(t *testing.T) {
|
|
configYaml := ""
|
|
expected := ""
|
|
|
|
actual := subEnvVars(configYaml)
|
|
|
|
if actual != expected {
|
|
t.Errorf("Expected: '%s'\nActual: '%s'", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestSubEnvVarsVarsSubMissingEnvVar(t *testing.T) {
|
|
envKey := setTestEnvVar(t, "var1", "foo")
|
|
configYaml := fmt.Sprintf("field1: '${%s}'", envKey)
|
|
|
|
// Remove the env var and expect the system to sub in ""
|
|
os.Unsetenv(envKey)
|
|
expected := "field1: ''"
|
|
|
|
actual := subEnvVars(configYaml)
|
|
|
|
if actual != expected {
|
|
t.Errorf("Expected: '%s'\nActual: '%s'", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestSubEnvVarsVarsSubEmptyVarName(t *testing.T) {
|
|
configYaml := "field1: '${}'"
|
|
expected := "field1: ''"
|
|
|
|
actual := subEnvVars(configYaml)
|
|
|
|
if actual != expected {
|
|
t.Errorf("Expected: '%s'\nActual: '%s'", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestMergeValuesNoOverride(t *testing.T) {
|
|
dest := map[string]any{}
|
|
src := map[string]any{
|
|
"a": map[string]any{
|
|
"b": "foo",
|
|
},
|
|
}
|
|
|
|
actual := mergeValues(dest, src)
|
|
|
|
expected := map[string]any{
|
|
"a": map[string]any{
|
|
"b": "foo",
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Errorf("merged map does not match expected:\n\nExpected: %+v\nActual: %+v", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestMergeValuesOverrideSingle(t *testing.T) {
|
|
dest := map[string]any{
|
|
"a": "bar",
|
|
}
|
|
src := map[string]any{
|
|
"a": "override-value",
|
|
}
|
|
|
|
actual := mergeValues(dest, src)
|
|
|
|
expected := map[string]any{
|
|
"a": "override-value",
|
|
}
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Errorf("merged map does not match expected:\n\nExpected: %+v\nActual: %+v", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestMergeValuesOverrideSingleNested(t *testing.T) {
|
|
dest := map[string]any{
|
|
"a": map[string]any{
|
|
"b": "foo",
|
|
},
|
|
}
|
|
src := map[string]any{
|
|
"a": map[string]any{
|
|
"b": "override-value",
|
|
},
|
|
}
|
|
|
|
actual := mergeValues(dest, src)
|
|
|
|
expected := map[string]any{
|
|
"a": map[string]any{
|
|
"b": "override-value",
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Errorf("merged map does not match expected:\n\nExpected: %+v\nActual: %+v", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestMergeValuesOverrideMultipleNested(t *testing.T) {
|
|
dest := map[string]any{
|
|
"a": map[string]any{
|
|
"b": map[string]any{
|
|
"k1": "v1",
|
|
"k2": "v2",
|
|
"k3": "v3",
|
|
"k4": "v4",
|
|
},
|
|
},
|
|
}
|
|
src := map[string]any{
|
|
"a": map[string]any{
|
|
"b": map[string]any{
|
|
"k1": "v1-override",
|
|
"k4": "v4-override",
|
|
},
|
|
},
|
|
}
|
|
|
|
actual := mergeValues(dest, src)
|
|
|
|
expected := map[string]any{
|
|
"a": map[string]any{
|
|
"b": map[string]any{
|
|
"k1": "v1-override",
|
|
"k2": "v2",
|
|
"k3": "v3",
|
|
"k4": "v4-override",
|
|
},
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Errorf("merged map does not match expected:\n\nExpected: %+v\nActual: %+v", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestMergeValuesOverrideSingleList(t *testing.T) {
|
|
dest := map[string]any{
|
|
"a": map[string]any{
|
|
"b": []map[string]any{
|
|
{
|
|
"k1": "v1",
|
|
"k2": "v2",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
src := map[string]any{
|
|
"a": map[string]any{
|
|
"b": []map[string]any{
|
|
{
|
|
"k3": "v3",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
actual := mergeValues(dest, src)
|
|
|
|
// The list index 0 should have been replaced instead of merging the sub objects
|
|
expected := map[string]any{
|
|
"a": map[string]any{
|
|
"b": []map[string]any{
|
|
{
|
|
"k3": "v3",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Errorf("merged map does not match expected:\n\nExpected: %+v\nActual: %+v", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestMergeValuesNoSrc(t *testing.T) {
|
|
dest := map[string]any{
|
|
"a": map[string]any{
|
|
"b": "foo",
|
|
},
|
|
}
|
|
src := map[string]any{}
|
|
|
|
actual := mergeValues(dest, src)
|
|
|
|
expected := map[string]any{
|
|
"a": map[string]any{
|
|
"b": "foo",
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Errorf("merged map does not match expected:\n\nExpected: %+v\nActual: %+v", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestMergeValuesNoSrcOrDest(t *testing.T) {
|
|
dest := map[string]any{}
|
|
src := map[string]any{}
|
|
|
|
actual := mergeValues(dest, src)
|
|
|
|
expected := map[string]any{}
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Errorf("merged map does not match expected:\n\nExpected: %+v\nActual: %+v", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestLoadConfigWithParamOverride(t *testing.T) {
|
|
fs := map[string]string{"/some/config.yaml": `
|
|
services:
|
|
acmecorp:
|
|
url: https://example.com/control-plane-api/v1
|
|
|
|
discovery:
|
|
name: /example/discovery
|
|
prefix: configuration
|
|
`}
|
|
|
|
test.WithTempFS(fs, func(rootDir string) {
|
|
configFile := filepath.Join(rootDir, "some", "config.yaml")
|
|
configOverrides := []string{"services.acmecorp.credentials.bearer.token=bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm"}
|
|
|
|
configBytes, err := Load(configFile, configOverrides, nil)
|
|
if err != nil {
|
|
t.Errorf("unexpected error loading config: %s", err.Error())
|
|
}
|
|
|
|
config := map[string]any{}
|
|
err = yaml.Unmarshal(configBytes, &config)
|
|
if err != nil {
|
|
t.Errorf("unexpected error unmarshalling config")
|
|
}
|
|
|
|
expected := map[string]any{
|
|
"services": map[string]any{
|
|
"acmecorp": map[string]any{
|
|
"url": "https://example.com/control-plane-api/v1",
|
|
"credentials": map[string]any{
|
|
"bearer": map[string]any{
|
|
"token": "bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"discovery": map[string]any{
|
|
"name": "/example/discovery",
|
|
"prefix": "configuration",
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(config, expected) {
|
|
t.Errorf("config does not match expected:\n\nExpected: %+v\nActual: %+v", expected, config)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestLoadConfigWithFileOverride(t *testing.T) {
|
|
fs := map[string]string{
|
|
"/some/config.yaml": `
|
|
services:
|
|
acmecorp:
|
|
url: https://example.com/control-plane-api/v1
|
|
credentials:
|
|
bearer:
|
|
token: "XXXXXXXXXX"
|
|
|
|
discovery:
|
|
name: /example/discovery
|
|
prefix: configuration
|
|
`,
|
|
"/some/secret.txt": "bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm",
|
|
}
|
|
|
|
test.WithTempFS(fs, func(rootDir string) {
|
|
configFile := filepath.Join(rootDir, "some", "config.yaml")
|
|
secretFile := filepath.Join(rootDir, "some", "secret.txt")
|
|
overrideFiles := []string{"services.acmecorp.credentials.bearer.token=" + secretFile}
|
|
|
|
configBytes, err := Load(configFile, nil, overrideFiles)
|
|
if err != nil {
|
|
t.Errorf("unexpected error loading config: %s", err.Error())
|
|
}
|
|
|
|
config := map[string]any{}
|
|
err = yaml.Unmarshal(configBytes, &config)
|
|
if err != nil {
|
|
t.Errorf("unexpected error unmarshalling config")
|
|
}
|
|
|
|
expected := map[string]any{
|
|
"services": map[string]any{
|
|
"acmecorp": map[string]any{
|
|
"url": "https://example.com/control-plane-api/v1",
|
|
"credentials": map[string]any{
|
|
"bearer": map[string]any{
|
|
"token": "bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"discovery": map[string]any{
|
|
"name": "/example/discovery",
|
|
"prefix": "configuration",
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(config, expected) {
|
|
t.Errorf("config does not match expected:\n\nExpected: %+v\nActual: %+v", expected, config)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestLoadConfigWithParamOverrideNoConfigFile(t *testing.T) {
|
|
configOverrides := []string{
|
|
"services.acmecorp.url=https://example.com/control-plane-api/v1",
|
|
"services.acmecorp.credentials.bearer.token=bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm",
|
|
"discovery.name=/example/discovery",
|
|
"discovery.prefix=configuration",
|
|
}
|
|
|
|
configBytes, err := Load("", configOverrides, nil)
|
|
if err != nil {
|
|
t.Errorf("unexpected error loading config: %s", err.Error())
|
|
}
|
|
|
|
config := map[string]any{}
|
|
err = yaml.Unmarshal(configBytes, &config)
|
|
if err != nil {
|
|
t.Errorf("unexpected error unmarshalling config")
|
|
}
|
|
|
|
expected := map[string]any{
|
|
"services": map[string]any{
|
|
"acmecorp": map[string]any{
|
|
"url": "https://example.com/control-plane-api/v1",
|
|
"credentials": map[string]any{
|
|
"bearer": map[string]any{
|
|
"token": "bGFza2RqZmxha3NkamZsa2Fqc2Rsa2ZqYWtsc2RqZmtramRmYWxkc2tm",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"discovery": map[string]any{
|
|
"name": "/example/discovery",
|
|
"prefix": "configuration",
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(config, expected) {
|
|
t.Errorf("config does not match expected:\n\nExpected: %+v\nActual: %+v", expected, config)
|
|
}
|
|
}
|
|
|
|
func TestLoadConfigWithParamOverrideNoConfigFileWithEmptyObject(t *testing.T) {
|
|
configOverrides := []string{
|
|
"services.acmecorp.url=https://example.com/control-plane-api/v1",
|
|
"services.acmecorp.headers=null",
|
|
"services.acmecorp.credentials.s3_signing.environment_credentials=null",
|
|
"decision_logs.plugin=my_plugin",
|
|
"plugins.my_plugin=null",
|
|
}
|
|
|
|
configBytes, err := Load("", configOverrides, nil)
|
|
if err != nil {
|
|
t.Errorf("unexpected error loading config: %s", err.Error())
|
|
}
|
|
|
|
config := map[string]any{}
|
|
err = yaml.Unmarshal(configBytes, &config)
|
|
if err != nil {
|
|
t.Errorf("unexpected error unmarshalling config")
|
|
}
|
|
|
|
expected := map[string]any{
|
|
"services": map[string]any{
|
|
"acmecorp": map[string]any{
|
|
"url": "https://example.com/control-plane-api/v1",
|
|
"headers": map[string]any{},
|
|
"credentials": map[string]any{
|
|
"s3_signing": map[string]any{
|
|
"environment_credentials": map[string]any{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"decision_logs": map[string]any{
|
|
"plugin": "my_plugin",
|
|
},
|
|
"plugins": map[string]any{
|
|
"my_plugin": map[string]any{},
|
|
},
|
|
}
|
|
|
|
if !reflect.DeepEqual(config, expected) {
|
|
t.Errorf("config does not match expected:\n\nExpected: %+v\nActual: %+v", expected, config)
|
|
}
|
|
}
|