725 lines
26 KiB
Go
725 lines
26 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package configparser
|
|
|
|
import (
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.opentelemetry.io/collector/component"
|
|
"go.opentelemetry.io/collector/config"
|
|
"go.opentelemetry.io/collector/config/confignet"
|
|
"go.opentelemetry.io/collector/internal/testcomponents"
|
|
)
|
|
|
|
func TestDecodeConfig(t *testing.T) {
|
|
factories, err := testcomponents.ExampleComponents()
|
|
assert.NoError(t, err)
|
|
|
|
// Load the config
|
|
cfg, err := loadConfigFile(t, path.Join(".", "testdata", "valid-config.yaml"), factories)
|
|
require.NoError(t, err, "Unable to load config")
|
|
|
|
// Verify extensions.
|
|
assert.Equal(t, 3, len(cfg.Extensions))
|
|
assert.Equal(t, "some string", cfg.Extensions["exampleextension/1"].(*testcomponents.ExampleExtensionCfg).ExtraSetting)
|
|
|
|
// Verify service.
|
|
assert.Equal(t, 2, len(cfg.Service.Extensions))
|
|
assert.Equal(t, "exampleextension/0", cfg.Service.Extensions[0])
|
|
assert.Equal(t, "exampleextension/1", cfg.Service.Extensions[1])
|
|
|
|
// Verify receivers
|
|
assert.Equal(t, 2, len(cfg.Receivers), "Incorrect receivers count")
|
|
|
|
assert.Equal(t,
|
|
&testcomponents.ExampleReceiver{
|
|
ReceiverSettings: config.ReceiverSettings{
|
|
TypeVal: "examplereceiver",
|
|
NameVal: "examplereceiver",
|
|
},
|
|
TCPAddr: confignet.TCPAddr{
|
|
Endpoint: "localhost:1000",
|
|
},
|
|
ExtraSetting: "some string",
|
|
},
|
|
cfg.Receivers["examplereceiver"],
|
|
"Did not load receiver config correctly")
|
|
|
|
assert.Equal(t,
|
|
&testcomponents.ExampleReceiver{
|
|
ReceiverSettings: config.ReceiverSettings{
|
|
TypeVal: "examplereceiver",
|
|
NameVal: "examplereceiver/myreceiver",
|
|
},
|
|
TCPAddr: confignet.TCPAddr{
|
|
Endpoint: "localhost:12345",
|
|
},
|
|
ExtraSetting: "some string",
|
|
},
|
|
cfg.Receivers["examplereceiver/myreceiver"],
|
|
"Did not load receiver config correctly")
|
|
|
|
// Verify exporters
|
|
assert.Equal(t, 2, len(cfg.Exporters), "Incorrect exporters count")
|
|
|
|
assert.Equal(t,
|
|
&testcomponents.ExampleExporter{
|
|
ExporterSettings: config.ExporterSettings{
|
|
NameVal: "exampleexporter",
|
|
TypeVal: "exampleexporter",
|
|
},
|
|
ExtraSetting: "some export string",
|
|
},
|
|
cfg.Exporters["exampleexporter"],
|
|
"Did not load exporter config correctly")
|
|
|
|
assert.Equal(t,
|
|
&testcomponents.ExampleExporter{
|
|
ExporterSettings: config.ExporterSettings{
|
|
NameVal: "exampleexporter/myexporter",
|
|
TypeVal: "exampleexporter",
|
|
},
|
|
ExtraSetting: "some export string 2",
|
|
},
|
|
cfg.Exporters["exampleexporter/myexporter"],
|
|
"Did not load exporter config correctly")
|
|
|
|
// Verify Processors
|
|
assert.Equal(t, 1, len(cfg.Processors), "Incorrect processors count")
|
|
|
|
assert.Equal(t,
|
|
&testcomponents.ExampleProcessorCfg{
|
|
ProcessorSettings: config.ProcessorSettings{
|
|
TypeVal: "exampleprocessor",
|
|
NameVal: "exampleprocessor",
|
|
},
|
|
ExtraSetting: "some export string",
|
|
},
|
|
cfg.Processors["exampleprocessor"],
|
|
"Did not load processor config correctly")
|
|
|
|
// Verify Pipelines
|
|
assert.Equal(t, 1, len(cfg.Service.Pipelines), "Incorrect pipelines count")
|
|
|
|
assert.Equal(t,
|
|
&config.Pipeline{
|
|
Name: "traces",
|
|
InputType: config.TracesDataType,
|
|
Receivers: []string{"examplereceiver"},
|
|
Processors: []string{"exampleprocessor"},
|
|
Exporters: []string{"exampleexporter"},
|
|
},
|
|
cfg.Service.Pipelines["traces"],
|
|
"Did not load pipeline config correctly")
|
|
}
|
|
|
|
func TestSimpleConfig(t *testing.T) {
|
|
var testCases = []struct {
|
|
name string // test case name (also file name containing config yaml)
|
|
}{
|
|
{name: "simple-config-with-no-env"},
|
|
{name: "simple-config-with-partial-env"},
|
|
{name: "simple-config-with-all-env"},
|
|
}
|
|
|
|
const extensionExtra = "some extension string"
|
|
const extensionExtraMapValue = "some extension map value"
|
|
const extensionExtraListElement = "some extension list value"
|
|
assert.NoError(t, os.Setenv("EXTENSIONS_EXAMPLEEXTENSION_EXTRA", extensionExtra))
|
|
assert.NoError(t, os.Setenv("EXTENSIONS_EXAMPLEEXTENSION_EXTRA_MAP_EXT_VALUE_1", extensionExtraMapValue+"_1"))
|
|
assert.NoError(t, os.Setenv("EXTENSIONS_EXAMPLEEXTENSION_EXTRA_MAP_EXT_VALUE_2", extensionExtraMapValue+"_2"))
|
|
assert.NoError(t, os.Setenv("EXTENSIONS_EXAMPLEEXTENSION_EXTRA_LIST_VALUE_1", extensionExtraListElement+"_1"))
|
|
assert.NoError(t, os.Setenv("EXTENSIONS_EXAMPLEEXTENSION_EXTRA_LIST_VALUE_2", extensionExtraListElement+"_2"))
|
|
|
|
const receiverExtra = "some receiver string"
|
|
const receiverExtraMapValue = "some receiver map value"
|
|
const receiverExtraListElement = "some receiver list value"
|
|
assert.NoError(t, os.Setenv("RECEIVERS_EXAMPLERECEIVER_EXTRA", receiverExtra))
|
|
assert.NoError(t, os.Setenv("RECEIVERS_EXAMPLERECEIVER_EXTRA_MAP_RECV_VALUE_1", receiverExtraMapValue+"_1"))
|
|
assert.NoError(t, os.Setenv("RECEIVERS_EXAMPLERECEIVER_EXTRA_MAP_RECV_VALUE_2", receiverExtraMapValue+"_2"))
|
|
assert.NoError(t, os.Setenv("RECEIVERS_EXAMPLERECEIVER_EXTRA_LIST_VALUE_1", receiverExtraListElement+"_1"))
|
|
assert.NoError(t, os.Setenv("RECEIVERS_EXAMPLERECEIVER_EXTRA_LIST_VALUE_2", receiverExtraListElement+"_2"))
|
|
|
|
const processorExtra = "some processor string"
|
|
const processorExtraMapValue = "some processor map value"
|
|
const processorExtraListElement = "some processor list value"
|
|
assert.NoError(t, os.Setenv("PROCESSORS_EXAMPLEPROCESSOR_EXTRA", processorExtra))
|
|
assert.NoError(t, os.Setenv("PROCESSORS_EXAMPLEPROCESSOR_EXTRA_MAP_PROC_VALUE_1", processorExtraMapValue+"_1"))
|
|
assert.NoError(t, os.Setenv("PROCESSORS_EXAMPLEPROCESSOR_EXTRA_MAP_PROC_VALUE_2", processorExtraMapValue+"_2"))
|
|
assert.NoError(t, os.Setenv("PROCESSORS_EXAMPLEPROCESSOR_EXTRA_LIST_VALUE_1", processorExtraListElement+"_1"))
|
|
assert.NoError(t, os.Setenv("PROCESSORS_EXAMPLEPROCESSOR_EXTRA_LIST_VALUE_2", processorExtraListElement+"_2"))
|
|
|
|
const exporterExtra = "some exporter string"
|
|
const exporterExtraMapValue = "some exporter map value"
|
|
const exporterExtraListElement = "some exporter list value"
|
|
assert.NoError(t, os.Setenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA_INT", "65"))
|
|
assert.NoError(t, os.Setenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA", exporterExtra))
|
|
assert.NoError(t, os.Setenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA_MAP_EXP_VALUE_1", exporterExtraMapValue+"_1"))
|
|
assert.NoError(t, os.Setenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA_MAP_EXP_VALUE_2", exporterExtraMapValue+"_2"))
|
|
assert.NoError(t, os.Setenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA_LIST_VALUE_1", exporterExtraListElement+"_1"))
|
|
assert.NoError(t, os.Setenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA_LIST_VALUE_2", exporterExtraListElement+"_2"))
|
|
|
|
defer func() {
|
|
assert.NoError(t, os.Unsetenv("EXTENSIONS_EXAMPLEEXTENSION_EXTRA"))
|
|
assert.NoError(t, os.Unsetenv("EXTENSIONS_EXAMPLEEXTENSION_EXTRA_MAP_EXT_VALUE"))
|
|
assert.NoError(t, os.Unsetenv("EXTENSIONS_EXAMPLEEXTENSION_EXTRA_LIST_VALUE_1"))
|
|
|
|
assert.NoError(t, os.Unsetenv("RECEIVERS_EXAMPLERECEIVER_EXTRA"))
|
|
assert.NoError(t, os.Unsetenv("RECEIVERS_EXAMPLERECEIVER_EXTRA_MAP_RECV_VALUE"))
|
|
assert.NoError(t, os.Unsetenv("RECEIVERS_EXAMPLERECEIVER_EXTRA_LIST_VALUE_1"))
|
|
|
|
assert.NoError(t, os.Unsetenv("PROCESSORS_EXAMPLEPROCESSOR_EXTRA"))
|
|
assert.NoError(t, os.Unsetenv("PROCESSORS_EXAMPLEPROCESSOR_EXTRA_MAP_PROC_VALUE"))
|
|
assert.NoError(t, os.Unsetenv("PROCESSORS_EXAMPLEPROCESSOR_EXTRA_LIST_VALUE_1"))
|
|
|
|
assert.NoError(t, os.Unsetenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA_INT"))
|
|
assert.NoError(t, os.Unsetenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA"))
|
|
assert.NoError(t, os.Unsetenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA_MAP_EXP_VALUE"))
|
|
assert.NoError(t, os.Unsetenv("EXPORTERS_EXAMPLEEXPORTER_EXTRA_LIST_VALUE_1"))
|
|
}()
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
factories, err := testcomponents.ExampleComponents()
|
|
assert.NoError(t, err)
|
|
|
|
// Load the config
|
|
cfg, err := loadConfigFile(t, path.Join(".", "testdata", test.name+".yaml"), factories)
|
|
require.NoError(t, err, "Unable to load config")
|
|
|
|
// Verify extensions.
|
|
assert.Equalf(t, 1, len(cfg.Extensions), "TEST[%s]", test.name)
|
|
assert.Equalf(t,
|
|
&testcomponents.ExampleExtensionCfg{
|
|
ExtensionSettings: config.ExtensionSettings{
|
|
TypeVal: "exampleextension",
|
|
NameVal: "exampleextension",
|
|
},
|
|
ExtraSetting: extensionExtra,
|
|
ExtraMapSetting: map[string]string{"ext-1": extensionExtraMapValue + "_1", "ext-2": extensionExtraMapValue + "_2"},
|
|
ExtraListSetting: []string{extensionExtraListElement + "_1", extensionExtraListElement + "_2"},
|
|
},
|
|
cfg.Extensions["exampleextension"],
|
|
"TEST[%s] Did not load extension config correctly", test.name)
|
|
|
|
// Verify service.
|
|
assert.Equalf(t, 1, len(cfg.Service.Extensions), "TEST[%s]", test.name)
|
|
assert.Equalf(t, "exampleextension", cfg.Service.Extensions[0], "TEST[%s]", test.name)
|
|
|
|
// Verify receivers
|
|
assert.Equalf(t, 1, len(cfg.Receivers), "TEST[%s]", test.name)
|
|
|
|
assert.Equalf(t,
|
|
&testcomponents.ExampleReceiver{
|
|
ReceiverSettings: config.ReceiverSettings{
|
|
TypeVal: "examplereceiver",
|
|
NameVal: "examplereceiver",
|
|
},
|
|
TCPAddr: confignet.TCPAddr{
|
|
Endpoint: "localhost:1234",
|
|
},
|
|
ExtraSetting: receiverExtra,
|
|
ExtraMapSetting: map[string]string{"recv.1": receiverExtraMapValue + "_1", "recv.2": receiverExtraMapValue + "_2"},
|
|
ExtraListSetting: []string{receiverExtraListElement + "_1", receiverExtraListElement + "_2"},
|
|
},
|
|
cfg.Receivers["examplereceiver"],
|
|
"TEST[%s] Did not load receiver config correctly", test.name)
|
|
|
|
// Verify exporters
|
|
assert.Equalf(t, 1, len(cfg.Exporters), "TEST[%s]", test.name)
|
|
|
|
assert.Equalf(t,
|
|
&testcomponents.ExampleExporter{
|
|
ExporterSettings: config.ExporterSettings{
|
|
NameVal: "exampleexporter",
|
|
TypeVal: "exampleexporter",
|
|
},
|
|
ExtraInt: 65,
|
|
ExtraSetting: exporterExtra,
|
|
ExtraMapSetting: map[string]string{"exp_1": exporterExtraMapValue + "_1", "exp_2": exporterExtraMapValue + "_2"},
|
|
ExtraListSetting: []string{exporterExtraListElement + "_1", exporterExtraListElement + "_2"},
|
|
},
|
|
cfg.Exporters["exampleexporter"],
|
|
"TEST[%s] Did not load exporter config correctly", test.name)
|
|
|
|
// Verify Processors
|
|
assert.Equalf(t, 1, len(cfg.Processors), "TEST[%s]", test.name)
|
|
|
|
assert.Equalf(t,
|
|
&testcomponents.ExampleProcessorCfg{
|
|
ProcessorSettings: config.ProcessorSettings{
|
|
TypeVal: "exampleprocessor",
|
|
NameVal: "exampleprocessor",
|
|
},
|
|
ExtraSetting: processorExtra,
|
|
ExtraMapSetting: map[string]string{"proc_1": processorExtraMapValue + "_1", "proc_2": processorExtraMapValue + "_2"},
|
|
ExtraListSetting: []string{processorExtraListElement + "_1", processorExtraListElement + "_2"},
|
|
},
|
|
cfg.Processors["exampleprocessor"],
|
|
"TEST[%s] Did not load processor config correctly", test.name)
|
|
|
|
// Verify Pipelines
|
|
assert.Equalf(t, 1, len(cfg.Service.Pipelines), "TEST[%s]", test.name)
|
|
|
|
assert.Equalf(t,
|
|
&config.Pipeline{
|
|
Name: "traces",
|
|
InputType: config.TracesDataType,
|
|
Receivers: []string{"examplereceiver"},
|
|
Processors: []string{"exampleprocessor"},
|
|
Exporters: []string{"exampleexporter"},
|
|
},
|
|
cfg.Service.Pipelines["traces"],
|
|
"TEST[%s] Did not load pipeline config correctly", test.name)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEscapedEnvVars(t *testing.T) {
|
|
const receiverExtraMapValue = "some receiver map value"
|
|
assert.NoError(t, os.Setenv("RECEIVERS_EXAMPLERECEIVER_EXTRA_MAP_RECV_VALUE_2", receiverExtraMapValue))
|
|
defer func() {
|
|
assert.NoError(t, os.Unsetenv("RECEIVERS_EXAMPLERECEIVER_EXTRA_MAP_RECV_VALUE_2"))
|
|
}()
|
|
|
|
factories, err := testcomponents.ExampleComponents()
|
|
assert.NoError(t, err)
|
|
|
|
// Load the config
|
|
cfg, err := loadConfigFile(t, path.Join(".", "testdata", "simple-config-with-escaped-env.yaml"), factories)
|
|
require.NoError(t, err, "Unable to load config")
|
|
|
|
// Verify extensions.
|
|
assert.Equal(t, 1, len(cfg.Extensions))
|
|
assert.Equal(t,
|
|
&testcomponents.ExampleExtensionCfg{
|
|
ExtensionSettings: config.ExtensionSettings{
|
|
TypeVal: "exampleextension",
|
|
NameVal: "exampleextension",
|
|
},
|
|
ExtraSetting: "${EXTENSIONS_EXAMPLEEXTENSION_EXTRA}",
|
|
ExtraMapSetting: map[string]string{"ext-1": "${EXTENSIONS_EXAMPLEEXTENSION_EXTRA_MAP_EXT_VALUE_1}", "ext-2": "${EXTENSIONS_EXAMPLEEXTENSION_EXTRA_MAP_EXT_VALUE_2}"},
|
|
ExtraListSetting: []string{"${EXTENSIONS_EXAMPLEEXTENSION_EXTRA_LIST_VALUE_1}", "${EXTENSIONS_EXAMPLEEXTENSION_EXTRA_LIST_VALUE_2}"},
|
|
},
|
|
cfg.Extensions["exampleextension"],
|
|
"Did not load extension config correctly")
|
|
|
|
// Verify service.
|
|
assert.Equal(t, 1, len(cfg.Service.Extensions))
|
|
assert.Equal(t, "exampleextension", cfg.Service.Extensions[0])
|
|
|
|
// Verify receivers
|
|
assert.Equal(t, 1, len(cfg.Receivers))
|
|
|
|
assert.Equal(t,
|
|
&testcomponents.ExampleReceiver{
|
|
ReceiverSettings: config.ReceiverSettings{
|
|
TypeVal: "examplereceiver",
|
|
NameVal: "examplereceiver",
|
|
},
|
|
TCPAddr: confignet.TCPAddr{
|
|
Endpoint: "localhost:1234",
|
|
},
|
|
ExtraSetting: "$RECEIVERS_EXAMPLERECEIVER_EXTRA",
|
|
ExtraMapSetting: map[string]string{
|
|
// $$ -> escaped $
|
|
"recv.1": "$RECEIVERS_EXAMPLERECEIVER_EXTRA_MAP_RECV_VALUE_1",
|
|
// $$$ -> escaped $ + substituted env var
|
|
"recv.2": "$" + receiverExtraMapValue,
|
|
// $$$$ -> two escaped $
|
|
"recv.3": "$$RECEIVERS_EXAMPLERECEIVER_EXTRA_MAP_RECV_VALUE_3",
|
|
// escaped $ in the middle
|
|
"recv.4": "some${RECEIVERS_EXAMPLERECEIVER_EXTRA_MAP_RECV_VALUE_4}text",
|
|
// $$$$ -> two escaped $
|
|
"recv.5": "${ONE}${TWO}",
|
|
// trailing escaped $
|
|
"recv.6": "text$",
|
|
// escaped $ alone
|
|
"recv.7": "$",
|
|
},
|
|
ExtraListSetting: []string{"$RECEIVERS_EXAMPLERECEIVER_EXTRA_LIST_VALUE_1", "$RECEIVERS_EXAMPLERECEIVER_EXTRA_LIST_VALUE_2"},
|
|
},
|
|
cfg.Receivers["examplereceiver"],
|
|
"Did not load receiver config correctly")
|
|
|
|
// Verify exporters
|
|
assert.Equal(t, 1, len(cfg.Exporters))
|
|
|
|
assert.Equal(t,
|
|
&testcomponents.ExampleExporter{
|
|
ExporterSettings: config.ExporterSettings{
|
|
NameVal: "exampleexporter",
|
|
TypeVal: "exampleexporter",
|
|
},
|
|
ExtraSetting: "${EXPORTERS_EXAMPLEEXPORTER_EXTRA}",
|
|
ExtraMapSetting: map[string]string{"exp_1": "${EXPORTERS_EXAMPLEEXPORTER_EXTRA_MAP_EXP_VALUE_1}", "exp_2": "${EXPORTERS_EXAMPLEEXPORTER_EXTRA_MAP_EXP_VALUE_2}"},
|
|
ExtraListSetting: []string{"${EXPORTERS_EXAMPLEEXPORTER_EXTRA_LIST_VALUE_1}", "${EXPORTERS_EXAMPLEEXPORTER_EXTRA_LIST_VALUE_2}"},
|
|
},
|
|
cfg.Exporters["exampleexporter"],
|
|
"Did not load exporter config correctly")
|
|
|
|
// Verify Processors
|
|
assert.Equal(t, 1, len(cfg.Processors))
|
|
|
|
assert.Equal(t,
|
|
&testcomponents.ExampleProcessorCfg{
|
|
ProcessorSettings: config.ProcessorSettings{
|
|
TypeVal: "exampleprocessor",
|
|
NameVal: "exampleprocessor",
|
|
},
|
|
ExtraSetting: "$PROCESSORS_EXAMPLEPROCESSOR_EXTRA",
|
|
ExtraMapSetting: map[string]string{"proc_1": "$PROCESSORS_EXAMPLEPROCESSOR_EXTRA_MAP_PROC_VALUE_1", "proc_2": "$PROCESSORS_EXAMPLEPROCESSOR_EXTRA_MAP_PROC_VALUE_2"},
|
|
ExtraListSetting: []string{"$PROCESSORS_EXAMPLEPROCESSOR_EXTRA_LIST_VALUE_1", "$PROCESSORS_EXAMPLEPROCESSOR_EXTRA_LIST_VALUE_2"},
|
|
},
|
|
cfg.Processors["exampleprocessor"],
|
|
"Did not load processor config correctly")
|
|
|
|
// Verify Pipelines
|
|
assert.Equal(t, 1, len(cfg.Service.Pipelines))
|
|
|
|
assert.Equal(t,
|
|
&config.Pipeline{
|
|
Name: "traces",
|
|
InputType: config.TracesDataType,
|
|
Receivers: []string{"examplereceiver"},
|
|
Processors: []string{"exampleprocessor"},
|
|
Exporters: []string{"exampleexporter"},
|
|
},
|
|
cfg.Service.Pipelines["traces"],
|
|
"Did not load pipeline config correctly")
|
|
}
|
|
|
|
func TestDecodeConfig_Invalid(t *testing.T) {
|
|
|
|
var testCases = []struct {
|
|
name string // test case name (also file name containing config yaml)
|
|
expected configErrorCode // expected error (if nil any error is acceptable)
|
|
expectedMessage string // string that the error must contain
|
|
}{
|
|
{name: "invalid-extension-type", expected: errInvalidTypeAndNameKey},
|
|
{name: "invalid-receiver-type", expected: errInvalidTypeAndNameKey},
|
|
{name: "invalid-exporter-type", expected: errInvalidTypeAndNameKey},
|
|
{name: "invalid-processor-type", expected: errInvalidTypeAndNameKey},
|
|
{name: "invalid-pipeline-type", expected: errInvalidTypeAndNameKey},
|
|
|
|
{name: "invalid-extension-name-after-slash", expected: errInvalidTypeAndNameKey},
|
|
{name: "invalid-receiver-name-after-slash", expected: errInvalidTypeAndNameKey},
|
|
{name: "invalid-exporter-name-after-slash", expected: errInvalidTypeAndNameKey},
|
|
{name: "invalid-processor-name-after-slash", expected: errInvalidTypeAndNameKey},
|
|
{name: "invalid-pipeline-name-after-slash", expected: errInvalidTypeAndNameKey},
|
|
|
|
{name: "unknown-extension-type", expected: errUnknownType, expectedMessage: "extensions"},
|
|
{name: "unknown-receiver-type", expected: errUnknownType, expectedMessage: "receivers"},
|
|
{name: "unknown-exporter-type", expected: errUnknownType, expectedMessage: "exporters"},
|
|
{name: "unknown-processor-type", expected: errUnknownType, expectedMessage: "processors"},
|
|
{name: "unknown-pipeline-type", expected: errUnknownType, expectedMessage: "pipelines"},
|
|
|
|
{name: "duplicate-extension", expected: errDuplicateName, expectedMessage: "extensions"},
|
|
{name: "duplicate-receiver", expected: errDuplicateName, expectedMessage: "receivers"},
|
|
{name: "duplicate-exporter", expected: errDuplicateName, expectedMessage: "exporters"},
|
|
{name: "duplicate-processor", expected: errDuplicateName, expectedMessage: "processors"},
|
|
{name: "duplicate-pipeline", expected: errDuplicateName, expectedMessage: "pipelines"},
|
|
|
|
{name: "invalid-top-level-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "top level"},
|
|
{name: "invalid-extension-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "extensions"},
|
|
{name: "invalid-receiver-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "receivers"},
|
|
{name: "invalid-processor-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "processors"},
|
|
{name: "invalid-exporter-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "exporters"},
|
|
{name: "invalid-service-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "service"},
|
|
{name: "invalid-service-extensions-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "service"},
|
|
{name: "invalid-pipeline-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "pipelines"},
|
|
{name: "invalid-sequence-value", expected: errUnmarshalTopLevelStructureError, expectedMessage: "pipelines"},
|
|
|
|
{name: "invalid-extension-sub-config", expected: errUnmarshalTopLevelStructureError},
|
|
{name: "invalid-exporter-sub-config", expected: errUnmarshalTopLevelStructureError},
|
|
{name: "invalid-processor-sub-config", expected: errUnmarshalTopLevelStructureError},
|
|
{name: "invalid-receiver-sub-config", expected: errUnmarshalTopLevelStructureError},
|
|
{name: "invalid-pipeline-sub-config", expected: errUnmarshalTopLevelStructureError},
|
|
}
|
|
|
|
factories, err := testcomponents.ExampleComponents()
|
|
assert.NoError(t, err)
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
_, err := loadConfigFile(t, path.Join(".", "testdata", test.name+".yaml"), factories)
|
|
require.Error(t, err)
|
|
if test.expected != 0 {
|
|
cfgErr, ok := err.(*configError)
|
|
if !ok {
|
|
t.Errorf("expected config error code %v but got a different error '%v'", test.expected, err)
|
|
} else {
|
|
assert.Equal(t, test.expected, cfgErr.code, err)
|
|
if test.expectedMessage != "" {
|
|
assert.Contains(t, cfgErr.Error(), test.expectedMessage)
|
|
}
|
|
assert.NotEmpty(t, cfgErr.Error(), "returned config error %v with empty error message", cfgErr.code)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLoadEmpty(t *testing.T) {
|
|
factories, err := testcomponents.ExampleComponents()
|
|
assert.NoError(t, err)
|
|
|
|
_, err = loadConfigFile(t, path.Join(".", "testdata", "empty-config.yaml"), factories)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestLoadEmptyAllSections(t *testing.T) {
|
|
factories, err := testcomponents.ExampleComponents()
|
|
assert.NoError(t, err)
|
|
|
|
_, err = loadConfigFile(t, path.Join(".", "testdata", "empty-all-sections.yaml"), factories)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func loadConfigFile(t *testing.T, fileName string, factories component.Factories) (*config.Config, error) {
|
|
v, err := config.NewParserFromFile(fileName)
|
|
require.NoError(t, err)
|
|
|
|
// Load the config from viper using the given factories.
|
|
return Load(v, factories)
|
|
}
|
|
|
|
type nestedConfig struct {
|
|
NestedStringValue string
|
|
NestedIntValue int
|
|
}
|
|
|
|
type testConfig struct {
|
|
config.ExporterSettings
|
|
|
|
NestedConfigPtr *nestedConfig
|
|
NestedConfigValue nestedConfig
|
|
StringValue string
|
|
StringPtrValue *string
|
|
IntValue int
|
|
}
|
|
|
|
func TestExpandEnvLoadedConfig(t *testing.T) {
|
|
assert.NoError(t, os.Setenv("NESTED_VALUE", "replaced_nested_value"))
|
|
assert.NoError(t, os.Setenv("VALUE", "replaced_value"))
|
|
assert.NoError(t, os.Setenv("PTR_VALUE", "replaced_ptr_value"))
|
|
|
|
defer func() {
|
|
assert.NoError(t, os.Unsetenv("NESTED_VALUE"))
|
|
assert.NoError(t, os.Unsetenv("VALUE"))
|
|
assert.NoError(t, os.Unsetenv("PTR_VALUE"))
|
|
}()
|
|
|
|
testString := "$PTR_VALUE"
|
|
|
|
cfg := &testConfig{
|
|
ExporterSettings: config.ExporterSettings{
|
|
TypeVal: config.Type("test"),
|
|
NameVal: "test",
|
|
},
|
|
NestedConfigPtr: &nestedConfig{
|
|
NestedStringValue: "$NESTED_VALUE",
|
|
NestedIntValue: 1,
|
|
},
|
|
NestedConfigValue: nestedConfig{
|
|
NestedStringValue: "$NESTED_VALUE",
|
|
NestedIntValue: 2,
|
|
},
|
|
StringValue: "$VALUE",
|
|
StringPtrValue: &testString,
|
|
IntValue: 3,
|
|
}
|
|
|
|
expandEnvLoadedConfig(cfg)
|
|
|
|
replacedTestString := "replaced_ptr_value"
|
|
|
|
assert.Equal(t, &testConfig{
|
|
ExporterSettings: config.ExporterSettings{
|
|
TypeVal: config.Type("test"),
|
|
NameVal: "test",
|
|
},
|
|
NestedConfigPtr: &nestedConfig{
|
|
NestedStringValue: "replaced_nested_value",
|
|
NestedIntValue: 1,
|
|
},
|
|
NestedConfigValue: nestedConfig{
|
|
NestedStringValue: "replaced_nested_value",
|
|
NestedIntValue: 2,
|
|
},
|
|
StringValue: "replaced_value",
|
|
StringPtrValue: &replacedTestString,
|
|
IntValue: 3,
|
|
}, cfg)
|
|
}
|
|
|
|
func TestExpandEnvLoadedConfigEscapedEnv(t *testing.T) {
|
|
assert.NoError(t, os.Setenv("NESTED_VALUE", "replaced_nested_value"))
|
|
assert.NoError(t, os.Setenv("ESCAPED_VALUE", "replaced_escaped_value"))
|
|
assert.NoError(t, os.Setenv("ESCAPED_PTR_VALUE", "replaced_escaped_pointer_value"))
|
|
|
|
defer func() {
|
|
assert.NoError(t, os.Unsetenv("NESTED_VALUE"))
|
|
assert.NoError(t, os.Unsetenv("ESCAPED_VALUE"))
|
|
assert.NoError(t, os.Unsetenv("ESCAPED_PTR_VALUE"))
|
|
}()
|
|
|
|
testString := "$$ESCAPED_PTR_VALUE"
|
|
|
|
cfg := &testConfig{
|
|
ExporterSettings: config.ExporterSettings{
|
|
TypeVal: config.Type("test"),
|
|
NameVal: "test",
|
|
},
|
|
NestedConfigPtr: &nestedConfig{
|
|
NestedStringValue: "$NESTED_VALUE",
|
|
NestedIntValue: 1,
|
|
},
|
|
NestedConfigValue: nestedConfig{
|
|
NestedStringValue: "$NESTED_VALUE",
|
|
NestedIntValue: 2,
|
|
},
|
|
StringValue: "$$ESCAPED_VALUE",
|
|
StringPtrValue: &testString,
|
|
IntValue: 3,
|
|
}
|
|
|
|
expandEnvLoadedConfig(cfg)
|
|
|
|
replacedTestString := "$ESCAPED_PTR_VALUE"
|
|
|
|
assert.Equal(t, &testConfig{
|
|
ExporterSettings: config.ExporterSettings{
|
|
TypeVal: config.Type("test"),
|
|
NameVal: "test",
|
|
},
|
|
NestedConfigPtr: &nestedConfig{
|
|
NestedStringValue: "replaced_nested_value",
|
|
NestedIntValue: 1,
|
|
},
|
|
NestedConfigValue: nestedConfig{
|
|
NestedStringValue: "replaced_nested_value",
|
|
NestedIntValue: 2,
|
|
},
|
|
StringValue: "$ESCAPED_VALUE",
|
|
StringPtrValue: &replacedTestString,
|
|
IntValue: 3,
|
|
}, cfg)
|
|
}
|
|
|
|
func TestExpandEnvLoadedConfigMissingEnv(t *testing.T) {
|
|
assert.NoError(t, os.Setenv("NESTED_VALUE", "replaced_nested_value"))
|
|
|
|
defer func() {
|
|
assert.NoError(t, os.Unsetenv("NESTED_VALUE"))
|
|
}()
|
|
|
|
testString := "$PTR_VALUE"
|
|
|
|
cfg := &testConfig{
|
|
ExporterSettings: config.ExporterSettings{
|
|
TypeVal: config.Type("test"),
|
|
NameVal: "test",
|
|
},
|
|
NestedConfigPtr: &nestedConfig{
|
|
NestedStringValue: "$NESTED_VALUE",
|
|
NestedIntValue: 1,
|
|
},
|
|
NestedConfigValue: nestedConfig{
|
|
NestedStringValue: "$NESTED_VALUE",
|
|
NestedIntValue: 2,
|
|
},
|
|
StringValue: "$VALUE",
|
|
StringPtrValue: &testString,
|
|
IntValue: 3,
|
|
}
|
|
|
|
expandEnvLoadedConfig(cfg)
|
|
|
|
replacedTestString := ""
|
|
|
|
assert.Equal(t, &testConfig{
|
|
ExporterSettings: config.ExporterSettings{
|
|
TypeVal: config.Type("test"),
|
|
NameVal: "test",
|
|
},
|
|
NestedConfigPtr: &nestedConfig{
|
|
NestedStringValue: "replaced_nested_value",
|
|
NestedIntValue: 1,
|
|
},
|
|
NestedConfigValue: nestedConfig{
|
|
NestedStringValue: "replaced_nested_value",
|
|
NestedIntValue: 2,
|
|
},
|
|
StringValue: "",
|
|
StringPtrValue: &replacedTestString,
|
|
IntValue: 3,
|
|
}, cfg)
|
|
}
|
|
|
|
func TestExpandEnvLoadedConfigNil(t *testing.T) {
|
|
var cfg *testConfig
|
|
|
|
// This should safely do nothing
|
|
expandEnvLoadedConfig(cfg)
|
|
|
|
assert.Equal(t, (*testConfig)(nil), cfg)
|
|
}
|
|
|
|
func TestExpandEnvLoadedConfigNoPointer(t *testing.T) {
|
|
assert.NoError(t, os.Setenv("VALUE", "replaced_value"))
|
|
|
|
cfg := testConfig{
|
|
StringValue: "$VALUE",
|
|
}
|
|
|
|
// This should do nothing as cfg is not a pointer
|
|
expandEnvLoadedConfig(cfg)
|
|
|
|
assert.Equal(t, testConfig{StringValue: "$VALUE"}, cfg)
|
|
}
|
|
|
|
type testUnexportedConfig struct {
|
|
config.ExporterSettings
|
|
|
|
unexportedStringValue string
|
|
ExportedStringValue string
|
|
}
|
|
|
|
func TestExpandEnvLoadedConfigUnexportedField(t *testing.T) {
|
|
assert.NoError(t, os.Setenv("VALUE", "replaced_value"))
|
|
|
|
defer func() {
|
|
assert.NoError(t, os.Unsetenv("VALUE"))
|
|
}()
|
|
|
|
cfg := &testUnexportedConfig{
|
|
unexportedStringValue: "$VALUE",
|
|
ExportedStringValue: "$VALUE",
|
|
}
|
|
|
|
expandEnvLoadedConfig(cfg)
|
|
|
|
assert.Equal(t, &testUnexportedConfig{
|
|
unexportedStringValue: "$VALUE",
|
|
ExportedStringValue: "replaced_value",
|
|
}, cfg)
|
|
}
|