diff --git a/component/metadata/metadata.go b/component/metadata/metadata.go index 0c58f35475ce..8ff2587ae8e3 100644 --- a/component/metadata/metadata.go +++ b/component/metadata/metadata.go @@ -20,38 +20,42 @@ import ( type Type struct { Name string // Returns true if provided args include this type (including nested structs) - ExistsInArgsFn func(args component.Arguments) bool + existsInArgsFn func(args component.Arguments) bool // Returns true if provided exports include this type (including nested structs) - ExistsInExportsFn func(exports component.Exports) bool + existsInExportsFn func(exports component.Exports) bool +} + +func (t Type) String() string { + return fmt.Sprintf("Type[%s]", t.Name) } var ( TypeTargets = Type{ Name: "Targets", - ExistsInArgsFn: func(args component.Arguments) bool { + existsInArgsFn: func(args component.Arguments) bool { return hasFieldOfType(args, reflect.TypeOf([]discovery.Target{})) }, - ExistsInExportsFn: func(exports component.Exports) bool { + existsInExportsFn: func(exports component.Exports) bool { return hasFieldOfType(exports, reflect.TypeOf([]discovery.Target{})) }, } TypeLokiLogs = Type{ Name: "Loki `LogsReceiver`", - ExistsInArgsFn: func(args component.Arguments) bool { + existsInArgsFn: func(args component.Arguments) bool { return hasFieldOfType(args, reflect.TypeOf([]loki.LogsReceiver{})) }, - ExistsInExportsFn: func(exports component.Exports) bool { + existsInExportsFn: func(exports component.Exports) bool { return hasFieldOfType(exports, reflect.TypeOf(loki.NewLogsReceiver())) }, } TypePromMetricsReceiver = Type{ Name: "Prometheus `MetricsReceiver`", - ExistsInArgsFn: func(args component.Arguments) bool { + existsInArgsFn: func(args component.Arguments) bool { return hasFieldOfType(args, reflect.TypeOf([]storage.Appendable{})) }, - ExistsInExportsFn: func(exports component.Exports) bool { + existsInExportsFn: func(exports component.Exports) bool { var a *storage.Appendable = nil return hasFieldOfType(exports, reflect.TypeOf(a).Elem()) }, @@ -59,10 +63,10 @@ var ( TypePyroProfilesReceiver = Type{ Name: "Pyroscope `ProfilesReceiver`", - ExistsInArgsFn: func(args component.Arguments) bool { + existsInArgsFn: func(args component.Arguments) bool { return hasFieldOfType(args, reflect.TypeOf([]pyroscope.Appendable{})) }, - ExistsInExportsFn: func(exports component.Exports) bool { + existsInExportsFn: func(exports component.Exports) bool { var a *pyroscope.Appendable = nil return hasFieldOfType(exports, reflect.TypeOf(a).Elem()) }, @@ -70,10 +74,10 @@ var ( TypeOTELReceiver = Type{ Name: "OpenTelemetry `otelcol.Consumer`", - ExistsInArgsFn: func(args component.Arguments) bool { + existsInArgsFn: func(args component.Arguments) bool { return hasFieldOfType(args, reflect.TypeOf([]otelcol.Consumer{})) }, - ExistsInExportsFn: func(exports component.Exports) bool { + existsInExportsFn: func(exports component.Exports) bool { var a *otelcol.Consumer = nil return hasFieldOfType(exports, reflect.TypeOf(a).Elem()) }, @@ -134,10 +138,10 @@ func ForComponent(name string) (Metadata, error) { func inferMetadata(args component.Arguments, exports component.Exports) Metadata { m := Metadata{} for _, t := range AllTypes { - if t.ExistsInArgsFn(args) { + if t.existsInArgsFn(args) { m.accepts = append(m.accepts, t) } - if t.ExistsInExportsFn(exports) { + if t.existsInExportsFn(exports) { m.exports = append(m.exports, t) } } diff --git a/component/metadata/metadata_test.go b/component/metadata/metadata_test.go index e4ffa6e2ae17..a60376b2c2d1 100644 --- a/component/metadata/metadata_test.go +++ b/component/metadata/metadata_test.go @@ -24,13 +24,12 @@ func Test_inferMetadata(t *testing.T) { }, { name: "loki.echo", - expected: Metadata{accepts: []Type{TypeLokiLogs}}, + expected: Metadata{exports: []Type{TypeLokiLogs}}, }, { name: "loki.source.file", expected: Metadata{ - accepts: []Type{TypeTargets}, - exports: []Type{TypeLokiLogs}, + accepts: []Type{TypeTargets, TypeLokiLogs}, }, }, { @@ -40,12 +39,56 @@ func Test_inferMetadata(t *testing.T) { exports: []Type{TypeLokiLogs}, }, }, + { + name: "prometheus.relabel", + expected: Metadata{ + accepts: []Type{TypePromMetricsReceiver}, + exports: []Type{TypePromMetricsReceiver}, + }, + }, + { + name: "prometheus.remote_write", + expected: Metadata{ + accepts: []Type{}, + exports: []Type{TypePromMetricsReceiver}, + }, + }, + { + name: "otelcol.exporter.otlp", + expected: Metadata{ + accepts: []Type{}, + exports: []Type{TypeOTELReceiver}, + }, + }, + { + name: "otelcol.processor.filter", + expected: Metadata{ + accepts: []Type{TypeOTELReceiver}, + exports: []Type{TypeOTELReceiver}, + }, + }, + { + name: "faro.receiver", + expected: Metadata{ + accepts: []Type{TypeLokiLogs, TypeOTELReceiver}, + exports: []Type{}, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { actual, err := ForComponent(tt.name) require.NoError(t, err) - require.Equal(t, tt.expected, actual) + + compareSlices := func(expected, actual []Type, name string) { + require.Equal(t, len(expected), len(actual), "expected %d %s types, got %d; expected: %v, actual: %v", len(expected), name, len(actual), expected, actual) + for i := range expected { + require.Equal(t, expected[i].Name, actual[i].Name, "expected %s type at %d to be %q, got %q", name, i, expected[i].Name, actual[i].Name) + } + } + + compareSlices(tt.expected.AllTypesAccepted(), actual.AllTypesAccepted(), "accepted") + compareSlices(tt.expected.AllTypesExported(), actual.AllTypesExported(), "exported") }) } }