diff --git a/cmd/jaeger/internal/.nocover b/cmd/jaeger/internal/.nocover deleted file mode 100644 index 46911e9377b..00000000000 --- a/cmd/jaeger/internal/.nocover +++ /dev/null @@ -1,2 +0,0 @@ -FIXME - diff --git a/cmd/jaeger/internal/command.go b/cmd/jaeger/internal/command.go index 478e8ec327a..072a05e8cc1 100644 --- a/cmd/jaeger/internal/command.go +++ b/cmd/jaeger/internal/command.go @@ -40,17 +40,7 @@ func Command() *cobra.Command { // are present in the args. If not, we create one with all-in-one configuration. otelRunE := cmd.RunE cmd.RunE = func(cmd *cobra.Command, args []string) error { - configFlag := cmd.Flag("config") - if !configFlag.Changed { - log.Print("No '--config' flags detected, using default All-in-One configuration with memory storage.") - log.Print("To customize All-in-One behavior, pass a proper configuration.") - data, err := yamlAllInOne.ReadFile("all-in-one.yaml") - if err != nil { - return fmt.Errorf("cannot read embedded all-in-one configuration: %w", err) - } - configFlag.Value.Set("yaml:" + string(data)) - } - return otelRunE(cmd, args) + return checkConfigAndRun(cmd, args, yamlAllInOne.ReadFile, otelRunE) } cmd.Short = description @@ -58,3 +48,22 @@ func Command() *cobra.Command { return cmd } + +func checkConfigAndRun( + cmd *cobra.Command, + args []string, + getCfg func(name string) ([]byte, error), + runE func(cmd *cobra.Command, args []string) error, +) error { + configFlag := cmd.Flag("config") + if !configFlag.Changed { + log.Print("No '--config' flags detected, using default All-in-One configuration with memory storage.") + log.Print("To customize All-in-One behavior, pass a proper configuration.") + data, err := getCfg("all-in-one.yaml") + if err != nil { + return fmt.Errorf("cannot read embedded all-in-one configuration: %w", err) + } + configFlag.Value.Set("yaml:" + string(data)) + } + return runE(cmd, args) +} diff --git a/cmd/jaeger/internal/command_test.go b/cmd/jaeger/internal/command_test.go new file mode 100644 index 00000000000..f2c20ebbfad --- /dev/null +++ b/cmd/jaeger/internal/command_test.go @@ -0,0 +1,63 @@ +// Copyright (c) 2024 The Jaeger 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 internal + +import ( + "errors" + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCommand(t *testing.T) { + cmd := Command() + + assert.NotNil(t, cmd) + assert.Equal(t, "jaeger", cmd.Use) + assert.Equal(t, description, cmd.Long) + + require.NotNil(t, cmd.RunE) + + cmd.ParseFlags([]string{"--config", "bad-file-name"}) + err := cmd.Execute() + require.ErrorContains(t, err, "bad-file-name") +} + +func TestCheckConfigAndRun_DefaultConfig(t *testing.T) { + cmd := &cobra.Command{ + RunE: func(cmd *cobra.Command, args []string) error { + return nil + }, + } + cmd.Flags().String("config", "", "path to config file") + getCfg := func(name string) ([]byte, error) { + return []byte("default-config"), nil + } + runE := func(cmd *cobra.Command, args []string) error { + return nil + } + + err := checkConfigAndRun(cmd, nil, getCfg, runE) + require.NoError(t, err) + + errGetCfg := errors.New("error") + getCfgErr := func(name string) ([]byte, error) { + return nil, errGetCfg + } + err = checkConfigAndRun(cmd, nil, getCfgErr, runE) + require.ErrorIs(t, err, errGetCfg) +} diff --git a/cmd/jaeger/internal/components.go b/cmd/jaeger/internal/components.go index a93cc19f9b6..2b758a55990 100644 --- a/cmd/jaeger/internal/components.go +++ b/cmd/jaeger/internal/components.go @@ -9,6 +9,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerreceiver" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kafkareceiver" "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipkinreceiver" + "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/connector/forwardconnector" "go.opentelemetry.io/collector/exporter" @@ -30,11 +31,29 @@ import ( "github.com/jaegertracing/jaeger/cmd/jaeger/internal/extension/jaegerstorage" ) -func components() (otelcol.Factories, error) { +type builders struct { + extension func(factories ...extension.Factory) (map[component.Type]extension.Factory, error) + receiver func(factories ...receiver.Factory) (map[component.Type]receiver.Factory, error) + exporter func(factories ...exporter.Factory) (map[component.Type]exporter.Factory, error) + processor func(factories ...processor.Factory) (map[component.Type]processor.Factory, error) + connector func(factories ...connector.Factory) (map[component.Type]connector.Factory, error) +} + +func defaultBuilders() builders { + return builders{ + extension: extension.MakeFactoryMap, + receiver: receiver.MakeFactoryMap, + exporter: exporter.MakeFactoryMap, + processor: processor.MakeFactoryMap, + connector: connector.MakeFactoryMap, + } +} + +func (b builders) build() (otelcol.Factories, error) { var err error factories := otelcol.Factories{} - factories.Extensions, err = extension.MakeFactoryMap( + factories.Extensions, err = b.extension( // standard ballastextension.NewFactory(), zpagesextension.NewFactory(), @@ -47,7 +66,7 @@ func components() (otelcol.Factories, error) { return otelcol.Factories{}, err } - factories.Receivers, err = receiver.MakeFactoryMap( + factories.Receivers, err = b.receiver( // standard otlpreceiver.NewFactory(), // add-ons @@ -59,7 +78,7 @@ func components() (otelcol.Factories, error) { return otelcol.Factories{}, err } - factories.Exporters, err = exporter.MakeFactoryMap( + factories.Exporters, err = b.exporter( // standard loggingexporter.NewFactory(), otlpexporter.NewFactory(), @@ -73,7 +92,7 @@ func components() (otelcol.Factories, error) { return otelcol.Factories{}, err } - factories.Processors, err = processor.MakeFactoryMap( + factories.Processors, err = b.processor( // standard batchprocessor.NewFactory(), memorylimiterprocessor.NewFactory(), @@ -84,7 +103,7 @@ func components() (otelcol.Factories, error) { return otelcol.Factories{}, err } - factories.Connectors, err = connector.MakeFactoryMap( + factories.Connectors, err = b.connector( // standard forwardconnector.NewFactory(), // add-ons @@ -96,3 +115,7 @@ func components() (otelcol.Factories, error) { return factories, nil } + +func components() (otelcol.Factories, error) { + return defaultBuilders().build() +} diff --git a/cmd/jaeger/internal/components_test.go b/cmd/jaeger/internal/components_test.go new file mode 100644 index 00000000000..fed360d0bdd --- /dev/null +++ b/cmd/jaeger/internal/components_test.go @@ -0,0 +1,84 @@ +// Copyright (c) 2024 The Jaeger 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 internal + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/connector" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/extension" + "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/receiver" +) + +func TestComponents(t *testing.T) { + factories, err := components() + + require.NoError(t, err) + + assert.NotNil(t, factories.Extensions) + assert.NotNil(t, factories.Receivers) + assert.NotNil(t, factories.Exporters) + assert.NotNil(t, factories.Processors) + assert.NotNil(t, factories.Connectors) + + _, jaegerReceiverFactoryExists := factories.Receivers["jaeger"] + assert.True(t, jaegerReceiverFactoryExists) +} + +func TestGetOtelcolFactories(t *testing.T) { + errMock := errors.New("mock error") + { + b := defaultBuilders() + b.extension = mockFactoryMap[extension.Factory](errMock) + _, err := b.build() + require.ErrorIs(t, err, errMock) + } + { + b := defaultBuilders() + b.receiver = mockFactoryMap[receiver.Factory](errMock) + _, err := b.build() + require.ErrorIs(t, err, errMock) + } + { + b := defaultBuilders() + b.exporter = mockFactoryMap[exporter.Factory](errMock) + _, err := b.build() + require.ErrorIs(t, err, errMock) + } + { + b := defaultBuilders() + b.processor = mockFactoryMap[processor.Factory](errMock) + _, err := b.build() + require.ErrorIs(t, err, errMock) + } + { + b := defaultBuilders() + b.connector = mockFactoryMap[connector.Factory](errMock) + _, err := b.build() + require.ErrorIs(t, err, errMock) + } +} + +func mockFactoryMap[FACTORY component.Factory](err error) func(factories ...FACTORY) (map[component.Type]FACTORY, error) { + return func(factories ...FACTORY) (map[component.Type]FACTORY, error) { + return nil, err + } +} diff --git a/cmd/jaeger/internal/package_test.go b/cmd/jaeger/internal/package_test.go new file mode 100644 index 00000000000..5f1c10eaf08 --- /dev/null +++ b/cmd/jaeger/internal/package_test.go @@ -0,0 +1,25 @@ +// Copyright (c) 2024 The Jaeger 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 internal + +import ( + "testing" + + "github.com/jaegertracing/jaeger/pkg/testutils" +) + +func TestMain(m *testing.M) { + testutils.VerifyGoLeaks(m) +}