Skip to content

Commit

Permalink
Add a new bytes provier, allows providing yaml bytes
Browse files Browse the repository at this point in the history
Open Question: Should the schema be "yaml:" or "bytes:"?

Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>
  • Loading branch information
bogdandrutu committed Mar 15, 2022
1 parent 7666eb0 commit 45201c7
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 0 deletions.
58 changes: 58 additions & 0 deletions config/configmapprovider/yaml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package configmapprovider // import "go.opentelemetry.io/collector/config/configmapprovider"

import (
"context"
"fmt"
"strings"

"gopkg.in/yaml.v2"

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

const bytesSchemeName = "yaml"

type bytesMapProvider struct{}

// NewYaml returns a new Provider that allows to provide yaml bytes.
//
// This Provider supports "yaml" scheme, and can be called with a "location" that follows:
// bytes-location = "yaml:" yaml-bytes
//
// Examples:
// `yaml:processors::batch::timeout: 2s`
// `yaml:processors::batch/foo::timeout: 3s`
func NewYaml() Provider {
return &bytesMapProvider{}
}

func (s *bytesMapProvider) Retrieve(_ context.Context, location string, _ WatcherFunc) (Retrieved, error) {
if !strings.HasPrefix(location, bytesSchemeName+":") {
return Retrieved{}, fmt.Errorf("%v location is not supported by %v provider", location, bytesSchemeName)
}

var data map[string]interface{}
if err := yaml.Unmarshal([]byte(location[len(bytesSchemeName)+1:]), &data); err != nil {
return Retrieved{}, fmt.Errorf("unable to parse yaml: %w", err)
}

return Retrieved{Map: config.NewMapFromStringMap(data)}, nil
}

func (s *bytesMapProvider) Shutdown(context.Context) error {
return nil
}
106 changes: 106 additions & 0 deletions config/configmapprovider/yaml_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package configmapprovider

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
)

func TestYamlProvider_Empty(t *testing.T) {
sp := NewYaml()
_, err := sp.Retrieve(context.Background(), "", nil)
assert.Error(t, err)
assert.NoError(t, sp.Shutdown(context.Background()))
}

func TestYamlProvider_InvalidValue(t *testing.T) {
sp := NewYaml()
_, err := sp.Retrieve(context.Background(), "yaml::2s", nil)
assert.Error(t, err)
assert.NoError(t, sp.Shutdown(context.Background()))
}

func TestYamlProvider(t *testing.T) {
sp := NewYaml()
ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch::timeout: 2s", nil)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"processors": map[string]interface{}{
"batch": map[string]interface{}{
"timeout": "2s",
},
},
}, ret.Map.ToStringMap())
assert.NoError(t, sp.Shutdown(context.Background()))
}

func TestYamlProvider_NamedComponent(t *testing.T) {
sp := NewYaml()
ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch/foo::timeout: 3s", nil)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"processors": map[string]interface{}{
"batch/foo": map[string]interface{}{
"timeout": "3s",
},
},
}, ret.Map.ToStringMap())
assert.NoError(t, sp.Shutdown(context.Background()))
}

func TestYamlProvider_MapEntry(t *testing.T) {
sp := NewYaml()
ret, err := sp.Retrieve(context.Background(), "yaml:processors: {batch/foo::timeout: 3s, batch::timeout: 2s}", nil)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"processors": map[string]interface{}{
"batch/foo": map[string]interface{}{
"timeout": "3s",
},
"batch": map[string]interface{}{
"timeout": "2s",
},
},
}, ret.Map.ToStringMap())
assert.NoError(t, sp.Shutdown(context.Background()))
}

func TestYamlProvider_NewLine(t *testing.T) {
sp := NewYaml()
ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch/foo::timeout: 3s\nprocessors::batch::timeout: 2s", nil)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"processors": map[string]interface{}{
"batch/foo": map[string]interface{}{
"timeout": "3s",
},
"batch": map[string]interface{}{
"timeout": "2s",
},
},
}, ret.Map.ToStringMap())
assert.NoError(t, sp.Shutdown(context.Background()))
}

func TestYamlProvider_DotSeparator(t *testing.T) {
sp := NewYaml()
ret, err := sp.Retrieve(context.Background(), "yaml:processors.batch.timeout: 4s", nil)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{"processors.batch.timeout": "4s"}, ret.Map.ToStringMap())
assert.NoError(t, sp.Shutdown(context.Background()))
}
1 change: 1 addition & 0 deletions service/config_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func MustNewDefaultConfigProvider(configLocations []string, properties []string)
map[string]configmapprovider.Provider{
"file": configmapprovider.NewFile(),
"env": configmapprovider.NewEnv(),
"yaml": configmapprovider.NewYaml(),
},
[]config.MapConverterFunc{
configmapprovider.NewOverwritePropertiesConverter(properties),
Expand Down

0 comments on commit 45201c7

Please sign in to comment.