Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@ fmt:
.PHONY: tidy
tidy:
rm -fr go.sum
$(GOCMD) mod tidy -compat=1.22.0
$(GOCMD) mod tidy -compat=1.24.0
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
go.opentelemetry.io/collector/component v1.49.0
go.opentelemetry.io/collector/component/componenttest v0.143.0
go.opentelemetry.io/collector/confmap v1.49.0
go.opentelemetry.io/collector/confmap/xconfmap v0.143.0
go.opentelemetry.io/collector/consumer v1.49.0
go.opentelemetry.io/collector/consumer/xconsumer v0.143.0
go.opentelemetry.io/collector/pdata v1.49.0
Expand Down
34 changes: 22 additions & 12 deletions internal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/go-viper/mapstructure/v2"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/xconfmap"
"gopkg.in/yaml.v3"
)

Expand Down Expand Up @@ -63,13 +64,8 @@ func parseConfig[C any](id component.ID, yamlConfig string, createDefaultConfig
return parseMultipleConfigs[C](yamlConfig, deserializedConf, createDefaultConfig)
}

configMap := make(map[string]any)
for k, v := range deserializedConf.ToStringMap() {
configMap[k] = escapeDollarSigns(v)
}

defaultConfig := createDefaultConfig()
err = confmap.NewFromStringMap(configMap).Unmarshal(&defaultConfig)
err = unmarshalValidConfig(deserializedConf, defaultConfig)
if err != nil {
return nil, err
}
Expand All @@ -89,13 +85,8 @@ func parseMultipleConfigs[C any](yamlConfig string, deserializedConf *confmap.Co
return nil, err
}

subConfigMap := map[string]any{}
for k, v := range sub.ToStringMap() {
subConfigMap[k] = escapeDollarSigns(v)
}

defaultConfig := createDefaultConfig()
err = confmap.NewFromStringMap(subConfigMap).Unmarshal(&defaultConfig)
err = unmarshalValidConfig(sub, defaultConfig)
if err != nil {
return nil, err
}
Expand All @@ -106,6 +97,25 @@ func parseMultipleConfigs[C any](yamlConfig string, deserializedConf *confmap.Co
return configs, nil
}

func unmarshalValidConfig[C any](cfg *confmap.Conf, defaultConfig C) error {
subConfigMap := map[string]any{}
for k, v := range cfg.ToStringMap() {
subConfigMap[k] = escapeDollarSigns(v)
}

err := confmap.NewFromStringMap(subConfigMap).Unmarshal(&defaultConfig)
if err != nil {
return err
}

validator, ok := any(defaultConfig).(xconfmap.Validator)
if ok {
return validator.Validate()
}

return nil
}

func sortedConfigKeys(yamlData string) ([]string, error) {
var root yaml.Node
if err := yaml.Unmarshal([]byte(yamlData), &root); err != nil {
Expand Down
64 changes: 64 additions & 0 deletions internal/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package internal

import (
"errors"
"testing"

"github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor"
Expand Down Expand Up @@ -52,6 +53,54 @@ func Test_parseConfig_singleConfig(t *testing.T) {
require.NotEmpty(t, pc.MetricStatements)
}

func Test_parseConfig_configValidator(t *testing.T) {
id := component.MustNewID("test")
tests := []struct {
name string
config string
expectErr bool
}{
{
name: "valid single config",
config: "valid: true",
expectErr: false,
},
{
name: "invalid single config",
config: "valid: false",
expectErr: true,
},
{
name: "valid multiple config",
config: "test:\n valid: true\ntest/b:\n valid: true",
expectErr: false,
},
{
name: "invalid multiple config",
config: "test:\n valid: true\ntest/b:\n valid: false",
expectErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := parseConfig[mockConfig](
id,
tt.config,
func() *mockConfig {
return &mockConfig{Valid: !tt.expectErr}
},
)

if tt.expectErr {
require.ErrorIs(t, err, errInvalidMockConfig)
} else {
require.NoError(t, err)
}
})
}
}

func Test_parseConfig_multipleConfig(t *testing.T) {
config := readTestData(t, configMultiple)
allConfigs, err := parseConfig[transformprocessor.Config](
Expand Down Expand Up @@ -87,3 +136,18 @@ func Test_parseConfig_invalidConfig(t *testing.T) {
)
require.ErrorContains(t, err, "cannot be used as a Conf")
}

var (
errInvalidMockConfig = errors.New("config validation failed")
)

type mockConfig struct {
Valid bool `mapstructure:"valid"`
}

func (m *mockConfig) Validate() error {
if m.Valid {
return nil
}
return errInvalidMockConfig
}
Loading