diff --git a/operator/builtin/transformer/router/config_test.go b/operator/builtin/transformer/router/config_test.go new file mode 100644 index 000000000000..fd999ee4cd4d --- /dev/null +++ b/operator/builtin/transformer/router/config_test.go @@ -0,0 +1,171 @@ +// 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 router + +import ( + "fmt" + "io/ioutil" + "path" + "testing" + + "github.com/open-telemetry/opentelemetry-log-collection/operator/helper" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" +) + +type testCase struct { + name string + expectErr bool + expect *RouterOperatorConfig +} + +func TestRouterGoldenConfig(t *testing.T) { + cases := []testCase{ + { + "default", + false, + defaultCfg(), + }, + { + "routes_one", + false, + func() *RouterOperatorConfig { + cfg := defaultCfg() + newRoute := &RouterOperatorRouteConfig{ + Expression: `$.format == "json"`, + OutputIDs: []string{"my_json_parser"}, + } + cfg.Routes = append(cfg.Routes, newRoute) + return cfg + }(), + }, + { + "routes_multi", + false, + func() *RouterOperatorConfig { + cfg := defaultCfg() + newRoute := []*RouterOperatorRouteConfig{ + { + Expression: `$.format == "json"`, + OutputIDs: []string{"my_json_parser"}, + }, + { + Expression: `$.format == "json"2`, + OutputIDs: []string{"my_json_parser2"}, + }, + { + Expression: `$.format == "json"3`, + OutputIDs: []string{"my_json_parser3"}, + }, + } + cfg.Routes = newRoute + return cfg + }(), + }, + { + "routes_attributes", + false, + func() *RouterOperatorConfig { + cfg := defaultCfg() + + attVal := helper.NewAttributerConfig() + attVal.Attributes = map[string]helper.ExprStringConfig{ + "key1": "val1", + } + + cfg.Routes = []*RouterOperatorRouteConfig{ + { + Expression: `$.format == "json"`, + OutputIDs: []string{"my_json_parser"}, + AttributerConfig: attVal, + }, + } + return cfg + }(), + }, + { + "routes_default", + false, + func() *RouterOperatorConfig { + cfg := defaultCfg() + newRoute := &RouterOperatorRouteConfig{ + Expression: `$.format == "json"`, + OutputIDs: []string{"my_json_parser"}, + } + cfg.Routes = append(cfg.Routes, newRoute) + cfg.Default = append(cfg.Default, "catchall") + return cfg + }(), + }, + } + + for _, tc := range cases { + t.Run("yaml/"+tc.name, func(t *testing.T) { + cfgFromYaml, yamlErr := configFromFileViaYaml(path.Join(".", "testdata", fmt.Sprintf("%s.yaml", tc.name))) + if tc.expectErr { + require.Error(t, yamlErr) + } else { + require.NoError(t, yamlErr) + require.Equal(t, tc.expect, cfgFromYaml) + } + }) + t.Run("mapstructure/"+tc.name, func(t *testing.T) { + cfgFromMapstructure := defaultCfg() + mapErr := configFromFileViaMapstructure( + path.Join(".", "testdata", fmt.Sprintf("%s.yaml", tc.name)), + cfgFromMapstructure, + ) + if tc.expectErr { + require.Error(t, mapErr) + } else { + require.NoError(t, mapErr) + require.Equal(t, tc.expect, cfgFromMapstructure) + } + }) + } +} + +func configFromFileViaYaml(file string) (*RouterOperatorConfig, error) { + bytes, err := ioutil.ReadFile(file) + if err != nil { + return nil, fmt.Errorf("could not find config file: %s", err) + } + + config := defaultCfg() + if err := yaml.Unmarshal(bytes, config); err != nil { + return nil, fmt.Errorf("failed to read config file as yaml: %s", err) + } + + return config, nil +} + +func configFromFileViaMapstructure(file string, result *RouterOperatorConfig) error { + bytes, err := ioutil.ReadFile(file) + if err != nil { + return fmt.Errorf("could not find config file: %s", err) + } + + raw := map[string]interface{}{} + + if err := yaml.Unmarshal(bytes, raw); err != nil { + return fmt.Errorf("failed to read data from yaml: %s", err) + } + + err = helper.UnmarshalMapstructure(raw, result) + return err +} + +func defaultCfg() *RouterOperatorConfig { + return NewRouterOperatorConfig("router") +} diff --git a/operator/builtin/transformer/router/router.go b/operator/builtin/transformer/router/router.go index 673af252db1a..d227c4559495 100644 --- a/operator/builtin/transformer/router/router.go +++ b/operator/builtin/transformer/router/router.go @@ -39,16 +39,16 @@ func NewRouterOperatorConfig(operatorID string) *RouterOperatorConfig { // RouterOperatorConfig is the configuration of a router operator type RouterOperatorConfig struct { - helper.BasicConfig `yaml:",inline"` - Routes []*RouterOperatorRouteConfig `json:"routes" yaml:"routes"` - Default helper.OutputIDs `json:"default" yaml:"default"` + helper.BasicConfig `mapstructure:",squash" yaml:",inline"` + Routes []*RouterOperatorRouteConfig `mapstructure:"routes" json:"routes" yaml:"routes"` + Default helper.OutputIDs `mapstructure:"default" json:"default" yaml:"default"` } // RouterOperatorRouteConfig is the configuration of a route on a router operator type RouterOperatorRouteConfig struct { - helper.AttributerConfig `yaml:",inline"` - Expression string `json:"expr" yaml:"expr"` - OutputIDs helper.OutputIDs `json:"output" yaml:"output"` + helper.AttributerConfig `mapstructure:",squash" yaml:",inline"` + Expression string `mapstructure:"expr" json:"expr" yaml:"expr"` + OutputIDs helper.OutputIDs `mapstructure:"output" json:"output" yaml:"output"` } // Build will build a router operator from the supplied configuration diff --git a/operator/builtin/transformer/router/testdata/default.yaml b/operator/builtin/transformer/router/testdata/default.yaml new file mode 100644 index 000000000000..00bce5eef0f5 --- /dev/null +++ b/operator/builtin/transformer/router/testdata/default.yaml @@ -0,0 +1 @@ +type: router \ No newline at end of file diff --git a/operator/builtin/transformer/router/testdata/routes_attributes.yaml b/operator/builtin/transformer/router/testdata/routes_attributes.yaml new file mode 100644 index 000000000000..8c2efa00036a --- /dev/null +++ b/operator/builtin/transformer/router/testdata/routes_attributes.yaml @@ -0,0 +1,6 @@ +type: router +routes: + - output: my_json_parser + expr: '$.format == "json"' + attributes: + key1: val1 \ No newline at end of file diff --git a/operator/builtin/transformer/router/testdata/routes_default.yaml b/operator/builtin/transformer/router/testdata/routes_default.yaml new file mode 100644 index 000000000000..8c4433223ad5 --- /dev/null +++ b/operator/builtin/transformer/router/testdata/routes_default.yaml @@ -0,0 +1,5 @@ +type: router +routes: + - output: my_json_parser + expr: '$.format == "json"' +default: catchall \ No newline at end of file diff --git a/operator/builtin/transformer/router/testdata/routes_multi.yaml b/operator/builtin/transformer/router/testdata/routes_multi.yaml new file mode 100644 index 000000000000..ccc3155bc0d0 --- /dev/null +++ b/operator/builtin/transformer/router/testdata/routes_multi.yaml @@ -0,0 +1,8 @@ +type: router +routes: + - output: my_json_parser + expr: '$.format == "json"' + - output: my_json_parser2 + expr: '$.format == "json"2' + - output: my_json_parser3 + expr: '$.format == "json"3' \ No newline at end of file diff --git a/operator/builtin/transformer/router/testdata/routes_one.yaml b/operator/builtin/transformer/router/testdata/routes_one.yaml new file mode 100644 index 000000000000..7f8a7970ec1d --- /dev/null +++ b/operator/builtin/transformer/router/testdata/routes_one.yaml @@ -0,0 +1,4 @@ +type: router +routes: + - output: my_json_parser + expr: '$.format == "json"'