diff --git a/component/component.go b/component/component.go index c3541102802..7b72757613e 100644 --- a/component/component.go +++ b/component/component.go @@ -17,6 +17,8 @@ package component import ( "context" + "github.com/spf13/viper" + "go.opentelemetry.io/collector/config" ) @@ -76,3 +78,23 @@ type Factory interface { // Type gets the type of the component created by this factory. Type() config.Type } + +// DeprecatedUnmarshaler interface is a deprecated optional interface that if implemented by a Factory, +// the configuration loading system will use to unmarshal the config. +// Use config.Unmarshal instead. +type DeprecatedUnmarshaler interface { + // Unmarshal is a function that un-marshals a viper data into a config struct in a custom way. + // componentViperSection *viper.Viper + // The config for this specific component. May be nil or empty if no config available. + // intoCfg interface{} + // An empty interface wrapping a pointer to the config struct to unmarshal into. + Unmarshal(componentViperSection *viper.Viper, intoCfg interface{}) error +} + +// CustomUnmarshaler is a function that un-marshals a viper data into a config struct +// in a custom way. +// componentViperSection *viper.Viper +// The config for this specific component. May be nil or empty if no config available. +// intoCfg interface{} +// An empty interface wrapping a pointer to the config struct to unmarshal into. +type CustomUnmarshaler func(componentViperSection *viper.Viper, intoCfg interface{}) error diff --git a/config/configparser/config.go b/config/configparser/config.go index d847e2a8a19..f07dfcacec2 100644 --- a/config/configparser/config.go +++ b/config/configparser/config.go @@ -245,7 +245,8 @@ func loadExtensions(exts map[string]interface{}, factories map[config.Type]compo // Now that the default config struct is created we can Unmarshal into it // and it will apply user-defined config on top of the default. - if err := unmarshal(componentConfig, extensionCfg); err != nil { + unm := unmarshaler(factory) + if err := unm(componentConfig, extensionCfg); err != nil { return nil, errorUnmarshalError(extensionsKeyName, fullName, err) } @@ -280,7 +281,8 @@ func LoadReceiver(componentConfig *config.Parser, fullName string, factory compo // Now that the default config struct is created we can Unmarshal into it // and it will apply user-defined config on top of the default. - if err := unmarshal(componentConfig, receiverCfg); err != nil { + unm := unmarshaler(factory) + if err := unm(componentConfig, receiverCfg); err != nil { return nil, errorUnmarshalError(receiversKeyName, fullName, err) } @@ -352,7 +354,8 @@ func loadExporters(exps map[string]interface{}, factories map[config.Type]compon // Now that the default config struct is created we can Unmarshal into it // and it will apply user-defined config on top of the default. - if err := unmarshal(componentConfig, exporterCfg); err != nil { + unm := unmarshaler(factory) + if err := unm(componentConfig, exporterCfg); err != nil { return nil, errorUnmarshalError(exportersKeyName, fullName, err) } @@ -394,7 +397,8 @@ func loadProcessors(procs map[string]interface{}, factories map[config.Type]comp // Now that the default config struct is created we can Unmarshal into it // and it will apply user-defined config on top of the default. - if err := unmarshal(componentConfig, processorCfg); err != nil { + unm := unmarshaler(factory) + if err := unm(componentConfig, processorCfg); err != nil { return nil, errorUnmarshalError(processorsKeyName, fullName, err) } @@ -536,3 +540,13 @@ func unmarshal(componentSection *config.Parser, intoCfg interface{}) error { return componentSection.UnmarshalExact(intoCfg) } + +// unmarshaler returns an unmarshaling function. It should be removed when deprecatedUnmarshaler is removed. +func unmarshaler(factory component.Factory) func(componentViperSection *config.Parser, intoCfg interface{}) error { + if fu, ok := factory.(component.DeprecatedUnmarshaler); ok { + return func(componentParser *config.Parser, intoCfg interface{}) error { + return fu.Unmarshal(componentParser.Viper(), intoCfg) + } + } + return unmarshal +} diff --git a/exporter/exporterhelper/factory.go b/exporter/exporterhelper/factory.go index 84b23872d6e..aa2798dbd13 100644 --- a/exporter/exporterhelper/factory.go +++ b/exporter/exporterhelper/factory.go @@ -17,6 +17,8 @@ package exporterhelper import ( "context" + "github.com/spf13/viper" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config" "go.opentelemetry.io/collector/config/configerror" @@ -39,6 +41,7 @@ type CreateLogsExporter func(context.Context, component.ExporterCreateParams, co type factory struct { cfgType config.Type + customUnmarshaler component.CustomUnmarshaler createDefaultConfig CreateDefaultConfig createTracesExporter CreateTracesExporter createMetricsExporter CreateMetricsExporter @@ -66,6 +69,13 @@ func WithLogs(createLogsExporter CreateLogsExporter) FactoryOption { } } +// WithCustomUnmarshaler implements component.DeprecatedUnmarshaler. +func WithCustomUnmarshaler(customUnmarshaler component.CustomUnmarshaler) FactoryOption { + return func(o *factory) { + o.customUnmarshaler = customUnmarshaler + } +} + // NewFactory returns a component.ExporterFactory. func NewFactory( cfgType config.Type, @@ -78,7 +88,13 @@ func NewFactory( for _, opt := range options { opt(f) } - return f + var ret component.ExporterFactory + if f.customUnmarshaler != nil { + ret = &factoryWithUnmarshaler{f} + } else { + ret = f + } + return ret } // Type gets the type of the Exporter config created by this factory. @@ -124,3 +140,14 @@ func (f *factory) CreateLogsExporter( } return nil, configerror.ErrDataTypeIsNotSupported } + +var _ component.DeprecatedUnmarshaler = (*factoryWithUnmarshaler)(nil) + +type factoryWithUnmarshaler struct { + *factory +} + +// Unmarshal un-marshals the config using the provided custom unmarshaler. +func (f *factoryWithUnmarshaler) Unmarshal(componentViperSection *viper.Viper, intoCfg interface{}) error { + return f.customUnmarshaler(componentViperSection, intoCfg) +} diff --git a/exporter/exporterhelper/factory_test.go b/exporter/exporterhelper/factory_test.go index 175c0e28bc7..fb03c2b4a01 100644 --- a/exporter/exporterhelper/factory_test.go +++ b/exporter/exporterhelper/factory_test.go @@ -16,8 +16,10 @@ package exporterhelper import ( "context" + "errors" "testing" + "github.com/spf13/viper" "github.com/stretchr/testify/assert" "go.uber.org/zap" @@ -51,6 +53,8 @@ func TestNewFactory(t *testing.T) { defaultConfig) assert.EqualValues(t, typeStr, factory.Type()) assert.EqualValues(t, defaultCfg, factory.CreateDefaultConfig()) + _, ok := factory.(component.DeprecatedUnmarshaler) + assert.False(t, ok) _, err := factory.CreateTracesExporter(context.Background(), component.ExporterCreateParams{Logger: zap.NewNop()}, defaultCfg) assert.Equal(t, configerror.ErrDataTypeIsNotSupported, err) _, err = factory.CreateMetricsExporter(context.Background(), component.ExporterCreateParams{Logger: zap.NewNop()}, defaultCfg) @@ -65,10 +69,15 @@ func TestNewFactory_WithConstructors(t *testing.T) { defaultConfig, WithTraces(createTraceExporter), WithMetrics(createMetricsExporter), - WithLogs(createLogsExporter)) + WithLogs(createLogsExporter), + WithCustomUnmarshaler(customUnmarshaler)) assert.EqualValues(t, typeStr, factory.Type()) assert.EqualValues(t, defaultCfg, factory.CreateDefaultConfig()) + fu, ok := factory.(component.DeprecatedUnmarshaler) + assert.True(t, ok) + assert.Equal(t, errors.New("my error"), fu.Unmarshal(nil, nil)) + te, err := factory.CreateTracesExporter(context.Background(), component.ExporterCreateParams{Logger: zap.NewNop()}, defaultCfg) assert.NoError(t, err) assert.Same(t, nopTracesExporter, te) @@ -97,3 +106,7 @@ func createMetricsExporter(context.Context, component.ExporterCreateParams, conf func createLogsExporter(context.Context, component.ExporterCreateParams, config.Exporter) (component.LogsExporter, error) { return nopLogsExporter, nil } + +func customUnmarshaler(*viper.Viper, interface{}) error { + return errors.New("my error") +} diff --git a/extension/extensionhelper/factory.go b/extension/extensionhelper/factory.go index b85c79a9816..2a02244ee14 100644 --- a/extension/extensionhelper/factory.go +++ b/extension/extensionhelper/factory.go @@ -17,6 +17,8 @@ package extensionhelper import ( "context" + "github.com/spf13/viper" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config" ) @@ -32,10 +34,18 @@ type CreateServiceExtension func(context.Context, component.ExtensionCreateParam type factory struct { cfgType config.Type + customUnmarshaler component.CustomUnmarshaler createDefaultConfig CreateDefaultConfig createServiceExtension CreateServiceExtension } +// WithCustomUnmarshaler implements component.DeprecatedUnmarshaler. +func WithCustomUnmarshaler(customUnmarshaler component.CustomUnmarshaler) FactoryOption { + return func(o *factory) { + o.customUnmarshaler = customUnmarshaler + } +} + // NewFactory returns a component.ExtensionFactory. func NewFactory( cfgType config.Type, @@ -50,7 +60,13 @@ func NewFactory( for _, opt := range options { opt(f) } - return f + var ret component.ExtensionFactory + if f.customUnmarshaler != nil { + ret = &factoryWithUnmarshaler{f} + } else { + ret = f + } + return ret } // Type gets the type of the Extension config created by this factory. @@ -70,3 +86,14 @@ func (f *factory) CreateExtension( cfg config.Extension) (component.Extension, error) { return f.createServiceExtension(ctx, params, cfg) } + +var _ component.DeprecatedUnmarshaler = (*factoryWithUnmarshaler)(nil) + +type factoryWithUnmarshaler struct { + *factory +} + +// Unmarshal un-marshals the config using the provided custom unmarshaler. +func (f *factoryWithUnmarshaler) Unmarshal(componentViperSection *viper.Viper, intoCfg interface{}) error { + return f.customUnmarshaler(componentViperSection, intoCfg) +} diff --git a/extension/extensionhelper/factory_test.go b/extension/extensionhelper/factory_test.go index dec42bfc042..b9082f06853 100644 --- a/extension/extensionhelper/factory_test.go +++ b/extension/extensionhelper/factory_test.go @@ -16,8 +16,10 @@ package extensionhelper import ( "context" + "errors" "testing" + "github.com/spf13/viper" "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/component" @@ -46,6 +48,24 @@ func TestNewFactory(t *testing.T) { assert.Same(t, nopExtensionInstance, ext) } +func TestNewFactory_WithConstructors(t *testing.T) { + factory := NewFactory( + typeStr, + defaultConfig, + createExtension, + WithCustomUnmarshaler(customUnmarshaler)) + assert.EqualValues(t, typeStr, factory.Type()) + assert.EqualValues(t, defaultCfg, factory.CreateDefaultConfig()) + + fu, ok := factory.(component.DeprecatedUnmarshaler) + assert.True(t, ok) + assert.Equal(t, errors.New("my error"), fu.Unmarshal(nil, nil)) + + ext, err := factory.CreateExtension(context.Background(), component.ExtensionCreateParams{}, defaultCfg) + assert.NoError(t, err) + assert.Same(t, nopExtensionInstance, ext) +} + func defaultConfig() config.Extension { return defaultCfg } @@ -54,6 +74,10 @@ func createExtension(context.Context, component.ExtensionCreateParams, config.Ex return nopExtensionInstance, nil } +func customUnmarshaler(*viper.Viper, interface{}) error { + return errors.New("my error") +} + type nopExtension struct { } diff --git a/processor/processorhelper/factory.go b/processor/processorhelper/factory.go index 2656f1feec7..b8b4db5dfb1 100644 --- a/processor/processorhelper/factory.go +++ b/processor/processorhelper/factory.go @@ -17,6 +17,8 @@ package processorhelper import ( "context" + "github.com/spf13/viper" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config" "go.opentelemetry.io/collector/config/configerror" @@ -40,12 +42,20 @@ type CreateLogsProcessor func(context.Context, component.ProcessorCreateParams, type factory struct { cfgType config.Type + customUnmarshaler component.CustomUnmarshaler createDefaultConfig CreateDefaultConfig createTraceProcessor CreateTraceProcessor createMetricsProcessor CreateMetricsProcessor createLogsProcessor CreateLogsProcessor } +// WithCustomUnmarshaler implements component.DeprecatedUnmarshaler. +func WithCustomUnmarshaler(customUnmarshaler component.CustomUnmarshaler) FactoryOption { + return func(o *factory) { + o.customUnmarshaler = customUnmarshaler + } +} + // WithTraces overrides the default "error not supported" implementation for CreateTraceProcessor. func WithTraces(createTraceProcessor CreateTraceProcessor) FactoryOption { return func(o *factory) { @@ -79,7 +89,13 @@ func NewFactory( for _, opt := range options { opt(f) } - return f + var ret component.ProcessorFactory + if f.customUnmarshaler != nil { + ret = &factoryWithUnmarshaler{f} + } else { + ret = f + } + return ret } // Type gets the type of the Processor config created by this factory. @@ -130,3 +146,14 @@ func (f *factory) CreateLogsProcessor( } return nil, configerror.ErrDataTypeIsNotSupported } + +var _ component.DeprecatedUnmarshaler = (*factoryWithUnmarshaler)(nil) + +type factoryWithUnmarshaler struct { + *factory +} + +// Unmarshal un-marshals the config using the provided custom unmarshaler. +func (f *factoryWithUnmarshaler) Unmarshal(componentViperSection *viper.Viper, intoCfg interface{}) error { + return f.customUnmarshaler(componentViperSection, intoCfg) +} diff --git a/processor/processorhelper/factory_test.go b/processor/processorhelper/factory_test.go index b53b187133a..c1573be69ab 100644 --- a/processor/processorhelper/factory_test.go +++ b/processor/processorhelper/factory_test.go @@ -16,8 +16,10 @@ package processorhelper import ( "context" + "errors" "testing" + "github.com/spf13/viper" "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/component" @@ -38,6 +40,8 @@ func TestNewTrace(t *testing.T) { defaultConfig) assert.EqualValues(t, typeStr, factory.Type()) assert.EqualValues(t, defaultCfg, factory.CreateDefaultConfig()) + _, ok := factory.(component.DeprecatedUnmarshaler) + assert.False(t, ok) _, err := factory.CreateTracesProcessor(context.Background(), component.ProcessorCreateParams{}, defaultCfg, nil) assert.Error(t, err) _, err = factory.CreateMetricsProcessor(context.Background(), component.ProcessorCreateParams{}, defaultCfg, nil) @@ -52,10 +56,15 @@ func TestNewMetrics_WithConstructors(t *testing.T) { defaultConfig, WithTraces(createTraceProcessor), WithMetrics(createMetricsProcessor), - WithLogs(createLogsProcessor)) + WithLogs(createLogsProcessor), + WithCustomUnmarshaler(customUnmarshaler)) assert.EqualValues(t, typeStr, factory.Type()) assert.EqualValues(t, defaultCfg, factory.CreateDefaultConfig()) + fu, ok := factory.(component.DeprecatedUnmarshaler) + assert.True(t, ok) + assert.Equal(t, errors.New("my error"), fu.Unmarshal(nil, nil)) + _, err := factory.CreateTracesProcessor(context.Background(), component.ProcessorCreateParams{}, defaultCfg, nil) assert.NoError(t, err) @@ -81,3 +90,7 @@ func createMetricsProcessor(context.Context, component.ProcessorCreateParams, co func createLogsProcessor(context.Context, component.ProcessorCreateParams, config.Processor, consumer.Logs) (component.LogsProcessor, error) { return nil, nil } + +func customUnmarshaler(*viper.Viper, interface{}) error { + return errors.New("my error") +} diff --git a/receiver/receiverhelper/factory.go b/receiver/receiverhelper/factory.go index bd3bf4137a0..998cfac255c 100644 --- a/receiver/receiverhelper/factory.go +++ b/receiver/receiverhelper/factory.go @@ -17,6 +17,8 @@ package receiverhelper import ( "context" + "github.com/spf13/viper" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config" "go.opentelemetry.io/collector/config/configerror" @@ -26,6 +28,13 @@ import ( // FactoryOption apply changes to ReceiverOptions. type FactoryOption func(o *factory) +// WithCustomUnmarshaler implements component.DeprecatedUnmarshaler. +func WithCustomUnmarshaler(customUnmarshaler component.CustomUnmarshaler) FactoryOption { + return func(o *factory) { + o.customUnmarshaler = customUnmarshaler + } +} + // WithTraces overrides the default "error not supported" implementation for CreateTraceReceiver. func WithTraces(createTraceReceiver CreateTraceReceiver) FactoryOption { return func(o *factory) { @@ -61,6 +70,7 @@ type CreateLogsReceiver func(context.Context, component.ReceiverCreateParams, co type factory struct { cfgType config.Type + customUnmarshaler component.CustomUnmarshaler createDefaultConfig CreateDefaultConfig createTraceReceiver CreateTraceReceiver createMetricsReceiver CreateMetricsReceiver @@ -79,7 +89,13 @@ func NewFactory( for _, opt := range options { opt(f) } - return f + var ret component.ReceiverFactory + if f.customUnmarshaler != nil { + ret = &factoryWithUnmarshaler{f} + } else { + ret = f + } + return ret } // Type gets the type of the Receiver config created by this factory. @@ -128,3 +144,14 @@ func (f *factory) CreateLogsReceiver( } return nil, configerror.ErrDataTypeIsNotSupported } + +var _ component.DeprecatedUnmarshaler = (*factoryWithUnmarshaler)(nil) + +type factoryWithUnmarshaler struct { + *factory +} + +// Unmarshal un-marshals the config using the provided custom unmarshaler. +func (f *factoryWithUnmarshaler) Unmarshal(componentViperSection *viper.Viper, intoCfg interface{}) error { + return f.customUnmarshaler(componentViperSection, intoCfg) +} diff --git a/receiver/receiverhelper/factory_test.go b/receiver/receiverhelper/factory_test.go index a38de2cc1a0..cce11ca91da 100644 --- a/receiver/receiverhelper/factory_test.go +++ b/receiver/receiverhelper/factory_test.go @@ -16,8 +16,10 @@ package receiverhelper import ( "context" + "errors" "testing" + "github.com/spf13/viper" "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/component" @@ -41,6 +43,8 @@ func TestNewFactory(t *testing.T) { defaultConfig) assert.EqualValues(t, typeStr, factory.Type()) assert.EqualValues(t, defaultCfg, factory.CreateDefaultConfig()) + _, ok := factory.(component.DeprecatedUnmarshaler) + assert.False(t, ok) _, err := factory.CreateTracesReceiver(context.Background(), component.ReceiverCreateParams{}, factory.CreateDefaultConfig(), nil) assert.Error(t, err) _, err = factory.CreateMetricsReceiver(context.Background(), component.ReceiverCreateParams{}, factory.CreateDefaultConfig(), nil) @@ -55,10 +59,15 @@ func TestNewFactory_WithConstructors(t *testing.T) { defaultConfig, WithTraces(createTraceReceiver), WithMetrics(createMetricsReceiver), - WithLogs(createLogsReceiver)) + WithLogs(createLogsReceiver), + WithCustomUnmarshaler(customUnmarshaler)) assert.EqualValues(t, typeStr, factory.Type()) assert.EqualValues(t, defaultCfg, factory.CreateDefaultConfig()) + fu, ok := factory.(component.DeprecatedUnmarshaler) + assert.True(t, ok) + assert.Equal(t, errors.New("my error"), fu.Unmarshal(nil, nil)) + _, err := factory.CreateTracesReceiver(context.Background(), component.ReceiverCreateParams{}, factory.CreateDefaultConfig(), nil) assert.NoError(t, err) @@ -84,3 +93,7 @@ func createMetricsReceiver(context.Context, component.ReceiverCreateParams, conf func createLogsReceiver(context.Context, component.ReceiverCreateParams, config.Receiver, consumer.Logs) (component.LogsReceiver, error) { return nil, nil } + +func customUnmarshaler(*viper.Viper, interface{}) error { + return errors.New("my error") +}