Skip to content

Commit

Permalink
Change deprecated NewConfigProvider to use options and do input valid…
Browse files Browse the repository at this point in the history
…ation

Signed-off-by: Bogdan Drutu <[email protected]>
  • Loading branch information
bogdandrutu committed Mar 21, 2022
1 parent 1d2b265 commit 9d89a66
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 60 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

### 🚩 Deprecations 🚩

- Deprecate `service.MustNewConfigProvider` and `service.MustNewDefaultConfigProvider`in favor of `service.NewConfigProvider` (#4762)
- API related to `pdata.AttributeValue` is deprecated in favor of `pdata.Value` (#4975)
- `pdata.AttributeValue` struct is deprecated in favor of `pdata.Value`
- `pdata.AttributeValueType` type is deprecated in favor of `pdata.ValueType`
Expand Down
66 changes: 49 additions & 17 deletions service/collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/configmapprovider"
"go.opentelemetry.io/collector/internal/testcomponents"
"go.opentelemetry.io/collector/internal/testutil"
"go.opentelemetry.io/collector/service/featuregate"
Expand All @@ -60,11 +62,17 @@ func TestCollector_StartAsGoRoutine(t *testing.T) {
factories, err := testcomponents.NewDefaultFactories()
require.NoError(t, err)

cfgProvider, err := NewConfigProvider(
[]string{
filepath.Join("testdata", "otelcol-config.yaml"),
"yaml:service::telemetry::metrics::address: localhost:" + strconv.FormatUint(uint64(testutil.GetAvailablePort(t)), 10),
})
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)
Expand Down Expand Up @@ -98,12 +106,19 @@ func testCollectorStartHelper(t *testing.T) {
}

metricsPort := testutil.GetAvailablePort(t)
cfgProvider, err := NewConfigProvider(
[]string{filepath.Join("testdata", "otelcol-config.yaml")},
WithConfigMapConverters([]config.MapConverterFunc{
configmapprovider.NewOverwritePropertiesConverter(
[]string{"service.telemetry.metrics.address=localhost:" + strconv.FormatUint(uint64(metricsPort), 10)},
),
}))
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)
Expand Down Expand Up @@ -169,10 +184,13 @@ func TestCollector_ShutdownNoop(t *testing.T) {
factories, err := testcomponents.NewDefaultFactories()
require.NoError(t, err)

cfgProvider, err := NewConfigProvider([]string{filepath.Join("testdata", "otelcol-config.yaml")})
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)
Expand All @@ -190,10 +208,13 @@ func TestCollector_ShutdownBeforeRun(t *testing.T) {
factories, err := testcomponents.NewDefaultFactories()
require.NoError(t, err)

cfgProvider, err := NewConfigProvider([]string{filepath.Join("testdata", "otelcol-config.yaml")})
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)
Expand Down Expand Up @@ -221,11 +242,14 @@ func TestCollector_ClosedStateOnStartUpError(t *testing.T) {
factories, err := testcomponents.NewDefaultFactories()
require.NoError(t, err)

cfgProvider, err := NewConfigProvider([]string{filepath.Join("testdata", "otelcol-config.yaml")})
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)
Expand Down Expand Up @@ -256,10 +280,13 @@ func TestCollector_ReportError(t *testing.T) {
factories, err := testcomponents.NewDefaultFactories()
require.NoError(t, err)

cfgProvider, err := NewConfigProvider([]string{filepath.Join("testdata", "otelcol-config.yaml")})
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)

Expand Down Expand Up @@ -288,11 +315,16 @@ func TestCollector_ContextCancel(t *testing.T) {
factories, err := testcomponents.NewDefaultFactories()
require.NoError(t, err)

cfgProvider, err := NewConfigProvider([]string{
filepath.Join("testdata", "otelcol-config.yaml"),
"yaml:service::telemetry::metrics::address: localhost:" + strconv.FormatUint(uint64(testutil.GetAvailablePort(t)), 10),
})
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)
Expand Down
11 changes: 10 additions & 1 deletion service/collector_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import (
"go.uber.org/zap/zapcore"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/eventlog"

"go.opentelemetry.io/collector/config"
"go.opentelemetry.io/collector/config/configmapprovider"
)

type WindowsService struct {
Expand Down Expand Up @@ -134,7 +137,13 @@ 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
set.ConfigProvider, err = NewConfigProvider(
getConfigFlag(),
WithConfigMapConverters([]config.MapConverterFunc{configmapprovider.NewOverwritePropertiesConverter(getSetFlag())}))
if err != nil {
return nil, err
}
}
set.LoggingOptions = append(
set.LoggingOptions,
Expand Down
10 changes: 9 additions & 1 deletion service/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/configmapprovider"
"go.opentelemetry.io/collector/service/featuregate"
)

Expand All @@ -29,7 +31,13 @@ func NewCommand(set CollectorSettings) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
featuregate.Apply(featuregate.GetFlags())
if set.ConfigProvider == nil {
set.ConfigProvider = MustNewDefaultConfigProvider(getConfigFlag(), getSetFlag())
var err error
set.ConfigProvider, err = NewConfigProvider(
getConfigFlag(),
WithConfigMapConverters([]config.MapConverterFunc{configmapprovider.NewOverwritePropertiesConverter(getSetFlag())}))
if err != nil {
return err
}
}
col, err := New(set)
if err != nil {
Expand Down
104 changes: 78 additions & 26 deletions service/config_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,54 +65,106 @@ type ConfigProvider interface {
}

type configProvider struct {
locations []string
configMapProviders map[string]configmapprovider.Provider
cfgMapConverters []config.MapConverterFunc
configUnmarshaler configunmarshaler.ConfigUnmarshaler
locations []string
configMapProviders map[string]configmapprovider.Provider
configMapConverters []config.MapConverterFunc
configUnmarshaler configunmarshaler.ConfigUnmarshaler

sync.Mutex
closer configmapprovider.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 configmapprovider.Provider in order.
// * Then applies all the ConfigMapConverterFunc in the given order.
// * Then unmarshalls the final config.Config using the given configunmarshaler.ConfigUnmarshaler.
// ConfigProviderOption is an option to change the behavior of ConfigProvider
// returned by NewConfigProvider()
type ConfigProviderOption func(opts *configProvider)

// WithConfigMapProviders overwrites the default available providers.
//
// The `configMapProviders` is a map of pairs <scheme,Provider>.
func WithConfigMapProviders(c map[string]configmapprovider.Provider) ConfigProviderOption {
return func(opts *configProvider) {
opts.configMapProviders = c
}
}

// WithConfigMapConverters overwrites the default converters.
func WithConfigMapConverters(c []config.MapConverterFunc) ConfigProviderOption {
return func(opts *configProvider) {
opts.configMapConverters = c
}
}

// WithConfigUnmarshaler overwrites the default unmarshaler.
func WithConfigUnmarshaler(c configunmarshaler.ConfigUnmarshaler) ConfigProviderOption {
return func(opts *configProvider) {
opts.configUnmarshaler = c
}
}

// Deprecated: [v0.48.0] use NewConfigProvider instead.
func MustNewConfigProvider(
locations []string,
configMapProviders map[string]configmapprovider.Provider,
cfgMapConverters []config.MapConverterFunc,
configUnmarshaler configunmarshaler.ConfigUnmarshaler) ConfigProvider {
cfgProvider, err := NewConfigProvider(
locations,
WithConfigMapProviders(configMapProviders),
WithConfigMapConverters(cfgMapConverters),
WithConfigUnmarshaler(configUnmarshaler))
if err != nil {
panic(err)
}
return cfgProvider
}

// NewConfigProvider returns a new ConfigProvider that provides the configuration:
// * Retrieve the config.Map by merging all retrieved maps from all the configmapprovider.Provider in order.
// * Then applies all the config.MapConverterFunc in the given order.
// * Then unmarshalls the final config.Config using the given configunmarshaler.ConfigUnmarshaler.
func NewConfigProvider(locations []string, opts ...ConfigProviderOption) (ConfigProvider, error) {
if len(locations) == 0 {
return nil, fmt.Errorf("cannot create ConfigProvider: no locations provided")
}
// 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),
}
}

// 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,
map[string]configmapprovider.Provider{
provider := configProvider{
locations: locationsCopy,
configMapProviders: map[string]configmapprovider.Provider{
"file": configmapprovider.NewFile(),
"env": configmapprovider.NewEnv(),
"yaml": configmapprovider.NewYAML(),
},
[]config.MapConverterFunc{
configmapprovider.NewOverwritePropertiesConverter(properties),
configMapConverters: []config.MapConverterFunc{
configmapprovider.NewExpandConverter(),
},
configunmarshaler.NewDefault())
configUnmarshaler: configunmarshaler.NewDefault(),
watcher: make(chan error, 1),
}

// Override default values with user options
for _, o := range opts {
o(&provider)
}

return &provider, nil
}

// Deprecated: [v0.48.0] use NewConfigProvider instead.
func MustNewDefaultConfigProvider(configLocations []string, properties []string) ConfigProvider {
cfgProvider, err := NewConfigProvider(
configLocations,
WithConfigMapConverters([]config.MapConverterFunc{
configmapprovider.NewOverwritePropertiesConverter(properties),
configmapprovider.NewExpandConverter(),
}))
if err != nil {
panic(err)
}
return cfgProvider
}

func (cm *configProvider) Get(ctx context.Context, factories component.Factories) (*config.Config, error) {
Expand All @@ -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)
}
Expand Down
Loading

0 comments on commit 9d89a66

Please sign in to comment.