[confmap] Add converter and provider settings to confmap.ResolverSettings (#9516)
**Description:** Follows https://github.com/open-telemetry/opentelemetry-collector/pull/9443, relates to https://github.com/open-telemetry/opentelemetry-collector/pull/9513. This builds on https://github.com/open-telemetry/opentelemetry-collector/pull/9228 to demonstrate the concept. This shows one way of extending the otelcol APIs to allow passing converters and providers from the builder with the new settings structs for each type. I think this approach has a few advantages: 1. This follows our pattern of passing in "factory" functions instead of instances to the object that actually uses the instances. 2. Makes the API more declarative: the settings specify which modules to instantiate and which settings to instantiate them with, but don't require the caller to actually do this. 3. Compared to the current state, this allows us to update the config at different layers. A distribution's `main.go` file can specify the providers/converters it wants and leave the settings to be created by `otelcol.Collector`. The primary drawbacks I see here are: 1. This is a little more opinionated since you don't have access to the converter/provider instances or control how they are instantiated. I think this is acceptable and provides good encapsulation. 2. The scheme->provider map can now only be specified by the providers' schemes, which is how it is currently done by default. I would want to hear what use cases we see for more complex control here that necessitates using schemes not specified by the providers. cc @mx-psi --------- Co-authored-by: Evan Bradley <evan-bradley@users.noreply.github.com>
This commit is contained in:
parent
29b9b5593d
commit
2108ae88f5
|
|
@ -0,0 +1,25 @@
|
|||
# Use this changelog template to create an entry for release notes.
|
||||
|
||||
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
|
||||
change_type: enhancement
|
||||
|
||||
# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
|
||||
component: confmap
|
||||
|
||||
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
|
||||
note: Add `ProviderSettings`, `ConverterSettings`, `ProviderFactories`, and `ConverterFactories` fields to `confmap.ResolverSettings`
|
||||
|
||||
# One or more tracking issues or pull requests related to the change
|
||||
issues: [9516]
|
||||
|
||||
# (Optional) One or more lines of additional information to render under the primary note.
|
||||
# These lines will be padded with 2 spaces and then inserted directly into the document.
|
||||
# Use pipe (|) for multiline entries.
|
||||
subtext: This allows configuring providers and converters, which are instantiated by `NewResolver` using the given factories.
|
||||
|
||||
# Optional: The change log or logs in which this entry should be included.
|
||||
# e.g. '[user]' or '[user, api]'
|
||||
# Include 'user' if the change is relevant to end users.
|
||||
# Include 'api' if there is a change to a library API.
|
||||
# Default: '[user]'
|
||||
change_logs: []
|
||||
|
|
@ -256,7 +256,7 @@ type templateContext struct {
|
|||
}
|
||||
|
||||
func loadMetadata(filePath string) (metadata, error) {
|
||||
cp, err := fileprovider.NewWithSettings(confmaptest.NewNopProviderSettings()).Retrieve(context.Background(), "file:"+filePath, nil)
|
||||
cp, err := fileprovider.NewFactory().Create(confmaptest.NewNopProviderSettings()).Retrieve(context.Background(), "file:"+filePath, nil)
|
||||
if err != nil {
|
||||
return metadata{}, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -417,3 +417,23 @@ func zeroSliceHookFunc() mapstructure.DecodeHookFuncValue {
|
|||
return from.Interface(), nil
|
||||
}
|
||||
}
|
||||
|
||||
type moduleFactory[T any, S any] interface {
|
||||
Create(s S) T
|
||||
}
|
||||
|
||||
type createConfmapFunc[T any, S any] func(s S) T
|
||||
|
||||
type confmapModuleFactory[T any, S any] struct {
|
||||
f createConfmapFunc[T, S]
|
||||
}
|
||||
|
||||
func (c confmapModuleFactory[T, S]) Create(s S) T {
|
||||
return c.f(s)
|
||||
}
|
||||
|
||||
func newConfmapModuleFactory[T any, S any](f createConfmapFunc[T, S]) moduleFactory[T, S] {
|
||||
return confmapModuleFactory[T, S]{
|
||||
f: f,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,20 @@ import (
|
|||
)
|
||||
|
||||
// ConverterSettings are the settings to initialize a Converter.
|
||||
// Any Converter should take this as a parameter in its constructor.
|
||||
type ConverterSettings struct{}
|
||||
|
||||
// ConverterFactory defines a factory that can be used to instantiate
|
||||
// new instances of a Converter.
|
||||
type ConverterFactory = moduleFactory[Converter, ConverterSettings]
|
||||
|
||||
// CreateConverterFunc is a function that creates a Converter instance.
|
||||
type CreateConverterFunc = createConfmapFunc[Converter, ConverterSettings]
|
||||
|
||||
// NewConverterFactory can be used to create a ConverterFactory.
|
||||
func NewConverterFactory(f CreateConverterFunc) ConverterFactory {
|
||||
return newConfmapModuleFactory(f)
|
||||
}
|
||||
|
||||
// Converter is a converter interface for the confmap.Conf that allows distributions
|
||||
// (in the future components as well) to build backwards compatible config converters.
|
||||
type Converter interface {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ type converter struct {
|
|||
// New returns a confmap.Converter, that expands all environment variables for a given confmap.Conf.
|
||||
//
|
||||
// Notice: This API is experimental.
|
||||
//
|
||||
// Deprecated: [v0.99.0] Use NewFactory instead.
|
||||
func New(_ confmap.ConverterSettings) confmap.Converter {
|
||||
return converter{
|
||||
loggedDeprecations: make(map[string]struct{}),
|
||||
|
|
@ -31,6 +33,12 @@ func New(_ confmap.ConverterSettings) confmap.Converter {
|
|||
}
|
||||
}
|
||||
|
||||
// NewFactory returns a factory for a confmap.Converter,
|
||||
// which expands all environment variables for a given confmap.Conf.
|
||||
func NewFactory() confmap.ConverterFactory {
|
||||
return confmap.NewConverterFactory(New)
|
||||
}
|
||||
|
||||
func (c converter) Convert(_ context.Context, conf *confmap.Conf) error {
|
||||
out := make(map[string]any)
|
||||
for _, k := range conf.AllKeys() {
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ func TestNewExpandConverter(t *testing.T) {
|
|||
require.NoError(t, err, "Unable to get config")
|
||||
|
||||
// Test that expanded configs are the same with the simple config with no env vars.
|
||||
require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf))
|
||||
require.NoError(t, createConverter().Convert(context.Background(), conf))
|
||||
assert.Equal(t, expectedCfgMap.ToStringMap(), conf.ToStringMap())
|
||||
})
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ func TestNewExpandConverter_EscapedMaps(t *testing.T) {
|
|||
"recv": "$MAP_VALUE",
|
||||
}},
|
||||
)
|
||||
require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf))
|
||||
require.NoError(t, createConverter().Convert(context.Background(), conf))
|
||||
|
||||
expectedMap := map[string]any{
|
||||
"test_string_map": map[string]any{
|
||||
|
|
@ -105,7 +105,7 @@ func TestNewExpandConverter_EscapedEnvVars(t *testing.T) {
|
|||
// escaped $ alone
|
||||
"recv.7": "$",
|
||||
}}
|
||||
require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf))
|
||||
require.NoError(t, createConverter().Convert(context.Background(), conf))
|
||||
assert.Equal(t, expectedMap, conf.ToStringMap())
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ func TestNewExpandConverterHostPort(t *testing.T) {
|
|||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
conf := confmap.NewFromStringMap(tt.input)
|
||||
require.NoError(t, New(confmap.ConverterSettings{}).Convert(context.Background(), conf))
|
||||
require.NoError(t, createConverter().Convert(context.Background(), conf))
|
||||
assert.Equal(t, tt.expected, conf.ToStringMap())
|
||||
})
|
||||
}
|
||||
|
|
@ -252,3 +252,7 @@ func TestDeprecatedWarning(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createConverter() confmap.Converter {
|
||||
return NewFactory().Create(confmap.ConverterSettings{})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func TestResolverExpandEnvVars(t *testing.T) {
|
|||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{filepath.Join("testdata", test.name)}, Providers: makeMapProvidersMap(fileProvider, envProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{filepath.Join("testdata", test.name)}, ProviderFactories: []ProviderFactory{fileProvider, envProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test that expanded configs are the same with the simple config with no env vars.
|
||||
|
|
@ -65,7 +65,7 @@ func TestResolverDoneNotExpandOldEnvVars(t *testing.T) {
|
|||
return NewRetrieved("some string")
|
||||
})
|
||||
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"test:"}, Providers: makeMapProvidersMap(fileProvider, envProvider, emptySchemeProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"test:"}, ProviderFactories: []ProviderFactory{fileProvider, envProvider, emptySchemeProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test that expanded configs are the same with the simple config with no env vars.
|
||||
|
|
@ -86,7 +86,7 @@ func TestResolverExpandMapAndSliceValues(t *testing.T) {
|
|||
return NewRetrieved(receiverExtraMapValue)
|
||||
})
|
||||
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
cfgMap, err := resolver.Resolve(context.Background())
|
||||
|
|
@ -295,7 +295,7 @@ func TestResolverExpandStringValues(t *testing.T) {
|
|||
return NewRetrieved(uri[5:])
|
||||
})
|
||||
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, newEnvProvider(), testProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, newEnvProvider(), testProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
cfgMap, err := resolver.Resolve(context.Background())
|
||||
|
|
@ -305,7 +305,7 @@ func TestResolverExpandStringValues(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func newEnvProvider() Provider {
|
||||
func newEnvProvider() ProviderFactory {
|
||||
return newFakeProvider("env", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) {
|
||||
switch uri {
|
||||
case "env:COMPLEX_VALUE":
|
||||
|
|
@ -369,7 +369,7 @@ func TestResolverExpandReturnError(t *testing.T) {
|
|||
return nil, myErr
|
||||
})
|
||||
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = resolver.Resolve(context.Background())
|
||||
|
|
@ -388,7 +388,7 @@ func TestResolverInfiniteExpand(t *testing.T) {
|
|||
return NewRetrieved(receiverValue)
|
||||
})
|
||||
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = resolver.Resolve(context.Background())
|
||||
|
|
@ -404,7 +404,7 @@ func TestResolverExpandInvalidScheme(t *testing.T) {
|
|||
panic("must not be called")
|
||||
})
|
||||
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = resolver.Resolve(context.Background())
|
||||
|
|
@ -421,7 +421,7 @@ func TestResolverExpandInvalidOpaqueValue(t *testing.T) {
|
|||
panic("must not be called")
|
||||
})
|
||||
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = resolver.Resolve(context.Background())
|
||||
|
|
@ -437,7 +437,7 @@ func TestResolverExpandUnsupportedScheme(t *testing.T) {
|
|||
panic("must not be called")
|
||||
})
|
||||
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = resolver.Resolve(context.Background())
|
||||
|
|
@ -453,7 +453,7 @@ func TestResolverExpandStringValueInvalidReturnValue(t *testing.T) {
|
|||
return NewRetrieved([]any{1243})
|
||||
})
|
||||
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, Providers: makeMapProvidersMap(provider, testProvider), Converters: nil})
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: []string{"input:"}, ProviderFactories: []ProviderFactory{provider, testProvider}, ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = resolver.Resolve(context.Background())
|
||||
|
|
|
|||
|
|
@ -11,11 +11,26 @@ import (
|
|||
)
|
||||
|
||||
// ProviderSettings are the settings to initialize a Provider.
|
||||
// Any Provider should take this as a parameter in its constructor.
|
||||
type ProviderSettings struct {
|
||||
// Logger is a zap.Logger that will be passed to Providers.
|
||||
// Providers should be able to rely on the Logger being non-nil;
|
||||
// when instantiating a Provider with a ProviderFactory,
|
||||
// nil Logger references should be replaced with a no-op Logger.
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
// ProviderFactory defines a factory that can be used to instantiate
|
||||
// new instances of a Provider.
|
||||
type ProviderFactory = moduleFactory[Provider, ProviderSettings]
|
||||
|
||||
// CreateProviderFunc is a function that creates a Provider instance.
|
||||
type CreateProviderFunc = createConfmapFunc[Provider, ProviderSettings]
|
||||
|
||||
// NewProviderFactory can be used to create a ProviderFactory.
|
||||
func NewProviderFactory(f CreateProviderFunc) ProviderFactory {
|
||||
return newConfmapModuleFactory(f)
|
||||
}
|
||||
|
||||
// Provider is an interface that helps to retrieve a config map and watch for any
|
||||
// changes to the config map. Implementations may load the config from a file,
|
||||
// a database or any other source.
|
||||
|
|
|
|||
|
|
@ -25,12 +25,22 @@ type provider struct {
|
|||
//
|
||||
// This Provider supports "env" scheme, and can be called with a selector:
|
||||
// `env:NAME_OF_ENVIRONMENT_VARIABLE`
|
||||
//
|
||||
// Deprecated: [v0.99.0] Use NewFactory instead.
|
||||
func NewWithSettings(ps confmap.ProviderSettings) confmap.Provider {
|
||||
return &provider{
|
||||
logger: ps.Logger,
|
||||
}
|
||||
}
|
||||
|
||||
// NewFactory returns a factory for a confmap.Provider that reads the configuration from the given environment variable.
|
||||
//
|
||||
// This Provider supports "env" scheme, and can be called with a selector:
|
||||
// `env:NAME_OF_ENVIRONMENT_VARIABLE`
|
||||
func NewFactory() confmap.ProviderFactory {
|
||||
return confmap.NewProviderFactory(NewWithSettings)
|
||||
}
|
||||
|
||||
func (emp *provider) Retrieve(_ context.Context, uri string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) {
|
||||
if !strings.HasPrefix(uri, schemeName+":") {
|
||||
return nil, fmt.Errorf("%q uri is not supported by %q provider", uri, schemeName)
|
||||
|
|
|
|||
|
|
@ -27,18 +27,18 @@ exporters:
|
|||
`
|
||||
|
||||
func TestValidateProviderScheme(t *testing.T) {
|
||||
assert.NoError(t, confmaptest.ValidateProviderScheme(NewWithSettings(confmaptest.NewNopProviderSettings())))
|
||||
assert.NoError(t, confmaptest.ValidateProviderScheme(createProvider()))
|
||||
}
|
||||
|
||||
func TestEmptyName(t *testing.T) {
|
||||
env := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
env := createProvider()
|
||||
_, err := env.Retrieve(context.Background(), "", nil)
|
||||
require.Error(t, err)
|
||||
assert.NoError(t, env.Shutdown(context.Background()))
|
||||
}
|
||||
|
||||
func TestUnsupportedScheme(t *testing.T) {
|
||||
env := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
env := createProvider()
|
||||
_, err := env.Retrieve(context.Background(), "https://", nil)
|
||||
assert.Error(t, err)
|
||||
assert.NoError(t, env.Shutdown(context.Background()))
|
||||
|
|
@ -47,7 +47,7 @@ func TestUnsupportedScheme(t *testing.T) {
|
|||
func TestInvalidYAML(t *testing.T) {
|
||||
const envName = "invalid-yaml"
|
||||
t.Setenv(envName, "[invalid,")
|
||||
env := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
env := createProvider()
|
||||
_, err := env.Retrieve(context.Background(), envSchemePrefix+envName, nil)
|
||||
assert.Error(t, err)
|
||||
assert.NoError(t, env.Shutdown(context.Background()))
|
||||
|
|
@ -57,7 +57,7 @@ func TestEnv(t *testing.T) {
|
|||
const envName = "default-config"
|
||||
t.Setenv(envName, validYAML)
|
||||
|
||||
env := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
env := createProvider()
|
||||
ret, err := env.Retrieve(context.Background(), envSchemePrefix+envName, nil)
|
||||
require.NoError(t, err)
|
||||
retMap, err := ret.AsConf()
|
||||
|
|
@ -137,3 +137,7 @@ func TestEmptyEnvWithLoggerWarn(t *testing.T) {
|
|||
assert.Equal(t, zap.InfoLevel, logLine.Level)
|
||||
assert.Equal(t, envName, logLine.Context[0].String)
|
||||
}
|
||||
|
||||
func createProvider() confmap.Provider {
|
||||
return NewFactory().Create(confmaptest.NewNopProviderSettings())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,10 +33,31 @@ type provider struct{}
|
|||
// `file:/path/to/file` - absolute path (unix, windows)
|
||||
// `file:c:/path/to/file` - absolute path including drive-letter (windows)
|
||||
// `file:c:\path\to\file` - absolute path including drive-letter (windows)
|
||||
//
|
||||
// Deprecated: [v0.99.0] Use NewFactory instead.
|
||||
func NewWithSettings(confmap.ProviderSettings) confmap.Provider {
|
||||
return &provider{}
|
||||
}
|
||||
|
||||
// NewFactory returns a factory for a confmap.Provider that reads the configuration from a file.
|
||||
//
|
||||
// This Provider supports "file" scheme, and can be called with a "uri" that follows:
|
||||
//
|
||||
// file-uri = "file:" local-path
|
||||
// local-path = [ drive-letter ] file-path
|
||||
// drive-letter = ALPHA ":"
|
||||
//
|
||||
// The "file-path" can be relative or absolute, and it can be any OS supported format.
|
||||
//
|
||||
// Examples:
|
||||
// `file:path/to/file` - relative path (unix, windows)
|
||||
// `file:/path/to/file` - absolute path (unix, windows)
|
||||
// `file:c:/path/to/file` - absolute path including drive-letter (windows)
|
||||
// `file:c:\path\to\file` - absolute path including drive-letter (windows)
|
||||
func NewFactory() confmap.ProviderFactory {
|
||||
return confmap.NewProviderFactory(NewWithSettings)
|
||||
}
|
||||
|
||||
func (fmp *provider) Retrieve(_ context.Context, uri string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) {
|
||||
if !strings.HasPrefix(uri, schemeName+":") {
|
||||
return nil, fmt.Errorf("%q uri is not supported by %q provider", uri, schemeName)
|
||||
|
|
|
|||
|
|
@ -19,25 +19,25 @@ import (
|
|||
const fileSchemePrefix = schemeName + ":"
|
||||
|
||||
func TestValidateProviderScheme(t *testing.T) {
|
||||
assert.NoError(t, confmaptest.ValidateProviderScheme(NewWithSettings(confmaptest.NewNopProviderSettings())))
|
||||
assert.NoError(t, confmaptest.ValidateProviderScheme(createProvider()))
|
||||
}
|
||||
|
||||
func TestEmptyName(t *testing.T) {
|
||||
fp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
fp := createProvider()
|
||||
_, err := fp.Retrieve(context.Background(), "", nil)
|
||||
require.Error(t, err)
|
||||
require.NoError(t, fp.Shutdown(context.Background()))
|
||||
}
|
||||
|
||||
func TestUnsupportedScheme(t *testing.T) {
|
||||
fp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
fp := createProvider()
|
||||
_, err := fp.Retrieve(context.Background(), "https://", nil)
|
||||
assert.Error(t, err)
|
||||
assert.NoError(t, fp.Shutdown(context.Background()))
|
||||
}
|
||||
|
||||
func TestNonExistent(t *testing.T) {
|
||||
fp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
fp := createProvider()
|
||||
_, err := fp.Retrieve(context.Background(), fileSchemePrefix+filepath.Join("testdata", "non-existent.yaml"), nil)
|
||||
assert.Error(t, err)
|
||||
_, err = fp.Retrieve(context.Background(), fileSchemePrefix+absolutePath(t, filepath.Join("testdata", "non-existent.yaml")), nil)
|
||||
|
|
@ -46,7 +46,7 @@ func TestNonExistent(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestInvalidYAML(t *testing.T) {
|
||||
fp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
fp := createProvider()
|
||||
_, err := fp.Retrieve(context.Background(), fileSchemePrefix+filepath.Join("testdata", "invalid-yaml.yaml"), nil)
|
||||
assert.Error(t, err)
|
||||
_, err = fp.Retrieve(context.Background(), fileSchemePrefix+absolutePath(t, filepath.Join("testdata", "invalid-yaml.yaml")), nil)
|
||||
|
|
@ -55,7 +55,7 @@ func TestInvalidYAML(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRelativePath(t *testing.T) {
|
||||
fp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
fp := createProvider()
|
||||
ret, err := fp.Retrieve(context.Background(), fileSchemePrefix+filepath.Join("testdata", "default-config.yaml"), nil)
|
||||
require.NoError(t, err)
|
||||
retMap, err := ret.AsConf()
|
||||
|
|
@ -69,7 +69,7 @@ func TestRelativePath(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAbsolutePath(t *testing.T) {
|
||||
fp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
fp := createProvider()
|
||||
ret, err := fp.Retrieve(context.Background(), fileSchemePrefix+absolutePath(t, filepath.Join("testdata", "default-config.yaml")), nil)
|
||||
require.NoError(t, err)
|
||||
retMap, err := ret.AsConf()
|
||||
|
|
@ -87,3 +87,7 @@ func absolutePath(t *testing.T, relativePath string) string {
|
|||
require.NoError(t, err)
|
||||
return filepath.Join(dir, relativePath)
|
||||
}
|
||||
|
||||
func createProvider() confmap.Provider {
|
||||
return NewFactory().Create(confmaptest.NewNopProviderSettings())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,17 @@ import (
|
|||
// This Provider supports "http" scheme.
|
||||
//
|
||||
// One example for HTTP URI is: http://localhost:3333/getConfig
|
||||
//
|
||||
// Deprecated: [v0.99.0] Use NewFactory instead.
|
||||
func NewWithSettings(set confmap.ProviderSettings) confmap.Provider {
|
||||
return configurablehttpprovider.New(configurablehttpprovider.HTTPScheme, set)
|
||||
}
|
||||
|
||||
// NewFactory returns a factory for a confmap.Provider that reads the configuration from a http server.
|
||||
//
|
||||
// This Provider supports "http" scheme.
|
||||
//
|
||||
// One example for HTTP URI is: http://localhost:3333/getConfig
|
||||
func NewFactory() confmap.ProviderFactory {
|
||||
return confmap.NewProviderFactory(NewWithSettings)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import (
|
|||
)
|
||||
|
||||
func TestSupportedScheme(t *testing.T) {
|
||||
fp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
fp := NewFactory().Create(confmaptest.NewNopProviderSettings())
|
||||
assert.Equal(t, "http", fp.Scheme())
|
||||
require.NoError(t, fp.Shutdown(context.Background()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,24 @@ import (
|
|||
"go.opentelemetry.io/collector/confmap/provider/internal/configurablehttpprovider"
|
||||
)
|
||||
|
||||
// New returns a new confmap.Provider that reads the configuration from a https server.
|
||||
// NewWithSettings returns a new confmap.Provider that reads the configuration from a https server.
|
||||
//
|
||||
// This Provider supports "https" scheme. One example of an HTTPS URI is: https://localhost:3333/getConfig
|
||||
//
|
||||
// To add extra CA certificates you need to install certificates in the system pool. This procedure is operating system
|
||||
// dependent. E.g.: on Linux please refer to the `update-ca-trust` command.
|
||||
//
|
||||
// Deprecated: [v0.99.0] Use NewFactory instead.
|
||||
func NewWithSettings(set confmap.ProviderSettings) confmap.Provider {
|
||||
return configurablehttpprovider.New(configurablehttpprovider.HTTPSScheme, set)
|
||||
}
|
||||
|
||||
// NewFactory returns a factory for a confmap.Provider that reads the configuration from a https server.
|
||||
//
|
||||
// This Provider supports "https" scheme. One example of an HTTPS URI is: https://localhost:3333/getConfig
|
||||
//
|
||||
// To add extra CA certificates you need to install certificates in the system pool. This procedure is operating system
|
||||
// dependent. E.g.: on Linux please refer to the `update-ca-trust` command.
|
||||
func NewFactory() confmap.ProviderFactory {
|
||||
return confmap.NewProviderFactory(NewWithSettings)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ import (
|
|||
)
|
||||
|
||||
func TestSupportedScheme(t *testing.T) {
|
||||
fp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
fp := NewFactory().Create(confmaptest.NewNopProviderSettings())
|
||||
assert.Equal(t, "https", fp.Scheme())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,10 +25,25 @@ type provider struct{}
|
|||
// Examples:
|
||||
// `yaml:processors::batch::timeout: 2s`
|
||||
// `yaml:processors::batch/foo::timeout: 3s`
|
||||
//
|
||||
// Deprecated: [v0.99.0] Use NewFactory instead.
|
||||
func NewWithSettings(confmap.ProviderSettings) confmap.Provider {
|
||||
return &provider{}
|
||||
}
|
||||
|
||||
// NewFactory returns a factory for a confmap.Provider that allows to provide yaml bytes.
|
||||
//
|
||||
// This Provider supports "yaml" scheme, and can be called with a "uri" that follows:
|
||||
//
|
||||
// bytes-uri = "yaml:" yaml-bytes
|
||||
//
|
||||
// Examples:
|
||||
// `yaml:processors::batch::timeout: 2s`
|
||||
// `yaml:processors::batch/foo::timeout: 3s`
|
||||
func NewFactory() confmap.ProviderFactory {
|
||||
return confmap.NewProviderFactory(NewWithSettings)
|
||||
}
|
||||
|
||||
func (s *provider) Retrieve(_ context.Context, uri string, _ confmap.WatcherFunc) (*confmap.Retrieved, error) {
|
||||
if !strings.HasPrefix(uri, schemeName+":") {
|
||||
return nil, fmt.Errorf("%q uri is not supported by %q provider", uri, schemeName)
|
||||
|
|
|
|||
|
|
@ -9,29 +9,30 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"go.opentelemetry.io/collector/confmap"
|
||||
"go.opentelemetry.io/collector/confmap/confmaptest"
|
||||
)
|
||||
|
||||
func TestValidateProviderScheme(t *testing.T) {
|
||||
assert.NoError(t, confmaptest.ValidateProviderScheme(NewWithSettings(confmaptest.NewNopProviderSettings())))
|
||||
assert.NoError(t, confmaptest.ValidateProviderScheme(createProvider()))
|
||||
}
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
sp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
sp := createProvider()
|
||||
_, err := sp.Retrieve(context.Background(), "", nil)
|
||||
assert.Error(t, err)
|
||||
assert.NoError(t, sp.Shutdown(context.Background()))
|
||||
}
|
||||
|
||||
func TestInvalidYAML(t *testing.T) {
|
||||
sp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
sp := createProvider()
|
||||
_, err := sp.Retrieve(context.Background(), "yaml:[invalid,", nil)
|
||||
assert.Error(t, err)
|
||||
assert.NoError(t, sp.Shutdown(context.Background()))
|
||||
}
|
||||
|
||||
func TestOneValue(t *testing.T) {
|
||||
sp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
sp := createProvider()
|
||||
ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch::timeout: 2s", nil)
|
||||
assert.NoError(t, err)
|
||||
retMap, err := ret.AsConf()
|
||||
|
|
@ -47,7 +48,7 @@ func TestOneValue(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNamedComponent(t *testing.T) {
|
||||
sp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
sp := createProvider()
|
||||
ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch/foo::timeout: 3s", nil)
|
||||
assert.NoError(t, err)
|
||||
retMap, err := ret.AsConf()
|
||||
|
|
@ -63,7 +64,7 @@ func TestNamedComponent(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMapEntry(t *testing.T) {
|
||||
sp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
sp := createProvider()
|
||||
ret, err := sp.Retrieve(context.Background(), "yaml:processors: {batch/foo::timeout: 3s, batch::timeout: 2s}", nil)
|
||||
assert.NoError(t, err)
|
||||
retMap, err := ret.AsConf()
|
||||
|
|
@ -82,7 +83,7 @@ func TestMapEntry(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArrayEntry(t *testing.T) {
|
||||
sp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
sp := createProvider()
|
||||
ret, err := sp.Retrieve(context.Background(), "yaml:service::extensions: [zpages, zpages/foo]", nil)
|
||||
assert.NoError(t, err)
|
||||
retMap, err := ret.AsConf()
|
||||
|
|
@ -99,7 +100,7 @@ func TestArrayEntry(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNewLine(t *testing.T) {
|
||||
sp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
sp := createProvider()
|
||||
ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch/foo::timeout: 3s\nprocessors::batch::timeout: 2s", nil)
|
||||
assert.NoError(t, err)
|
||||
retMap, err := ret.AsConf()
|
||||
|
|
@ -118,7 +119,7 @@ func TestNewLine(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDotSeparator(t *testing.T) {
|
||||
sp := NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
sp := createProvider()
|
||||
ret, err := sp.Retrieve(context.Background(), "yaml:processors.batch.timeout: 4s", nil)
|
||||
assert.NoError(t, err)
|
||||
retMap, err := ret.AsConf()
|
||||
|
|
@ -126,3 +127,7 @@ func TestDotSeparator(t *testing.T) {
|
|||
assert.Equal(t, map[string]any{"processors.batch.timeout": "4s"}, retMap.ToStringMap())
|
||||
assert.NoError(t, sp.Shutdown(context.Background()))
|
||||
}
|
||||
|
||||
func createProvider() confmap.Provider {
|
||||
return NewFactory().Create(confmaptest.NewNopProviderSettings())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"go.uber.org/multierr"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// follows drive-letter specification:
|
||||
|
|
@ -33,12 +34,32 @@ type ResolverSettings struct {
|
|||
// It is required to have at least one location.
|
||||
URIs []string
|
||||
|
||||
// ProviderFactories is a list of Provider creation functions.
|
||||
// It is required to have at least one ProviderFactory
|
||||
// if a Provider is not given.
|
||||
ProviderFactories []ProviderFactory
|
||||
|
||||
// Providers is a map of pairs <scheme, Provider>.
|
||||
// It is required to have at least one Provider.
|
||||
//
|
||||
// Deprecated: [v0.99.0] Use ProviderFactories instead
|
||||
Providers map[string]Provider
|
||||
|
||||
// MapConverters is a slice of Converter.
|
||||
// ProviderSettings contains settings that will be passed to Provider
|
||||
// factories when instantiating Providers.
|
||||
ProviderSettings ProviderSettings
|
||||
|
||||
// ConverterFactories is a slice of Converter creation functions.
|
||||
ConverterFactories []ConverterFactory
|
||||
|
||||
// Converters is a slice of Converters.
|
||||
//
|
||||
// Deprecated: [v0.99.0] Use ConverterFactories instead
|
||||
Converters []Converter
|
||||
|
||||
// ConverterSettings contains settings that will be passed to Converter
|
||||
// factories when instantiating Converters.
|
||||
ConverterSettings ConverterSettings
|
||||
}
|
||||
|
||||
// NewResolver returns a new Resolver that resolves configuration from multiple URIs.
|
||||
|
|
@ -65,10 +86,42 @@ func NewResolver(set ResolverSettings) (*Resolver, error) {
|
|||
return nil, errors.New("invalid map resolver config: no URIs")
|
||||
}
|
||||
|
||||
if len(set.Providers) == 0 {
|
||||
if len(set.ProviderFactories) == 0 && len(set.Providers) == 0 {
|
||||
return nil, errors.New("invalid map resolver config: no Providers")
|
||||
}
|
||||
|
||||
if set.ProviderSettings.Logger == nil {
|
||||
set.ProviderSettings.Logger = zap.NewNop()
|
||||
}
|
||||
|
||||
var providers map[string]Provider
|
||||
var converters []Converter
|
||||
|
||||
if len(set.Providers) != 0 {
|
||||
if len(set.ProviderFactories) != 0 {
|
||||
return nil, errors.New("only one of ResolverSettings.Providers and ResolverSettings.ProviderFactories can be used")
|
||||
}
|
||||
providers = set.Providers
|
||||
} else {
|
||||
providers = make(map[string]Provider, len(set.ProviderFactories))
|
||||
for _, factory := range set.ProviderFactories {
|
||||
provider := factory.Create(set.ProviderSettings)
|
||||
providers[provider.Scheme()] = provider
|
||||
}
|
||||
}
|
||||
|
||||
if len(set.Converters) != 0 {
|
||||
if len(set.ConverterFactories) != 0 {
|
||||
return nil, errors.New("only one of ResolverSettings.Converters and ResolverSettings.ConverterFactories can be used")
|
||||
}
|
||||
converters = set.Converters
|
||||
} else {
|
||||
converters = make([]Converter, len(set.ConverterFactories))
|
||||
for i, factory := range set.ConverterFactories {
|
||||
converters[i] = factory.Create(set.ConverterSettings)
|
||||
}
|
||||
}
|
||||
|
||||
// Safe copy, ensures the slices and maps cannot be changed from the caller.
|
||||
uris := make([]location, len(set.URIs))
|
||||
for i, uri := range set.URIs {
|
||||
|
|
@ -83,22 +136,16 @@ func NewResolver(set ResolverSettings) (*Resolver, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := set.Providers[lURI.scheme]; !ok {
|
||||
if _, ok := providers[lURI.scheme]; !ok {
|
||||
return nil, fmt.Errorf("unsupported scheme on URI %q", uri)
|
||||
}
|
||||
uris[i] = lURI
|
||||
}
|
||||
providersCopy := make(map[string]Provider, len(set.Providers))
|
||||
for k, v := range set.Providers {
|
||||
providersCopy[k] = v
|
||||
}
|
||||
convertersCopy := make([]Converter, len(set.Converters))
|
||||
copy(convertersCopy, set.Converters)
|
||||
|
||||
return &Resolver{
|
||||
uris: uris,
|
||||
providers: providersCopy,
|
||||
converters: convertersCopy,
|
||||
providers: providers,
|
||||
converters: converters,
|
||||
watcher: make(chan error, 1),
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type mockProvider struct {
|
||||
|
|
@ -47,22 +48,49 @@ func (m *mockProvider) Shutdown(context.Context) error {
|
|||
return m.errS
|
||||
}
|
||||
|
||||
func newMockProvider(m *mockProvider) ProviderFactory {
|
||||
return NewProviderFactory(func(_ ProviderSettings) Provider {
|
||||
return m
|
||||
})
|
||||
}
|
||||
|
||||
type fakeProvider struct {
|
||||
scheme string
|
||||
ret func(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error)
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func newFileProvider(t testing.TB) Provider {
|
||||
func newFileProvider(t testing.TB) ProviderFactory {
|
||||
return newFakeProvider("file", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) {
|
||||
return NewRetrieved(newConfFromFile(t, uri[5:]))
|
||||
})
|
||||
}
|
||||
|
||||
func newFakeProvider(scheme string, ret func(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error)) Provider {
|
||||
return &fakeProvider{
|
||||
func newFakeProvider(scheme string, ret func(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error)) ProviderFactory {
|
||||
return NewProviderFactory(func(ps ProviderSettings) Provider {
|
||||
return &fakeProvider{
|
||||
scheme: scheme,
|
||||
ret: ret,
|
||||
logger: ps.Logger,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func newObservableFileProvider(t testing.TB) (ProviderFactory, *fakeProvider) {
|
||||
return newObservableProvider("file", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) {
|
||||
return NewRetrieved(newConfFromFile(t, uri[5:]))
|
||||
})
|
||||
}
|
||||
|
||||
func newObservableProvider(scheme string, ret func(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error)) (ProviderFactory, *fakeProvider) {
|
||||
fp := &fakeProvider{
|
||||
scheme: scheme,
|
||||
ret: ret,
|
||||
}
|
||||
return NewProviderFactory(func(ps ProviderSettings) Provider {
|
||||
fp.logger = ps.Logger
|
||||
return fp
|
||||
}), fp
|
||||
}
|
||||
|
||||
func (f *fakeProvider) Retrieve(ctx context.Context, uri string, watcher WatcherFunc) (*Retrieved, error) {
|
||||
|
|
@ -85,16 +113,8 @@ func (m *mockConverter) Convert(context.Context, *Conf) error {
|
|||
return errors.New("converter_err")
|
||||
}
|
||||
|
||||
func makeMapProvidersMap(providers ...Provider) map[string]Provider {
|
||||
ret := make(map[string]Provider, len(providers))
|
||||
for _, provider := range providers {
|
||||
ret[provider.Scheme()] = provider
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func TestNewResolverInvalidScheme(t *testing.T) {
|
||||
_, err := NewResolver(ResolverSettings{URIs: []string{"s_3:has invalid char"}, Providers: makeMapProvidersMap(&mockProvider{scheme: "s_3"})})
|
||||
_, err := NewResolver(ResolverSettings{URIs: []string{"s_3:has invalid char"}, ProviderFactories: []ProviderFactory{newMockProvider(&mockProvider{scheme: "s_3"})}})
|
||||
assert.EqualError(t, err, `invalid uri: "s_3:has invalid char"`)
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +191,17 @@ func TestResolverErrors(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: tt.locations, Providers: makeMapProvidersMap(tt.providers...), Converters: tt.converters})
|
||||
mockProviderFuncs := make([]ProviderFactory, len(tt.providers))
|
||||
for i, provider := range tt.providers {
|
||||
p := provider
|
||||
mockProviderFuncs[i] = NewProviderFactory(func(_ ProviderSettings) Provider { return p })
|
||||
}
|
||||
converterFuncs := make([]ConverterFactory, len(tt.converters))
|
||||
for i, converter := range tt.converters {
|
||||
c := converter
|
||||
converterFuncs[i] = NewConverterFactory(func(_ ConverterSettings) Converter { return c })
|
||||
}
|
||||
resolver, err := NewResolver(ResolverSettings{URIs: tt.locations, ProviderFactories: mockProviderFuncs, ConverterFactories: converterFuncs})
|
||||
if tt.expectBuildErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
|
|
@ -251,10 +281,12 @@ func TestBackwardsCompatibilityForFilePath(t *testing.T) {
|
|||
t.Run(tt.name, func(t *testing.T) {
|
||||
resolver, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{tt.location},
|
||||
Providers: makeMapProvidersMap(newFakeProvider("file", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) {
|
||||
return nil, errors.New(uri)
|
||||
})),
|
||||
Converters: nil})
|
||||
ProviderFactories: []ProviderFactory{
|
||||
newFakeProvider("file", func(_ context.Context, uri string, _ WatcherFunc) (*Retrieved, error) {
|
||||
return nil, errors.New(uri)
|
||||
}),
|
||||
},
|
||||
ConverterFactories: nil})
|
||||
if tt.expectBuildErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
|
|
@ -270,11 +302,13 @@ func TestResolver(t *testing.T) {
|
|||
numCalls := atomic.Int32{}
|
||||
resolver, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{"mock:"},
|
||||
Providers: makeMapProvidersMap(&mockProvider{retM: map[string]any{}, closeFunc: func(context.Context) error {
|
||||
numCalls.Add(1)
|
||||
return nil
|
||||
}}),
|
||||
Converters: nil})
|
||||
ProviderFactories: []ProviderFactory{
|
||||
newMockProvider(&mockProvider{retM: map[string]any{}, closeFunc: func(context.Context) error {
|
||||
numCalls.Add(1)
|
||||
return nil
|
||||
}}),
|
||||
},
|
||||
ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
_, errN := resolver.Resolve(context.Background())
|
||||
assert.NoError(t, errN)
|
||||
|
|
@ -303,33 +337,33 @@ func TestResolver(t *testing.T) {
|
|||
|
||||
func TestResolverNewLinesInOpaqueValue(t *testing.T) {
|
||||
_, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{"mock:receivers:\n nop:\n"},
|
||||
Providers: makeMapProvidersMap(&mockProvider{retM: map[string]any{}}),
|
||||
Converters: nil})
|
||||
URIs: []string{"mock:receivers:\n nop:\n"},
|
||||
ProviderFactories: []ProviderFactory{newMockProvider(&mockProvider{retM: map[string]any{}})},
|
||||
ConverterFactories: nil})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestResolverNoLocations(t *testing.T) {
|
||||
_, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{},
|
||||
Providers: makeMapProvidersMap(&mockProvider{}),
|
||||
Converters: nil})
|
||||
URIs: []string{},
|
||||
ProviderFactories: []ProviderFactory{newMockProvider(&mockProvider{})},
|
||||
ConverterFactories: nil})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestResolverNoProviders(t *testing.T) {
|
||||
_, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "config.yaml")},
|
||||
Providers: nil,
|
||||
Converters: nil})
|
||||
URIs: []string{filepath.Join("testdata", "config.yaml")},
|
||||
ProviderFactories: nil,
|
||||
ConverterFactories: nil})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestResolverShutdownClosesWatch(t *testing.T) {
|
||||
resolver, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "config.yaml")},
|
||||
Providers: makeMapProvidersMap(newFileProvider(t)),
|
||||
Converters: nil})
|
||||
URIs: []string{filepath.Join("testdata", "config.yaml")},
|
||||
ProviderFactories: []ProviderFactory{newFileProvider(t)},
|
||||
ConverterFactories: nil})
|
||||
require.NoError(t, err)
|
||||
_, errN := resolver.Resolve(context.Background())
|
||||
assert.NoError(t, errN)
|
||||
|
|
@ -347,3 +381,51 @@ func TestResolverShutdownClosesWatch(t *testing.T) {
|
|||
assert.NoError(t, resolver.Shutdown(context.Background()))
|
||||
watcherWG.Wait()
|
||||
}
|
||||
|
||||
func TestCantConfigureTwoProviderSettings(t *testing.T) {
|
||||
_, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "config.yaml")},
|
||||
ProviderFactories: []ProviderFactory{newFileProvider(t)},
|
||||
Providers: map[string]Provider{"mock": &mockProvider{}},
|
||||
ConverterFactories: nil,
|
||||
})
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCantConfigureTwoConverterSettings(t *testing.T) {
|
||||
_, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "config.yaml")},
|
||||
ProviderFactories: []ProviderFactory{newFileProvider(t)},
|
||||
ConverterFactories: []ConverterFactory{NewConverterFactory(func(_ ConverterSettings) Converter { return &mockConverter{} })},
|
||||
Converters: []Converter{&mockConverter{err: errors.New("converter_err")}},
|
||||
})
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestTakesInstantiatedProviders(t *testing.T) {
|
||||
_, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "config.yaml")},
|
||||
Providers: map[string]Provider{"mock": &mockProvider{}},
|
||||
ConverterFactories: nil,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestTakesInstantiatedConverters(t *testing.T) {
|
||||
_, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "config.yaml")},
|
||||
ProviderFactories: []ProviderFactory{newFileProvider(t)},
|
||||
Converters: []Converter{&mockConverter{err: errors.New("converter_err")}},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestProvidesDefaultLogger(t *testing.T) {
|
||||
factory, provider := newObservableFileProvider(t)
|
||||
_, err := NewResolver(ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "config.yaml")},
|
||||
ProviderFactories: []ProviderFactory{factory},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, provider.logger)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,6 +116,9 @@ func NewCollector(set CollectorSettings) (*Collector, error) {
|
|||
var err error
|
||||
configProvider := set.ConfigProvider
|
||||
|
||||
set.ConfigProviderSettings.ResolverSettings.ProviderSettings = confmap.ProviderSettings{Logger: zap.NewNop()}
|
||||
set.ConfigProviderSettings.ResolverSettings.ConverterSettings = confmap.ConverterSettings{}
|
||||
|
||||
if configProvider == nil {
|
||||
configProvider, err = NewConfigProvider(set.ConfigProviderSettings)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -464,8 +464,8 @@ func TestPassConfmapToServiceFailure(t *testing.T) {
|
|||
Factories: nopFactories,
|
||||
ConfigProviderSettings: ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")},
|
||||
Providers: makeMapProvidersMap(newFailureProvider()),
|
||||
URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")},
|
||||
ProviderFactories: []confmap.ProviderFactory{confmap.NewProviderFactory(newFailureProvider)},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -488,7 +488,7 @@ func startCollector(ctx context.Context, t *testing.T, col *Collector) *sync.Wai
|
|||
|
||||
type failureProvider struct{}
|
||||
|
||||
func newFailureProvider() confmap.Provider {
|
||||
func newFailureProvider(_ confmap.ProviderSettings) confmap.Provider {
|
||||
return &failureProvider{}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ func updateSettingsUsingFlags(set *CollectorSettings, flags *flag.FlagSet) error
|
|||
// Provide a default set of providers and converters if none have been specified.
|
||||
// TODO: Remove this after CollectorSettings.ConfigProvider is removed and instead
|
||||
// do it in the builder.
|
||||
if len(resolverSet.Providers) == 0 && len(resolverSet.Converters) == 0 {
|
||||
if len(resolverSet.ProviderFactories) == 0 && len(resolverSet.ConverterFactories) == 0 {
|
||||
set.ConfigProviderSettings = newDefaultConfigProviderSettings(resolverSet.URIs)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import (
|
|||
|
||||
"go.opentelemetry.io/collector/component"
|
||||
"go.opentelemetry.io/collector/confmap"
|
||||
"go.opentelemetry.io/collector/confmap/confmaptest"
|
||||
"go.opentelemetry.io/collector/confmap/converter/expandconverter"
|
||||
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
|
||||
"go.opentelemetry.io/collector/featuregate"
|
||||
|
|
@ -53,9 +52,9 @@ func TestAddFlagToSettings(t *testing.T) {
|
|||
set := CollectorSettings{
|
||||
ConfigProviderSettings: ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")},
|
||||
Providers: map[string]confmap.Provider{"file": fileprovider.NewWithSettings(confmaptest.NewNopProviderSettings())},
|
||||
Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})},
|
||||
URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")},
|
||||
ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()},
|
||||
ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -81,16 +80,16 @@ func TestAddDefaultConfmapModules(t *testing.T) {
|
|||
err = updateSettingsUsingFlags(&set, flgs)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, set.ConfigProviderSettings.ResolverSettings.URIs, 1)
|
||||
require.Len(t, set.ConfigProviderSettings.ResolverSettings.Converters, 1)
|
||||
require.Len(t, set.ConfigProviderSettings.ResolverSettings.Providers, 5)
|
||||
require.Len(t, set.ConfigProviderSettings.ResolverSettings.ConverterFactories, 1)
|
||||
require.Len(t, set.ConfigProviderSettings.ResolverSettings.ProviderFactories, 5)
|
||||
}
|
||||
|
||||
func TestInvalidCollectorSettings(t *testing.T) {
|
||||
set := CollectorSettings{
|
||||
ConfigProviderSettings: ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})},
|
||||
URIs: []string{"--config=otelcol-nop.yaml"},
|
||||
ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()},
|
||||
URIs: []string{"--config=otelcol-nop.yaml"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -102,9 +101,9 @@ func TestInvalidCollectorSettings(t *testing.T) {
|
|||
func TestNewCommandInvalidComponent(t *testing.T) {
|
||||
set := ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")},
|
||||
Providers: map[string]confmap.Provider{"file": fileprovider.NewWithSettings(confmaptest.NewNopProviderSettings())},
|
||||
Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})},
|
||||
URIs: []string{filepath.Join("testdata", "otelcol-invalid.yaml")},
|
||||
ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()},
|
||||
ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.opentelemetry.io/collector/confmap"
|
||||
"go.opentelemetry.io/collector/confmap/confmaptest"
|
||||
"go.opentelemetry.io/collector/confmap/converter/expandconverter"
|
||||
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
|
||||
"go.opentelemetry.io/collector/featuregate"
|
||||
|
|
@ -27,9 +26,9 @@ func TestValidateSubCommandInvalidComponents(t *testing.T) {
|
|||
cfgProvider, err := NewConfigProvider(
|
||||
ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
URIs: []string{filepath.Join("testdata", "otelcol-invalid-components.yaml")},
|
||||
Providers: map[string]confmap.Provider{"file": fileprovider.NewWithSettings(confmaptest.NewNopProviderSettings())},
|
||||
Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})},
|
||||
URIs: []string{filepath.Join("testdata", "otelcol-invalid-components.yaml")},
|
||||
ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()},
|
||||
ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"fmt"
|
||||
|
||||
"go.opentelemetry.io/collector/confmap"
|
||||
"go.opentelemetry.io/collector/confmap/confmaptest"
|
||||
"go.opentelemetry.io/collector/confmap/converter/expandconverter"
|
||||
"go.opentelemetry.io/collector/confmap/provider/envprovider"
|
||||
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
|
||||
|
|
@ -133,27 +132,17 @@ func (cm *configProvider) GetConfmap(ctx context.Context) (*confmap.Conf, error)
|
|||
}
|
||||
|
||||
func newDefaultConfigProviderSettings(uris []string) ConfigProviderSettings {
|
||||
converterSet := confmap.ConverterSettings{}
|
||||
providerSet := confmaptest.NewNopProviderSettings()
|
||||
return ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
URIs: uris,
|
||||
Providers: makeMapProvidersMap(
|
||||
fileprovider.NewWithSettings(providerSet),
|
||||
envprovider.NewWithSettings(providerSet),
|
||||
yamlprovider.NewWithSettings(providerSet),
|
||||
httpprovider.NewWithSettings(providerSet),
|
||||
httpsprovider.NewWithSettings(providerSet),
|
||||
),
|
||||
Converters: []confmap.Converter{expandconverter.New(converterSet)},
|
||||
ProviderFactories: []confmap.ProviderFactory{
|
||||
fileprovider.NewFactory(),
|
||||
envprovider.NewFactory(),
|
||||
yamlprovider.NewFactory(),
|
||||
httpprovider.NewFactory(),
|
||||
httpsprovider.NewFactory(),
|
||||
},
|
||||
ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeMapProvidersMap(providers ...confmap.Provider) map[string]confmap.Provider {
|
||||
ret := make(map[string]confmap.Provider, len(providers))
|
||||
for _, provider := range providers {
|
||||
ret[provider.Scheme()] = provider
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import (
|
|||
"gopkg.in/yaml.v3"
|
||||
|
||||
"go.opentelemetry.io/collector/confmap"
|
||||
"go.opentelemetry.io/collector/confmap/confmaptest"
|
||||
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
|
||||
"go.opentelemetry.io/collector/confmap/provider/yamlprovider"
|
||||
)
|
||||
|
|
@ -49,11 +48,10 @@ func TestConfigProviderYaml(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
uriLocation := "yaml:" + string(yamlBytes)
|
||||
provider := yamlprovider.NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
set := ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
URIs: []string{uriLocation},
|
||||
Providers: map[string]confmap.Provider{provider.Scheme(): provider},
|
||||
URIs: []string{uriLocation},
|
||||
ProviderFactories: []confmap.ProviderFactory{yamlprovider.NewFactory()},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -74,11 +72,10 @@ func TestConfigProviderYaml(t *testing.T) {
|
|||
|
||||
func TestConfigProviderFile(t *testing.T) {
|
||||
uriLocation := "file:" + filepath.Join("testdata", "otelcol-nop.yaml")
|
||||
provider := fileprovider.NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
set := ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
URIs: []string{uriLocation},
|
||||
Providers: map[string]confmap.Provider{provider.Scheme(): provider},
|
||||
URIs: []string{uriLocation},
|
||||
ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -102,11 +99,10 @@ func TestConfigProviderFile(t *testing.T) {
|
|||
|
||||
func TestGetConfmap(t *testing.T) {
|
||||
uriLocation := "file:" + filepath.Join("testdata", "otelcol-nop.yaml")
|
||||
provider := fileprovider.NewWithSettings(confmaptest.NewNopProviderSettings())
|
||||
set := ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
URIs: []string{uriLocation},
|
||||
Providers: map[string]confmap.Provider{provider.Scheme(): provider},
|
||||
URIs: []string{uriLocation},
|
||||
ProviderFactories: []confmap.ProviderFactory{fileprovider.NewFactory()},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"context"
|
||||
|
||||
"go.opentelemetry.io/collector/confmap"
|
||||
"go.opentelemetry.io/collector/confmap/confmaptest"
|
||||
"go.opentelemetry.io/collector/confmap/converter/expandconverter"
|
||||
"go.opentelemetry.io/collector/confmap/provider/envprovider"
|
||||
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
|
||||
|
|
@ -22,13 +21,13 @@ func LoadConfig(fileName string, factories otelcol.Factories) (*otelcol.Config,
|
|||
provider, err := otelcol.NewConfigProvider(otelcol.ConfigProviderSettings{
|
||||
ResolverSettings: confmap.ResolverSettings{
|
||||
URIs: []string{fileName},
|
||||
Providers: makeMapProvidersMap(
|
||||
fileprovider.NewWithSettings(confmaptest.NewNopProviderSettings()),
|
||||
envprovider.NewWithSettings(confmaptest.NewNopProviderSettings()),
|
||||
yamlprovider.NewWithSettings(confmaptest.NewNopProviderSettings()),
|
||||
httpprovider.NewWithSettings(confmaptest.NewNopProviderSettings()),
|
||||
),
|
||||
Converters: []confmap.Converter{expandconverter.New(confmap.ConverterSettings{})},
|
||||
ProviderFactories: []confmap.ProviderFactory{
|
||||
fileprovider.NewFactory(),
|
||||
envprovider.NewFactory(),
|
||||
yamlprovider.NewFactory(),
|
||||
httpprovider.NewFactory(),
|
||||
},
|
||||
ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
|
|
@ -45,11 +44,3 @@ func LoadConfigAndValidate(fileName string, factories otelcol.Factories) (*otelc
|
|||
}
|
||||
return cfg, cfg.Validate()
|
||||
}
|
||||
|
||||
func makeMapProvidersMap(providers ...confmap.Provider) map[string]confmap.Provider {
|
||||
ret := make(map[string]confmap.Provider, len(providers))
|
||||
for _, provider := range providers {
|
||||
ret[provider.Scheme()] = provider
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue