diff --git a/pkg/stanza/operator/helper/helper_test.go b/pkg/stanza/operator/helper/helper_test.go index 2067c066564c..d68c16973f63 100644 --- a/pkg/stanza/operator/helper/helper_test.go +++ b/pkg/stanza/operator/helper/helper_test.go @@ -27,6 +27,7 @@ func init() { type helpersConfig struct { BasicConfig `mapstructure:",squash"` + Writer WriterConfig `mapstructure:"writer"` Time TimeParser `mapstructure:"time"` Severity SeverityConfig `mapstructure:"severity"` Scope ScopeNameParser `mapstructure:"scope"` @@ -36,6 +37,7 @@ type helpersConfig struct { func newHelpersConfig() *helpersConfig { return &helpersConfig{ BasicConfig: NewBasicConfig(helpersTestType, helpersTestType), + Writer: NewWriterConfig(helpersTestType, helpersTestType), Time: NewTimeParser(), Severity: NewSeverityConfig(), Scope: NewScopeNameParser(), diff --git a/pkg/stanza/operator/helper/testdata/writer.yaml b/pkg/stanza/operator/helper/testdata/writer.yaml new file mode 100644 index 000000000000..7a32a0fb181a --- /dev/null +++ b/pkg/stanza/operator/helper/testdata/writer.yaml @@ -0,0 +1,13 @@ +string: + type: helpers_test + writer: + output: test +slice: + type: helpers_test + writer: + output: [test1, test2] +invalid: + type: helpers_test + writer: + output: + foo: bar \ No newline at end of file diff --git a/pkg/stanza/operator/helper/writer.go b/pkg/stanza/operator/helper/writer.go index 01c3f793b41f..a2accb4c52e8 100644 --- a/pkg/stanza/operator/helper/writer.go +++ b/pkg/stanza/operator/helper/writer.go @@ -16,7 +16,6 @@ package helper // import "github.com/open-telemetry/opentelemetry-collector-cont import ( "context" - "encoding/json" "fmt" "go.uber.org/zap" @@ -34,8 +33,8 @@ func NewWriterConfig(operatorID, operatorType string) WriterConfig { // WriterConfig is the configuration of a writer operator. type WriterConfig struct { - BasicConfig `mapstructure:",squash" yaml:",inline"` - OutputIDs OutputIDs `mapstructure:"output" json:"output" yaml:"output"` + BasicConfig `mapstructure:",squash"` + OutputIDs []string `mapstructure:"output"` } // Build will build a writer operator from the config. @@ -54,7 +53,7 @@ func (c WriterConfig) Build(logger *zap.SugaredLogger) (WriterOperator, error) { // WriterOperator is an operator that can write to other operators. type WriterOperator struct { BasicOperator - OutputIDs OutputIDs + OutputIDs []string OutputOperators []operator.Operator } @@ -119,66 +118,3 @@ func (w *WriterOperator) findOperator(operators []operator.Operator, operatorID } return nil, false } - -// OutputIDs is a collection of operator IDs used as outputs. -type OutputIDs []string - -// UnmarshalJSON will unmarshal a string or array of strings to OutputIDs. -func (o *OutputIDs) UnmarshalJSON(bytes []byte) error { - var value interface{} - err := json.Unmarshal(bytes, &value) - if err != nil { - return err - } - - ids, err := NewOutputIDsFromInterface(value) - if err != nil { - return err - } - - *o = ids - return nil -} - -// UnmarshalYAML will unmarshal a string or array of strings to OutputIDs. -func (o *OutputIDs) UnmarshalYAML(unmarshal func(interface{}) error) error { - var value interface{} - err := unmarshal(&value) - if err != nil { - return err - } - - ids, err := NewOutputIDsFromInterface(value) - if err != nil { - return err - } - - *o = ids - return nil -} - -// NewOutputIDsFromInterface creates a new OutputIDs object from an interface -func NewOutputIDsFromInterface(value interface{}) (OutputIDs, error) { - if str, ok := value.(string); ok { - return OutputIDs{str}, nil - } - - if array, ok := value.([]interface{}); ok { - return NewOutputIDsFromArray(array) - } - - return nil, fmt.Errorf("value is not of type string or string array") -} - -// NewOutputIDsFromArray creates a new OutputIDs object from an array -func NewOutputIDsFromArray(array []interface{}) (OutputIDs, error) { - ids := OutputIDs{} - for _, rawValue := range array { - strValue, ok := rawValue.(string) - if !ok { - return nil, fmt.Errorf("value in array is not of type string") - } - ids = append(ids, strValue) - } - return ids, nil -} diff --git a/pkg/stanza/operator/helper/writer_test.go b/pkg/stanza/operator/helper/writer_test.go index 087bab48f1dc..c067dfd79fb3 100644 --- a/pkg/stanza/operator/helper/writer_test.go +++ b/pkg/stanza/operator/helper/writer_test.go @@ -16,15 +16,15 @@ package helper import ( "context" - "encoding/json" + "path/filepath" "testing" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - yaml "gopkg.in/yaml.v2" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/entry" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator" + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/operatortest" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/testutil" ) @@ -40,7 +40,7 @@ func TestWriterConfigMissingOutput(t *testing.T) { func TestWriterConfigValidBuild(t *testing.T) { config := WriterConfig{ - OutputIDs: OutputIDs{"output"}, + OutputIDs: []string{"output"}, BasicConfig: BasicConfig{ OperatorType: "testtype", }, @@ -92,7 +92,7 @@ func TestWriterSetOutputsMissing(t *testing.T) { output1 := &testutil.Operator{} output1.On("ID").Return("output1") writer := WriterOperator{ - OutputIDs: OutputIDs{"output2"}, + OutputIDs: []string{"output2"}, } err := writer.SetOutputs([]operator.Operator{output1}) @@ -105,7 +105,7 @@ func TestWriterSetOutputsInvalid(t *testing.T) { output1.On("ID").Return("output1") output1.On("CanProcess").Return(false) writer := WriterOperator{ - OutputIDs: OutputIDs{"output1"}, + OutputIDs: []string{"output1"}, } err := writer.SetOutputs([]operator.Operator{output1}) @@ -121,7 +121,7 @@ func TestWriterSetOutputsValid(t *testing.T) { output2.On("ID").Return("output2") output2.On("CanProcess").Return(true) writer := WriterOperator{ - OutputIDs: OutputIDs{"output1", "output2"}, + OutputIDs: []string{"output1", "output2"}, } err := writer.SetOutputs([]operator.Operator{output1, output2}) @@ -129,82 +129,33 @@ func TestWriterSetOutputsValid(t *testing.T) { require.Equal(t, []operator.Operator{output1, output2}, writer.Outputs()) } -func TestUnmarshalJSONString(t *testing.T) { - bytes := []byte("{\"output\":\"test\"}") - var config WriterConfig - err := json.Unmarshal(bytes, &config) - require.NoError(t, err) - require.Equal(t, OutputIDs{"test"}, config.OutputIDs) -} - -func TestUnmarshalJSONArray(t *testing.T) { - bytes := []byte("{\"output\":[\"test1\",\"test2\"]}") - var config WriterConfig - err := json.Unmarshal(bytes, &config) - require.NoError(t, err) - require.Equal(t, OutputIDs{"test1", "test2"}, config.OutputIDs) -} - -func TestUnmarshalJSONInvalidValue(t *testing.T) { - bytes := []byte("..") - var config WriterConfig - err := json.Unmarshal(bytes, &config) - require.Error(t, err) - require.Contains(t, err.Error(), "invalid character") -} - -func TestUnmarshalJSONInvalidString(t *testing.T) { - bytes := []byte("{\"output\": true}") - var config WriterConfig - err := json.Unmarshal(bytes, &config) - require.Error(t, err) - require.Contains(t, err.Error(), "value is not of type string or string array") -} - -func TestUnmarshalJSONInvalidArray(t *testing.T) { - bytes := []byte("{\"output\":[\"test1\", true]}") - var config WriterConfig - err := json.Unmarshal(bytes, &config) - require.Error(t, err) - require.Contains(t, err.Error(), "value in array is not of type string") -} - -func TestUnmarshalYAMLString(t *testing.T) { - bytes := []byte("output: test") - var config WriterConfig - err := yaml.Unmarshal(bytes, &config) - require.NoError(t, err) - require.Equal(t, OutputIDs{"test"}, config.OutputIDs) -} - -func TestUnmarshalYAMLArray(t *testing.T) { - bytes := []byte("output: [test1, test2]") - var config WriterConfig - err := yaml.Unmarshal(bytes, &config) - require.NoError(t, err) - require.Equal(t, OutputIDs{"test1", "test2"}, config.OutputIDs) -} - -func TestUnmarshalYAMLInvalidValue(t *testing.T) { - bytes := []byte("..") - var config WriterConfig - err := yaml.Unmarshal(bytes, &config) - require.Error(t, err) - require.Contains(t, err.Error(), "cannot unmarshal") -} - -func TestUnmarshalYAMLInvalidString(t *testing.T) { - bytes := []byte("output: true") - var config WriterConfig - err := yaml.Unmarshal(bytes, &config) - require.Error(t, err) - require.Contains(t, err.Error(), "value is not of type string or string array") -} - -func TestUnmarshalYAMLInvalidArray(t *testing.T) { - bytes := []byte("output: [test1, true]") - var config WriterConfig - err := yaml.Unmarshal(bytes, &config) - require.Error(t, err) - require.Contains(t, err.Error(), "value in array is not of type string") +func TestUnmarshalWriterConfig(t *testing.T) { + operatortest.ConfigUnmarshalTests{ + DefaultConfig: newHelpersConfig(), + TestsFile: filepath.Join(".", "testdata", "writer.yaml"), + Tests: []operatortest.ConfigUnmarshalTest{ + { + Name: "string", + Expect: func() *helpersConfig { + c := newHelpersConfig() + c.Writer = NewWriterConfig(helpersTestType, helpersTestType) + c.Writer.OutputIDs = []string{"test"} + return c + }(), + }, + { + Name: "slice", + Expect: func() *helpersConfig { + c := newHelpersConfig() + c.Writer = NewWriterConfig(helpersTestType, helpersTestType) + c.Writer.OutputIDs = []string{"test1", "test2"} + return c + }(), + }, + { + Name: "invalid", + ExpectErr: true, + }, + }, + }.Run(t) } diff --git a/pkg/stanza/operator/transformer/router/router.go b/pkg/stanza/operator/transformer/router/router.go index 9bc784fefaf0..bd9291a51a51 100644 --- a/pkg/stanza/operator/transformer/router/router.go +++ b/pkg/stanza/operator/transformer/router/router.go @@ -48,15 +48,15 @@ func NewConfigWithID(operatorID string) *Config { // Config is the configuration of a router operator type Config struct { helper.BasicConfig `mapstructure:",squash" yaml:",inline"` - Routes []*RouteConfig `mapstructure:"routes" json:"routes" yaml:"routes"` - Default helper.OutputIDs `mapstructure:"default" json:"default" yaml:"default"` + Routes []*RouteConfig `mapstructure:"routes" json:"routes" yaml:"routes"` + Default []string `mapstructure:"default" json:"default" yaml:"default"` } // RouteConfig is the configuration of a route on a router operator type RouteConfig struct { helper.AttributerConfig `mapstructure:",squash" yaml:",inline"` - Expression string `mapstructure:"expr" json:"expr" yaml:"expr"` - OutputIDs helper.OutputIDs `mapstructure:"output" json:"output" yaml:"output"` + Expression string `mapstructure:"expr" json:"expr" yaml:"expr"` + OutputIDs []string `mapstructure:"output" json:"output" yaml:"output"` } // Build will build a router operator from the supplied configuration @@ -110,7 +110,7 @@ type Transformer struct { type Route struct { helper.Attributer Expression *vm.Program - OutputIDs helper.OutputIDs + OutputIDs []string OutputOperators []operator.Operator } diff --git a/pkg/stanza/operator/transformer/router/router_test.go b/pkg/stanza/operator/transformer/router/router_test.go index 9aef066cfe27..6921a84bfdf9 100644 --- a/pkg/stanza/operator/transformer/router/router_test.go +++ b/pkg/stanza/operator/transformer/router/router_test.go @@ -43,7 +43,7 @@ func TestTransformer(t *testing.T) { name string input *entry.Entry routes []*RouteConfig - defaultOutput helper.OutputIDs + defaultOutput []string expectedCounts map[string]int expectedAttributes map[string]interface{} }{