diff --git a/component/componenttest/nop_receiver.go b/component/componenttest/nop_receiver.go index 1db938a0722..3bc2993fdf4 100644 --- a/component/componenttest/nop_receiver.go +++ b/component/componenttest/nop_receiver.go @@ -16,7 +16,7 @@ package componenttest import ( "context" - "fmt" + "errors" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenthelper" @@ -39,13 +39,14 @@ func (f *nopReceiverFactory) Type() config.Type { return "nop" } +// TODO: Consider to remove this or move it to configtest. type NopConfig struct { config.ReceiverSettings } func (nc *NopConfig) Validate() error { if nc.TypeVal != "nop" { - return fmt.Errorf("invalid receiver config") + return errors.New("invalid receiver config") } return nil } diff --git a/config/config.go b/config/config.go index d158a9fd81f..6a610b91926 100644 --- a/config/config.go +++ b/config/config.go @@ -49,6 +49,8 @@ type Config struct { Service } +var _ validatable = (*Config)(nil) + // Validate returns an error if the config is invalid. // // This function performs basic validation of configuration. There may be more subtle @@ -61,6 +63,13 @@ func (cfg *Config) Validate() error { return errMissingReceivers } + // Validate the receiver configuration. + for recv, recvCfg := range cfg.Receivers { + if err := recvCfg.Validate(); err != nil { + return fmt.Errorf("receiver \"%s\" has invalid configuration: %w", recv, err) + } + } + // Currently there is no default exporter enabled. // The configuration must specify at least one exporter to be valid. if len(cfg.Exporters) == 0 { @@ -108,13 +117,6 @@ func (cfg *Config) validateServicePipelines() error { if cfg.Receivers[ref] == nil { return fmt.Errorf("pipeline %q references receiver %q which does not exist", pipeline.Name, ref) } - - // Validate the receiver configuration by the custom configuration validator - recCfg := cfg.Receivers[ref] - if err := recCfg.Validate(); err != nil { - return fmt.Errorf("pipeline %q references receiver %q which has invalid configuration with error: %v", pipeline.Name, ref, err) - } - } // Validate pipeline processor name references @@ -160,6 +162,12 @@ type NamedEntity interface { SetName(name string) } +// validatable defines the interface for the configuration validation. +type validatable interface { + // Validate validates the configuration and returns an error if invalid. + Validate() error +} + // DataType is the data type that is supported for collection. We currently support // collecting metrics, traces and logs, this can expand in the future. type DataType string diff --git a/config/config_test.go b/config/config_test.go index 2909ccdcec8..aa477fcb112 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -22,13 +22,15 @@ import ( "github.com/stretchr/testify/assert" ) -type NopConfig struct { +var errInvalidConfig = errors.New("invalid receiver config") + +type nopConfig struct { ReceiverSettings } -func (nc *NopConfig) Validate() error { +func (nc *nopConfig) Validate() error { if nc.TypeVal != "nop" { - return fmt.Errorf("invalid receiver config") + return errInvalidConfig } return nil } @@ -134,14 +136,14 @@ func TestConfigValidate(t *testing.T) { name: "invalid-receiver-config", cfgFn: func() *Config { cfg := generateConfig() - cfg.Receivers["nop"] = &NopConfig{ + cfg.Receivers["nop"] = &nopConfig{ ReceiverSettings: ReceiverSettings{ TypeVal: "invalid_rec_type", }, } return cfg }, - expected: fmt.Errorf(`pipeline "traces" references receiver "nop" which has invalid configuration with error: invalid receiver config`), + expected: fmt.Errorf(`receiver "nop" has invalid configuration: %w`, errInvalidConfig), }, } @@ -156,7 +158,7 @@ func TestConfigValidate(t *testing.T) { func generateConfig() *Config { return &Config{ Receivers: map[string]Receiver{ - "nop": &NopConfig{ + "nop": &nopConfig{ ReceiverSettings: ReceiverSettings{ TypeVal: "nop", }, diff --git a/config/receiver.go b/config/receiver.go index 404baa47fce..95e530cac93 100644 --- a/config/receiver.go +++ b/config/receiver.go @@ -16,27 +16,12 @@ package config // Receiver is the configuration of a receiver. Specific receivers must implement this // interface and will typically embed ReceiverSettings struct or a struct that extends it. -// Embedded CustomConfigOptions will force each receiver to implement Validate() function +// Embedded validatable will force each receiver to implement Validate() function type Receiver interface { NamedEntity - CustomConfigOptions + validatable } -// CustomConfigOptions defines the interfaces for configuration customization options -// Different custom interfaces can be added like CustomConfigValidator and any other interface. -type CustomConfigOptions interface { - CustomConfigValidator -} - -// CustomConfigValidator defines the interface for the custom configuration validation on each component -type CustomConfigValidator interface { - Validate() error -} - -// CustomValidator is a function that runs the customized validation -// on component level configuration. -type CustomValidator func() error - // Receivers is a map of names to Receivers. type Receivers map[string]Receiver diff --git a/receiver/hostmetricsreceiver/config.go b/receiver/hostmetricsreceiver/config.go index 6d209e885c3..60de4618d96 100644 --- a/receiver/hostmetricsreceiver/config.go +++ b/receiver/hostmetricsreceiver/config.go @@ -26,7 +26,7 @@ type Config struct { Scrapers map[string]internal.Config `mapstructure:"-"` } -var _ config.CustomConfigOptions = (*Config)(nil) +var _ config.Receiver = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { diff --git a/receiver/jaegerreceiver/config.go b/receiver/jaegerreceiver/config.go index 2902425621b..645b510d035 100644 --- a/receiver/jaegerreceiver/config.go +++ b/receiver/jaegerreceiver/config.go @@ -73,7 +73,7 @@ type Config struct { RemoteSampling *RemoteSamplingConfig `mapstructure:"remote_sampling"` } -var _ config.CustomConfigOptions = (*Config)(nil) +var _ config.Receiver = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { diff --git a/receiver/kafkareceiver/config.go b/receiver/kafkareceiver/config.go index 2c6192a6d6c..ec8f368ea37 100644 --- a/receiver/kafkareceiver/config.go +++ b/receiver/kafkareceiver/config.go @@ -42,7 +42,7 @@ type Config struct { Authentication kafkaexporter.Authentication `mapstructure:"auth"` } -var _ config.CustomConfigOptions = (*Config)(nil) +var _ config.Receiver = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { diff --git a/receiver/opencensusreceiver/config.go b/receiver/opencensusreceiver/config.go index 0e24b4f0b66..be372c67c78 100644 --- a/receiver/opencensusreceiver/config.go +++ b/receiver/opencensusreceiver/config.go @@ -50,7 +50,7 @@ func (cfg *Config) buildOptions() ([]ocOption, error) { return opts, nil } -var _ config.CustomConfigOptions = (*Config)(nil) +var _ config.Receiver = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { diff --git a/receiver/otlpreceiver/config.go b/receiver/otlpreceiver/config.go index 374ed6d03ea..a321458a8af 100644 --- a/receiver/otlpreceiver/config.go +++ b/receiver/otlpreceiver/config.go @@ -33,7 +33,7 @@ type Config struct { Protocols `mapstructure:"protocols"` } -var _ config.CustomConfigOptions = (*Config)(nil) +var _ config.Receiver = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { diff --git a/receiver/prometheusreceiver/config.go b/receiver/prometheusreceiver/config.go index d64b545ea3d..210df77970f 100644 --- a/receiver/prometheusreceiver/config.go +++ b/receiver/prometheusreceiver/config.go @@ -17,19 +17,19 @@ package prometheusreceiver import ( "time" - "github.com/prometheus/prometheus/config" + promconfig "github.com/prometheus/prometheus/config" - config2 "go.opentelemetry.io/collector/config" + "go.opentelemetry.io/collector/config" ) // Config defines configuration for Prometheus receiver. type Config struct { - config2.ReceiverSettings `mapstructure:",squash"` - PrometheusConfig *config.Config `mapstructure:"-"` - BufferPeriod time.Duration `mapstructure:"buffer_period"` - BufferCount int `mapstructure:"buffer_count"` - UseStartTimeMetric bool `mapstructure:"use_start_time_metric"` - StartTimeMetricRegex string `mapstructure:"start_time_metric_regex"` + config.ReceiverSettings `mapstructure:",squash"` + PrometheusConfig *promconfig.Config `mapstructure:"-"` + BufferPeriod time.Duration `mapstructure:"buffer_period"` + BufferCount int `mapstructure:"buffer_count"` + UseStartTimeMetric bool `mapstructure:"use_start_time_metric"` + StartTimeMetricRegex string `mapstructure:"start_time_metric_regex"` // ConfigPlaceholder is just an entry to make the configuration pass a check // that requires that all keys present in the config actually exist on the @@ -37,7 +37,7 @@ type Config struct { ConfigPlaceholder interface{} `mapstructure:"config"` } -var _ config2.CustomConfigOptions = (*Config)(nil) +var _ config.Receiver = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { diff --git a/receiver/receiverhelper/factory_test.go b/receiver/receiverhelper/factory_test.go index 817c8b5300f..d28db0e2177 100644 --- a/receiver/receiverhelper/factory_test.go +++ b/receiver/receiverhelper/factory_test.go @@ -45,11 +45,11 @@ func TestNewFactory(t *testing.T) { assert.EqualValues(t, defaultCfg, factory.CreateDefaultConfig()) _, ok := factory.(component.ConfigUnmarshaler) assert.False(t, ok) - _, err := factory.CreateTracesReceiver(context.Background(), component.ReceiverCreateParams{}, defaultCfg, nil) + _, err := factory.CreateTracesReceiver(context.Background(), component.ReceiverCreateParams{}, factory.CreateDefaultConfig(), nil) assert.Error(t, err) - _, err = factory.CreateMetricsReceiver(context.Background(), component.ReceiverCreateParams{}, defaultCfg, nil) + _, err = factory.CreateMetricsReceiver(context.Background(), component.ReceiverCreateParams{}, factory.CreateDefaultConfig(), nil) assert.Error(t, err) - _, err = factory.CreateLogsReceiver(context.Background(), component.ReceiverCreateParams{}, defaultCfg, nil) + _, err = factory.CreateLogsReceiver(context.Background(), component.ReceiverCreateParams{}, factory.CreateDefaultConfig(), nil) assert.Error(t, err) } @@ -68,13 +68,13 @@ func TestNewFactory_WithConstructors(t *testing.T) { assert.True(t, ok) assert.Equal(t, errors.New("my error"), fu.Unmarshal(nil, nil)) - _, err := factory.CreateTracesReceiver(context.Background(), component.ReceiverCreateParams{}, defaultCfg, nil) + _, err := factory.CreateTracesReceiver(context.Background(), component.ReceiverCreateParams{}, factory.CreateDefaultConfig(), nil) assert.NoError(t, err) - _, err = factory.CreateMetricsReceiver(context.Background(), component.ReceiverCreateParams{}, defaultCfg, nil) + _, err = factory.CreateMetricsReceiver(context.Background(), component.ReceiverCreateParams{}, factory.CreateDefaultConfig(), nil) assert.NoError(t, err) - _, err = factory.CreateLogsReceiver(context.Background(), component.ReceiverCreateParams{}, defaultCfg, nil) + _, err = factory.CreateLogsReceiver(context.Background(), component.ReceiverCreateParams{}, factory.CreateDefaultConfig(), nil) assert.NoError(t, err) } diff --git a/receiver/zipkinreceiver/config.go b/receiver/zipkinreceiver/config.go index 3762dafc4a1..0739ce34962 100644 --- a/receiver/zipkinreceiver/config.go +++ b/receiver/zipkinreceiver/config.go @@ -29,11 +29,9 @@ type Config struct { // If enabled the zipkin receiver will attempt to parse string tags/binary annotations into int/bool/float. // Disabled by default ParseStringTags bool `mapstructure:"parse_string_tags"` - - config.CustomConfigOptions } -var _ config.CustomConfigOptions = (*Config)(nil) +var _ config.Receiver = (*Config)(nil) // Validate checks the receiver configuration is valid func (cfg *Config) Validate() error { diff --git a/service/internal/builder/factories_test.go b/service/internal/builder/factories_test.go index c8ed32696fd..f25a375feb9 100644 --- a/service/internal/builder/factories_test.go +++ b/service/internal/builder/factories_test.go @@ -18,7 +18,7 @@ import ( "context" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/component/componenttest" + componenttest "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/config" "go.opentelemetry.io/collector/exporter/exporterhelper" "go.opentelemetry.io/collector/extension/extensionhelper" diff --git a/service/internal/builder/receivers_builder_test.go b/service/internal/builder/receivers_builder_test.go index 1cef5027c13..425f889fa7b 100644 --- a/service/internal/builder/receivers_builder_test.go +++ b/service/internal/builder/receivers_builder_test.go @@ -260,8 +260,7 @@ func TestBuildReceivers_BuildCustom(t *testing.T) { func TestBuildReceivers_StartAll(t *testing.T) { receivers := make(Receivers) - rcvCfg := &componenttest.NopConfig{} - + rcvCfg := &testcomponents.ExampleReceiver{} receiver := &testcomponents.ExampleReceiverProducer{} receivers[rcvCfg] = &builtReceiver{ @@ -279,8 +278,7 @@ func TestBuildReceivers_StartAll(t *testing.T) { func TestBuildReceivers_StopAll(t *testing.T) { receivers := make(Receivers) - rcvCfg := &componenttest.NopConfig{} - + rcvCfg := &testcomponents.ExampleReceiver{} receiver := &testcomponents.ExampleReceiverProducer{} receivers[rcvCfg] = &builtReceiver{