diff --git a/CHANGELOG.md b/CHANGELOG.md index ef81c50b40e..2912bc207ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ ### 🚩 Deprecations 🚩 - Deprecate configmapprovider package, replace with mapconverter (#5167) +- Deprecate `service.MustNewConfigProvider` and `service.MustNewDefaultConfigProvider`in favor of `service.NewConfigProvider` (#4762) ### 💡 Enhancements 💡 diff --git a/service/collector_test.go b/service/collector_test.go index 507a3fc6ee6..d8f05e59f25 100644 --- a/service/collector_test.go +++ b/service/collector_test.go @@ -36,6 +36,8 @@ import ( "go.uber.org/zap/zapcore" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config" + "go.opentelemetry.io/collector/config/mapconverter/overwritepropertiesmapconverter" "go.opentelemetry.io/collector/internal/testcomponents" "go.opentelemetry.io/collector/internal/testutil" "go.opentelemetry.io/collector/service/featuregate" @@ -60,11 +62,18 @@ func TestCollector_StartAsGoRoutine(t *testing.T) { factories, err := testcomponents.NewDefaultFactories() require.NoError(t, err) + cfgSet := newDefaultConfigProviderSettings() + cfgSet.Locations = []string{ + filepath.Join("testdata", "otelcol-config.yaml"), + "yaml:service::telemetry::metrics::address: localhost:" + portAsString(testutil.GetAvailablePort(t)), + } + cfgProvider, err := NewConfigProvider(cfgSet) + require.NoError(t, err) + set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: MustNewDefaultConfigProvider([]string{filepath.Join("testdata", "otelcol-config.yaml")}, - []string{"service.telemetry.metrics.address=localhost:" + strconv.FormatUint(uint64(testutil.GetAvailablePort(t)), 10)}), + BuildInfo: component.NewDefaultBuildInfo(), + Factories: factories, + ConfigProvider: cfgProvider, } col, err := New(set) require.NoError(t, err) @@ -98,12 +107,23 @@ func testCollectorStartHelper(t *testing.T) { } metricsPort := testutil.GetAvailablePort(t) + cfgSet := newDefaultConfigProviderSettings() + cfgSet.Locations = []string{ + filepath.Join("testdata", "otelcol-config.yaml"), + } + cfgSet.MapConverters = append([]config.MapConverterFunc{ + overwritepropertiesmapconverter.New( + []string{"service.telemetry.metrics.address=localhost:" + portAsString(metricsPort)}, + )}, + cfgSet.MapConverters..., + ) + cfgProvider, err := NewConfigProvider(cfgSet) + require.NoError(t, err) + col, err := New(CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: MustNewDefaultConfigProvider( - []string{filepath.Join("testdata", "otelcol-config.yaml")}, - []string{"service.telemetry.metrics.address=localhost:" + strconv.FormatUint(uint64(metricsPort), 10)}), + BuildInfo: component.NewDefaultBuildInfo(), + Factories: factories, + ConfigProvider: cfgProvider, LoggingOptions: []zap.Option{zap.Hooks(hook)}, }) require.NoError(t, err) @@ -169,10 +189,17 @@ func TestCollector_ShutdownNoop(t *testing.T) { factories, err := testcomponents.NewDefaultFactories() require.NoError(t, err) + cfgSet := newDefaultConfigProviderSettings() + cfgSet.Locations = []string{ + filepath.Join("testdata", "otelcol-config.yaml"), + } + cfgProvider, err := NewConfigProvider(cfgSet) + require.NoError(t, err) + set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), Factories: factories, - ConfigProvider: MustNewDefaultConfigProvider([]string{filepath.Join("testdata", "otelcol-config.yaml")}, nil), + ConfigProvider: cfgProvider, } col, err := New(set) require.NoError(t, err) @@ -190,10 +217,17 @@ func TestCollector_ShutdownBeforeRun(t *testing.T) { factories, err := testcomponents.NewDefaultFactories() require.NoError(t, err) + cfgSet := newDefaultConfigProviderSettings() + cfgSet.Locations = []string{ + filepath.Join("testdata", "otelcol-config.yaml"), + } + cfgProvider, err := NewConfigProvider(cfgSet) + require.NoError(t, err) + set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), Factories: factories, - ConfigProvider: MustNewDefaultConfigProvider([]string{filepath.Join("testdata", "otelcol-config.yaml")}, nil), + ConfigProvider: cfgProvider, } col, err := New(set) require.NoError(t, err) @@ -221,11 +255,18 @@ func TestCollector_ClosedStateOnStartUpError(t *testing.T) { factories, err := testcomponents.NewDefaultFactories() require.NoError(t, err) + cfgSet := newDefaultConfigProviderSettings() + cfgSet.Locations = []string{ + filepath.Join("testdata", "otelcol-invalid.yaml"), + } + cfgProvider, err := NewConfigProvider(cfgSet) + require.NoError(t, err) + // Load a bad config causing startup to fail set := CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), Factories: factories, - ConfigProvider: MustNewDefaultConfigProvider([]string{filepath.Join("testdata", "otelcol-invalid.yaml")}, nil), + ConfigProvider: cfgProvider, } col, err := New(set) require.NoError(t, err) @@ -256,10 +297,17 @@ func TestCollector_ReportError(t *testing.T) { factories, err := testcomponents.NewDefaultFactories() require.NoError(t, err) + cfgSet := newDefaultConfigProviderSettings() + cfgSet.Locations = []string{ + filepath.Join("testdata", "otelcol-config.yaml"), + } + cfgProvider, err := NewConfigProvider(cfgSet) + require.NoError(t, err) + col, err := New(CollectorSettings{ BuildInfo: component.NewDefaultBuildInfo(), Factories: factories, - ConfigProvider: MustNewDefaultConfigProvider([]string{filepath.Join("testdata", "otelcol-config.yaml")}, nil), + ConfigProvider: cfgProvider, }) require.NoError(t, err) @@ -288,11 +336,18 @@ func TestCollector_ContextCancel(t *testing.T) { factories, err := testcomponents.NewDefaultFactories() require.NoError(t, err) + cfgSet := newDefaultConfigProviderSettings() + cfgSet.Locations = []string{ + filepath.Join("testdata", "otelcol-config.yaml"), + "yaml:service::telemetry::metrics::address: localhost:" + portAsString(testutil.GetAvailablePort(t)), + } + cfgProvider, err := NewConfigProvider(cfgSet) + require.NoError(t, err) + set := CollectorSettings{ - BuildInfo: component.NewDefaultBuildInfo(), - Factories: factories, - ConfigProvider: MustNewDefaultConfigProvider([]string{filepath.Join("testdata", "otelcol-config.yaml")}, - []string{"service.telemetry.metrics.address=localhost:" + strconv.FormatUint(uint64(testutil.GetAvailablePort(t)), 10)}), + BuildInfo: component.NewDefaultBuildInfo(), + Factories: factories, + ConfigProvider: cfgProvider, } col, err := New(set) require.NoError(t, err) @@ -377,3 +432,7 @@ func assertZPages(t *testing.T) { testZPagePathFn(t, path) } } + +func portAsString(p uint16) string { + return strconv.FormatUint(uint64(p), 10) +} diff --git a/service/collector_windows.go b/service/collector_windows.go index a9c74c1c55d..7b36caccb11 100644 --- a/service/collector_windows.go +++ b/service/collector_windows.go @@ -29,6 +29,8 @@ import ( "golang.org/x/sys/windows/svc" "golang.org/x/sys/windows/svc/eventlog" + "go.opentelemetry.io/collector/config" + "go.opentelemetry.io/collector/config/mapconverter/overwritepropertiesmapconverter" "go.opentelemetry.io/collector/service/featuregate" ) @@ -144,7 +146,17 @@ func openEventLog(serviceName string) (*eventlog.Log, error) { func newWithWindowsEventLogCore(set CollectorSettings, elog *eventlog.Log) (*Collector, error) { if set.ConfigProvider == nil { - set.ConfigProvider = MustNewDefaultConfigProvider(getConfigFlag(), getSetFlag()) + var err error + cfgSet := newDefaultConfigProviderSettings() + cfgSet.Locations = getConfigFlag() + // Append the "overwrite properties converter" as the first converter. + cfgSet.MapConverters = append( + []config.MapConverterFunc{overwritepropertiesmapconverter.New(getSetFlag())}, + cfgSet.MapConverters...) + set.ConfigProvider, err = NewConfigProvider(cfgSet) + if err != nil { + return nil, err + } } set.LoggingOptions = append( set.LoggingOptions, diff --git a/service/command.go b/service/command.go index d71d7ca8248..5130a6fe6c6 100644 --- a/service/command.go +++ b/service/command.go @@ -17,6 +17,8 @@ package service // import "go.opentelemetry.io/collector/service" import ( "github.com/spf13/cobra" + "go.opentelemetry.io/collector/config" + "go.opentelemetry.io/collector/config/mapconverter/overwritepropertiesmapconverter" "go.opentelemetry.io/collector/service/featuregate" ) @@ -29,7 +31,17 @@ func NewCommand(set CollectorSettings) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { featuregate.Apply(gatesList) if set.ConfigProvider == nil { - set.ConfigProvider = MustNewDefaultConfigProvider(getConfigFlag(), getSetFlag()) + var err error + cfgSet := newDefaultConfigProviderSettings() + cfgSet.Locations = getConfigFlag() + // Append the "overwrite properties converter" as the first converter. + cfgSet.MapConverters = append( + []config.MapConverterFunc{overwritepropertiesmapconverter.New(getSetFlag())}, + cfgSet.MapConverters...) + set.ConfigProvider, err = NewConfigProvider(cfgSet) + if err != nil { + return err + } } col, err := New(set) if err != nil { diff --git a/service/config_provider.go b/service/config_provider.go index c8dcdb63552..d909b57d1d3 100644 --- a/service/config_provider.go +++ b/service/config_provider.go @@ -69,50 +69,102 @@ type ConfigProvider interface { } type configProvider struct { - locations []string - configMapProviders map[string]config.MapProvider - cfgMapConverters []config.MapConverterFunc - configUnmarshaler configunmarshaler.ConfigUnmarshaler + locations []string + configMapProviders map[string]config.MapProvider + configMapConverters []config.MapConverterFunc + configUnmarshaler configunmarshaler.ConfigUnmarshaler sync.Mutex closer config.CloseFunc watcher chan error } -// MustNewConfigProvider returns a new ConfigProvider that provides the configuration: -// * Retrieve the config.Map by merging all retrieved maps from all the config.MapProvider in order. -// * Then applies all the ConfigMapConverterFunc in the given order. -// * Then unmarshalls the final config.Config using the given configunmarshaler.ConfigUnmarshaler. -// -// The `configMapProviders` is a map of pairs . +// ConfigProviderSettings are the settings to configure the behavior of the ConfigProvider. +type ConfigProviderSettings struct { + // Locations from where the config.Map is retrieved, and merged in the given order. + // It is required to have at least one location. + Locations []string + + // MapProviders is a map of pairs . + // It is required to have at least one config.MapProvider. + MapProviders map[string]config.MapProvider + + // MapConverters is a slice of config.MapConverterFunc. + MapConverters []config.MapConverterFunc + + // The configunmarshaler.ConfigUnmarshaler to be used to unmarshal the config.Map into config.Config. + // It is required to not be nil, use configunmarshaler.NewDefault() by default. + Unmarshaler configunmarshaler.ConfigUnmarshaler +} + +func newDefaultConfigProviderSettings() ConfigProviderSettings { + return ConfigProviderSettings{ + MapProviders: makeConfigMapProviderMap(filemapprovider.New(), envmapprovider.New(), yamlmapprovider.New()), + MapConverters: []config.MapConverterFunc{expandmapconverter.New()}, + Unmarshaler: configunmarshaler.NewDefault(), + } +} + +// Deprecated: [v0.49.0] use NewConfigProvider instead. func MustNewConfigProvider( locations []string, configMapProviders map[string]config.MapProvider, - cfgMapConverters []config.MapConverterFunc, + configMapConverters []config.MapConverterFunc, configUnmarshaler configunmarshaler.ConfigUnmarshaler) ConfigProvider { - // Safe copy, ensures the slice cannot be changed from the caller. - locationsCopy := make([]string, len(locations)) - copy(locationsCopy, locations) - return &configProvider{ - locations: locationsCopy, - configMapProviders: configMapProviders, - cfgMapConverters: cfgMapConverters, - configUnmarshaler: configUnmarshaler, - watcher: make(chan error, 1), + cfgProvider, err := NewConfigProvider(ConfigProviderSettings{ + Locations: locations, + MapProviders: configMapProviders, + MapConverters: configMapConverters, + Unmarshaler: configUnmarshaler, + }) + if err != nil { + panic(err) } + return cfgProvider } -// MustNewDefaultConfigProvider returns the default ConfigProvider from slice of location strings -// (e.g. file:/path/to/config.yaml) and property overrides (e.g. service.telemetry.metrics.address=localhost:8888). -func MustNewDefaultConfigProvider(configLocations []string, properties []string) ConfigProvider { - return MustNewConfigProvider( - configLocations, - makeConfigMapProviderMap(filemapprovider.New(), envmapprovider.New(), yamlmapprovider.New()), - []config.MapConverterFunc{ - overwritepropertiesmapconverter.New(properties), - expandmapconverter.New(), - }, - configunmarshaler.NewDefault()) +// NewConfigProvider returns a new ConfigProvider that provides the configuration: +// * Retrieve the config.Map by merging all retrieved maps from the given `locations` in order. +// * Then applies all the config.MapConverterFunc in the given order. +// * Then unmarshals the config.Map into the service Config. +func NewConfigProvider(set ConfigProviderSettings) (ConfigProvider, error) { + if len(set.Locations) == 0 { + return nil, fmt.Errorf("cannot create ConfigProvider: no Locations") + } + + if len(set.MapProviders) == 0 { + return nil, fmt.Errorf("cannot create ConfigProvider: no MapProviders") + } + + // Safe copy, ensures the slices and maps cannot be changed from the caller. + locationsCopy := make([]string, len(set.Locations)) + copy(locationsCopy, set.Locations) + mapProvidersCopy := make(map[string]config.MapProvider, len(set.MapProviders)) + for k, v := range set.MapProviders { + mapProvidersCopy[k] = v + } + mapConvertersCopy := make([]config.MapConverterFunc, len(set.MapConverters)) + copy(mapConvertersCopy, set.MapConverters) + + return &configProvider{ + locations: locationsCopy, + configMapProviders: mapProvidersCopy, + configMapConverters: mapConvertersCopy, + configUnmarshaler: set.Unmarshaler, + watcher: make(chan error, 1), + }, nil +} + +// Deprecated: [v0.49.0] use NewConfigProvider instead. +func MustNewDefaultConfigProvider(locations []string, properties []string) ConfigProvider { + set := newDefaultConfigProviderSettings() + set.Locations = locations + set.MapConverters = append([]config.MapConverterFunc{overwritepropertiesmapconverter.New(properties)}, set.MapConverters...) + cfgProvider, err := NewConfigProvider(set) + if err != nil { + panic(err) + } + return cfgProvider } func (cm *configProvider) Get(ctx context.Context, factories component.Factories) (*config.Config, error) { @@ -128,7 +180,7 @@ func (cm *configProvider) Get(ctx context.Context, factories component.Factories cm.closer = ret.CloseFunc // Apply all converters. - for _, cfgMapConv := range cm.cfgMapConverters { + for _, cfgMapConv := range cm.configMapConverters { if err = cfgMapConv(ctx, ret.Map); err != nil { return nil, fmt.Errorf("cannot convert the config.Map: %w", err) } diff --git a/service/config_provider_test.go b/service/config_provider_test.go index 15bcc6492d5..0d1f080b373 100644 --- a/service/config_provider_test.go +++ b/service/config_provider_test.go @@ -34,11 +34,12 @@ import ( ) type mockProvider struct { - retM *config.Map - errR error - errS error - errW error - errC error + scheme string + retM *config.Map + errR error + errS error + errW error + errC error } func (m *mockProvider) Retrieve(_ context.Context, _ string, watcher config.WatcherFunc) (config.Retrieved, error) { @@ -55,7 +56,10 @@ func (m *mockProvider) Retrieve(_ context.Context, _ string, watcher config.Watc } func (m *mockProvider) Scheme() string { - return "mock" + if m.scheme == "" { + return "mock" + } + return m.scheme } func (m *mockProvider) Shutdown(context.Context) error { @@ -77,7 +81,7 @@ func TestConfigProvider_Errors(t *testing.T) { tests := []struct { name string locations []string - parserProvider map[string]config.MapProvider + parserProvider []config.MapProvider cfgMapConverters []config.MapConverterFunc configUnmarshaler configunmarshaler.ConfigUnmarshaler expectNewErr bool @@ -85,65 +89,51 @@ func TestConfigProvider_Errors(t *testing.T) { expectShutdownErr bool }{ { - name: "retrieve_err", - locations: []string{"mock:", "not_supported:"}, - parserProvider: map[string]config.MapProvider{ - "mock": &mockProvider{}, - }, + name: "retrieve_err", + locations: []string{"mock:", "not_supported:"}, + parserProvider: []config.MapProvider{&mockProvider{}}, configUnmarshaler: configunmarshaler.NewDefault(), expectNewErr: true, }, { name: "retrieve_err", locations: []string{"mock:", "err:"}, - parserProvider: map[string]config.MapProvider{ - "mock": &mockProvider{}, - "err": &mockProvider{errR: errors.New("retrieve_err")}, + parserProvider: []config.MapProvider{ + &mockProvider{}, + &mockProvider{scheme: "err", errR: errors.New("retrieve_err")}, }, configUnmarshaler: configunmarshaler.NewDefault(), expectNewErr: true, }, { - name: "converter_err", - locations: []string{"mock:", filepath.Join("testdata", "otelcol-nop.yaml")}, - parserProvider: map[string]config.MapProvider{ - "mock": &mockProvider{}, - "file": filemapprovider.New(), - }, + name: "converter_err", + locations: []string{"mock:", filepath.Join("testdata", "otelcol-nop.yaml")}, + parserProvider: []config.MapProvider{&mockProvider{}, filemapprovider.New()}, cfgMapConverters: []config.MapConverterFunc{func(context.Context, *config.Map) error { return errors.New("converter_err") }}, configUnmarshaler: configunmarshaler.NewDefault(), expectNewErr: true, }, { - name: "unmarshal_err", - locations: []string{"mock:", filepath.Join("testdata", "otelcol-nop.yaml")}, - parserProvider: map[string]config.MapProvider{ - "mock": &mockProvider{}, - "file": filemapprovider.New(), - }, + name: "unmarshal_err", + locations: []string{"mock:", filepath.Join("testdata", "otelcol-nop.yaml")}, + parserProvider: []config.MapProvider{&mockProvider{}, filemapprovider.New()}, configUnmarshaler: &errConfigUnmarshaler{err: errors.New("unmarshal_err")}, expectNewErr: true, }, { - name: "validation_err", - locations: []string{"mock:", filepath.Join("testdata", "otelcol-invalid.yaml")}, - parserProvider: map[string]config.MapProvider{ - "mock": &mockProvider{}, - "file": filemapprovider.New(), - }, + name: "validation_err", + locations: []string{"mock:", filepath.Join("testdata", "otelcol-invalid.yaml")}, + parserProvider: []config.MapProvider{&mockProvider{}, filemapprovider.New()}, configUnmarshaler: configunmarshaler.NewDefault(), expectNewErr: true, }, { name: "watch_err", locations: []string{"mock:", "err:"}, - parserProvider: func() map[string]config.MapProvider { + parserProvider: func() []config.MapProvider { cfgMap, err := configtest.LoadConfigMap(filepath.Join("testdata", "otelcol-nop.yaml")) require.NoError(t, err) - return map[string]config.MapProvider{ - "mock": &mockProvider{}, - "err": &mockProvider{retM: cfgMap, errW: errors.New("watch_err")}, - } + return []config.MapProvider{&mockProvider{}, &mockProvider{scheme: "err", retM: cfgMap, errW: errors.New("watch_err")}} }(), configUnmarshaler: configunmarshaler.NewDefault(), expectWatchErr: true, @@ -151,12 +141,12 @@ func TestConfigProvider_Errors(t *testing.T) { { name: "close_err", locations: []string{"mock:", "err:"}, - parserProvider: func() map[string]config.MapProvider { + parserProvider: func() []config.MapProvider { cfgMap, err := configtest.LoadConfigMap(filepath.Join("testdata", "otelcol-nop.yaml")) require.NoError(t, err) - return map[string]config.MapProvider{ - "mock": &mockProvider{}, - "err": &mockProvider{retM: cfgMap, errC: errors.New("close_err")}, + return []config.MapProvider{ + &mockProvider{}, + &mockProvider{scheme: "err", retM: cfgMap, errC: errors.New("close_err")}, } }(), configUnmarshaler: configunmarshaler.NewDefault(), @@ -165,7 +155,16 @@ func TestConfigProvider_Errors(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cfgW := MustNewConfigProvider(tt.locations, tt.parserProvider, tt.cfgMapConverters, tt.configUnmarshaler) + set := ConfigProviderSettings{ + Locations: tt.locations, + MapProviders: makeConfigMapProviderMap(tt.parserProvider...), + MapConverters: tt.cfgMapConverters, + Unmarshaler: tt.configUnmarshaler, + } + + cfgW, err := NewConfigProvider(set) + assert.NoError(t, err) + _, errN := cfgW.Get(context.Background(), factories) if tt.expectNewErr { assert.Error(t, errN) @@ -191,6 +190,39 @@ func TestConfigProvider_Errors(t *testing.T) { } func TestConfigProvider(t *testing.T) { + factories, errF := componenttest.NopFactories() + require.NoError(t, errF) + mapProvider := func() config.MapProvider { + cfgMap, err := configtest.LoadConfigMap(filepath.Join("testdata", "otelcol-nop.yaml")) + require.NoError(t, err) + return &mockProvider{retM: cfgMap} + }() + + set := newDefaultConfigProviderSettings() + set.Locations = []string{"mock:"} + set.MapProviders[mapProvider.Scheme()] = mapProvider + cfgW, err := NewConfigProvider(set) + require.NoError(t, err) + _, errN := cfgW.Get(context.Background(), factories) + assert.NoError(t, errN) + + errW := <-cfgW.Watch() + assert.NoError(t, errW) + + // Repeat Get/Watch. + + _, errN = cfgW.Get(context.Background(), factories) + assert.NoError(t, errN) + + errW = <-cfgW.Watch() + assert.NoError(t, errW) + + errC := cfgW.Shutdown(context.Background()) + assert.NoError(t, errC) +} + +// TODO: Remove when remove MustNewConfigProvider, duplicate of TestConfigProvider. +func TestMustNewConfigProvider(t *testing.T) { factories, errF := componenttest.NopFactories() require.NoError(t, errF) configMapProvider := func() config.MapProvider { @@ -201,10 +233,11 @@ func TestConfigProvider(t *testing.T) { }() cfgW := MustNewConfigProvider( - []string{"watcher:"}, - map[string]config.MapProvider{"watcher": configMapProvider}, + []string{"mock:"}, + map[string]config.MapProvider{"mock": configMapProvider}, nil, configunmarshaler.NewDefault()) + _, errN := cfgW.Get(context.Background(), factories) assert.NoError(t, errN) @@ -227,12 +260,35 @@ func TestConfigProviderNoWatcher(t *testing.T) { factories, errF := componenttest.NopFactories() require.NoError(t, errF) + set := newDefaultConfigProviderSettings() + set.Locations = []string{filepath.Join("testdata", "otelcol-nop.yaml")} + watcherWG := sync.WaitGroup{} - cfgW := MustNewConfigProvider( - []string{filepath.Join("testdata", "otelcol-nop.yaml")}, - map[string]config.MapProvider{"file": filemapprovider.New()}, - nil, - configunmarshaler.NewDefault()) + cfgW, err := NewConfigProvider(set) + require.NoError(t, err) + _, errN := cfgW.Get(context.Background(), factories) + assert.NoError(t, errN) + + watcherWG.Add(1) + go func() { + errW, ok := <-cfgW.Watch() + // Channel is closed, no exception + assert.False(t, ok) + assert.NoError(t, errW) + watcherWG.Done() + }() + + assert.NoError(t, cfgW.Shutdown(context.Background())) + watcherWG.Wait() +} + +// TODO: Remove when remove MustNewDefaultConfigProvider, duplicate of TestConfigProviderNoWatcher. +func TestMustNewDefaultConfigProvider(t *testing.T) { + factories, errF := componenttest.NopFactories() + require.NoError(t, errF) + + watcherWG := sync.WaitGroup{} + cfgW := MustNewDefaultConfigProvider([]string{filepath.Join("testdata", "otelcol-nop.yaml")}, nil) _, errN := cfgW.Get(context.Background(), factories) assert.NoError(t, errN) @@ -252,20 +308,22 @@ func TestConfigProviderNoWatcher(t *testing.T) { func TestConfigProvider_ShutdownClosesWatch(t *testing.T) { factories, errF := componenttest.NopFactories() require.NoError(t, errF) - configMapProvider := func() config.MapProvider { + mapProvider := func() config.MapProvider { // Use fakeRetrieved with nil errors to have Watchable interface implemented. cfgMap, err := configtest.LoadConfigMap(filepath.Join("testdata", "otelcol-nop.yaml")) require.NoError(t, err) return &mockProvider{retM: cfgMap, errW: configsource.ErrSessionClosed} }() + set := newDefaultConfigProviderSettings() + set.Locations = []string{"mock:"} + set.MapProviders[mapProvider.Scheme()] = mapProvider + watcherWG := sync.WaitGroup{} - cfgW := MustNewConfigProvider( - []string{"watcher:"}, - map[string]config.MapProvider{"watcher": configMapProvider}, - nil, - configunmarshaler.NewDefault()) + cfgW, err := NewConfigProvider(set) _, errN := cfgW.Get(context.Background(), factories) + require.NoError(t, err) + assert.NoError(t, errN) watcherWG.Add(1) @@ -322,8 +380,11 @@ func TestBackwardsCompatibilityForFilePath(t *testing.T) { }, } for _, tt := range tests { - provider := MustNewDefaultConfigProvider([]string{tt.location}, []string{}) - _, err := provider.Get(context.Background(), factories) + set := newDefaultConfigProviderSettings() + set.Locations = []string{tt.location} + provider, err := NewConfigProvider(set) + assert.NoError(t, err) + _, err = provider.Get(context.Background(), factories) assert.Contains(t, err.Error(), tt.errMessage, tt.name) }