Skip to content

Commit 02a1fda

Browse files
authored
Remove ConfigValidate and add Validate on the Config struct (#2665)
Signed-off-by: Bogdan Drutu <[email protected]>
1 parent 892fe4f commit 02a1fda

33 files changed

+338
-365
lines changed

config/config.go

Lines changed: 0 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import (
2626

2727
"github.com/spf13/cast"
2828
"github.com/spf13/viper"
29-
"go.uber.org/zap"
3029

3130
"go.opentelemetry.io/collector/component"
3231
"go.opentelemetry.io/collector/config/configmodels"
@@ -42,15 +41,6 @@ const (
4241
errInvalidTypeAndNameKey
4342
errUnknownType
4443
errDuplicateName
45-
errMissingPipelines
46-
errPipelineMustHaveReceiver
47-
errPipelineMustHaveExporter
48-
errExtensionNotExists
49-
errPipelineReceiverNotExists
50-
errPipelineProcessorNotExists
51-
errPipelineExporterNotExists
52-
errMissingReceivers
53-
errMissingExporters
5444
errUnmarshalTopLevelStructureError
5545
)
5646

@@ -478,171 +468,6 @@ func loadPipelines(pipelinesConfig map[string]pipelineSettings) (configmodels.Pi
478468
return pipelines, nil
479469
}
480470

481-
// ValidateConfig validates config.
482-
func ValidateConfig(cfg *configmodels.Config, _ *zap.Logger) error {
483-
// This function performs basic validation of configuration. There may be more subtle
484-
// invalid cases that we currently don't check for but which we may want to add in
485-
// the future (e.g. disallowing receiving and exporting on the same endpoint).
486-
487-
if err := validateReceivers(cfg); err != nil {
488-
return err
489-
}
490-
491-
if err := validateExporters(cfg); err != nil {
492-
return err
493-
}
494-
495-
if err := validateService(cfg); err != nil {
496-
return err
497-
}
498-
499-
return nil
500-
}
501-
502-
func validateService(cfg *configmodels.Config) error {
503-
if err := validatePipelines(cfg); err != nil {
504-
return err
505-
}
506-
507-
return validateServiceExtensions(cfg)
508-
}
509-
510-
func validateServiceExtensions(cfg *configmodels.Config) error {
511-
if len(cfg.Service.Extensions) == 0 {
512-
return nil
513-
}
514-
515-
// Validate extensions.
516-
for _, ref := range cfg.Service.Extensions {
517-
// Check that the name referenced in the Service extensions exists in the top-level extensions
518-
if cfg.Extensions[ref] == nil {
519-
return &configError{
520-
code: errExtensionNotExists,
521-
msg: fmt.Sprintf("Service references extension %q which does not exist", ref),
522-
}
523-
}
524-
}
525-
526-
return nil
527-
}
528-
529-
func validatePipelines(cfg *configmodels.Config) error {
530-
// Must have at least one pipeline.
531-
if len(cfg.Service.Pipelines) == 0 {
532-
return &configError{code: errMissingPipelines, msg: "must have at least one pipeline"}
533-
}
534-
535-
// Validate pipelines.
536-
for _, pipeline := range cfg.Service.Pipelines {
537-
if err := validatePipeline(cfg, pipeline); err != nil {
538-
return err
539-
}
540-
}
541-
return nil
542-
}
543-
544-
func validatePipeline(cfg *configmodels.Config, pipeline *configmodels.Pipeline) error {
545-
if err := validatePipelineReceivers(cfg, pipeline); err != nil {
546-
return err
547-
}
548-
549-
if err := validatePipelineExporters(cfg, pipeline); err != nil {
550-
return err
551-
}
552-
553-
if err := validatePipelineProcessors(cfg, pipeline); err != nil {
554-
return err
555-
}
556-
557-
return nil
558-
}
559-
560-
func validatePipelineReceivers(cfg *configmodels.Config, pipeline *configmodels.Pipeline) error {
561-
if len(pipeline.Receivers) == 0 {
562-
return &configError{
563-
code: errPipelineMustHaveReceiver,
564-
msg: fmt.Sprintf("pipeline %q must have at least one receiver", pipeline.Name),
565-
}
566-
}
567-
568-
// Validate pipeline receiver name references.
569-
for _, ref := range pipeline.Receivers {
570-
// Check that the name referenced in the pipeline's receivers exists in the top-level receivers
571-
if cfg.Receivers[ref] == nil {
572-
return &configError{
573-
code: errPipelineReceiverNotExists,
574-
msg: fmt.Sprintf("pipeline %q references receiver %q which does not exist", pipeline.Name, ref),
575-
}
576-
}
577-
}
578-
579-
return nil
580-
}
581-
582-
func validatePipelineExporters(cfg *configmodels.Config, pipeline *configmodels.Pipeline) error {
583-
if len(pipeline.Exporters) == 0 {
584-
return &configError{
585-
code: errPipelineMustHaveExporter,
586-
msg: fmt.Sprintf("pipeline %q must have at least one exporter", pipeline.Name),
587-
}
588-
}
589-
590-
// Validate pipeline exporter name references.
591-
for _, ref := range pipeline.Exporters {
592-
// Check that the name referenced in the pipeline's Exporters exists in the top-level Exporters
593-
if cfg.Exporters[ref] == nil {
594-
return &configError{
595-
code: errPipelineExporterNotExists,
596-
msg: fmt.Sprintf("pipeline %q references exporter %q which does not exist", pipeline.Name, ref),
597-
}
598-
}
599-
}
600-
601-
return nil
602-
}
603-
604-
func validatePipelineProcessors(cfg *configmodels.Config, pipeline *configmodels.Pipeline) error {
605-
if len(pipeline.Processors) == 0 {
606-
return nil
607-
}
608-
609-
// Validate pipeline processor name references
610-
for _, ref := range pipeline.Processors {
611-
// Check that the name referenced in the pipeline's processors exists in the top-level processors.
612-
if cfg.Processors[ref] == nil {
613-
return &configError{
614-
code: errPipelineProcessorNotExists,
615-
msg: fmt.Sprintf("pipeline %q references processor %s which does not exist", pipeline.Name, ref),
616-
}
617-
}
618-
}
619-
620-
return nil
621-
}
622-
623-
func validateReceivers(cfg *configmodels.Config) error {
624-
// Currently there is no default receiver enabled. The configuration must specify at least one enabled receiver to
625-
// be valid.
626-
if len(cfg.Receivers) == 0 {
627-
return &configError{
628-
code: errMissingReceivers,
629-
msg: "no enabled receivers specified in config",
630-
}
631-
}
632-
return nil
633-
}
634-
635-
func validateExporters(cfg *configmodels.Config) error {
636-
// There must be at least one enabled exporter to be considered a valid configuration.
637-
if len(cfg.Exporters) == 0 {
638-
return &configError{
639-
code: errMissingExporters,
640-
msg: "no enabled exporters specified in config",
641-
}
642-
}
643-
return nil
644-
}
645-
646471
// expandEnvConfig creates a new viper config with expanded values for all the values (simple, list or map value).
647472
// It does not expand the keys.
648473
func expandEnvConfig(v *viper.Viper) {

config/config_test.go

Lines changed: 30 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121

2222
"github.com/stretchr/testify/assert"
2323
"github.com/stretchr/testify/require"
24-
"go.uber.org/zap"
2524

2625
"go.opentelemetry.io/collector/component"
2726
"go.opentelemetry.io/collector/component/componenttest"
@@ -414,47 +413,40 @@ func TestDecodeConfig_Invalid(t *testing.T) {
414413
expected configErrorCode // expected error (if nil any error is acceptable)
415414
expectedMessage string // string that the error must contain
416415
}{
417-
{name: "empty-config"},
418-
{name: "missing-all-sections"},
419-
{name: "missing-exporters", expected: errMissingExporters},
420-
{name: "missing-receivers", expected: errMissingReceivers},
421-
{name: "missing-processors"},
422-
{name: "invalid-extension-name", expected: errExtensionNotExists},
423-
{name: "invalid-receiver-name"},
424-
{name: "invalid-receiver-reference", expected: errPipelineReceiverNotExists},
425-
{name: "missing-extension-type", expected: errInvalidTypeAndNameKey},
426-
{name: "missing-receiver-type", expected: errInvalidTypeAndNameKey},
427-
{name: "missing-exporter-name-after-slash", expected: errInvalidTypeAndNameKey},
428-
{name: "missing-processor-type", expected: errInvalidTypeAndNameKey},
429-
{name: "missing-pipelines", expected: errMissingPipelines},
430-
{name: "pipeline-must-have-exporter-logs", expected: errPipelineMustHaveExporter},
431-
{name: "pipeline-must-have-exporter-metrics", expected: errPipelineMustHaveExporter},
432-
{name: "pipeline-must-have-exporter-traces", expected: errPipelineMustHaveExporter},
433-
{name: "pipeline-must-have-receiver-logs", expected: errPipelineMustHaveReceiver},
434-
{name: "pipeline-must-have-receiver-metrics", expected: errPipelineMustHaveReceiver},
435-
{name: "pipeline-must-have-receiver-traces", expected: errPipelineMustHaveReceiver},
436-
{name: "pipeline-exporter-not-exists", expected: errPipelineExporterNotExists},
437-
{name: "pipeline-processor-not-exists", expected: errPipelineProcessorNotExists},
416+
{name: "invalid-extension-type", expected: errInvalidTypeAndNameKey},
417+
{name: "invalid-receiver-type", expected: errInvalidTypeAndNameKey},
418+
{name: "invalid-exporter-type", expected: errInvalidTypeAndNameKey},
419+
{name: "invalid-processor-type", expected: errInvalidTypeAndNameKey},
420+
{name: "invalid-pipeline-type", expected: errInvalidTypeAndNameKey},
421+
422+
{name: "invalid-extension-name-after-slash", expected: errInvalidTypeAndNameKey},
423+
{name: "invalid-receiver-name-after-slash", expected: errInvalidTypeAndNameKey},
424+
{name: "invalid-exporter-name-after-slash", expected: errInvalidTypeAndNameKey},
425+
{name: "invalid-processor-name-after-slash", expected: errInvalidTypeAndNameKey},
426+
{name: "invalid-pipeline-name-after-slash", expected: errInvalidTypeAndNameKey},
427+
438428
{name: "unknown-extension-type", expected: errUnknownType, expectedMessage: "extensions"},
439429
{name: "unknown-receiver-type", expected: errUnknownType, expectedMessage: "receivers"},
440430
{name: "unknown-exporter-type", expected: errUnknownType, expectedMessage: "exporters"},
441431
{name: "unknown-processor-type", expected: errUnknownType, expectedMessage: "processors"},
442-
{name: "invalid-service-extensions-value", expected: errUnmarshalTopLevelStructureError, expectedMessage: "service"},
443-
{name: "invalid-sequence-value", expected: errUnmarshalTopLevelStructureError, expectedMessage: "pipelines"},
444-
{name: "invalid-pipeline-type", expected: errUnknownType, expectedMessage: "pipelines"},
445-
{name: "invalid-pipeline-type-and-name", expected: errInvalidTypeAndNameKey},
432+
{name: "unknown-pipeline-type", expected: errUnknownType, expectedMessage: "pipelines"},
433+
446434
{name: "duplicate-extension", expected: errDuplicateName, expectedMessage: "extensions"},
447435
{name: "duplicate-receiver", expected: errDuplicateName, expectedMessage: "receivers"},
448436
{name: "duplicate-exporter", expected: errDuplicateName, expectedMessage: "exporters"},
449437
{name: "duplicate-processor", expected: errDuplicateName, expectedMessage: "processors"},
450438
{name: "duplicate-pipeline", expected: errDuplicateName, expectedMessage: "pipelines"},
439+
451440
{name: "invalid-top-level-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "top level"},
452441
{name: "invalid-extension-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "extensions"},
453-
{name: "invalid-service-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "service"},
454442
{name: "invalid-receiver-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "receivers"},
455443
{name: "invalid-processor-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "processors"},
456444
{name: "invalid-exporter-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "exporters"},
445+
{name: "invalid-service-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "service"},
446+
{name: "invalid-service-extensions-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "service"},
457447
{name: "invalid-pipeline-section", expected: errUnmarshalTopLevelStructureError, expectedMessage: "pipelines"},
448+
{name: "invalid-sequence-value", expected: errUnmarshalTopLevelStructureError, expectedMessage: "pipelines"},
449+
458450
{name: "invalid-extension-sub-config", expected: errUnmarshalTopLevelStructureError},
459451
{name: "invalid-exporter-sub-config", expected: errUnmarshalTopLevelStructureError},
460452
{name: "invalid-processor-sub-config", expected: errUnmarshalTopLevelStructureError},
@@ -468,9 +460,8 @@ func TestDecodeConfig_Invalid(t *testing.T) {
468460
for _, test := range testCases {
469461
t.Run(test.name, func(t *testing.T) {
470462
_, err := loadConfigFile(t, path.Join(".", "testdata", test.name+".yaml"), factories)
471-
if err == nil {
472-
t.Error("expected error but succeeded")
473-
} else if test.expected != 0 {
463+
require.Error(t, err)
464+
if test.expected != 0 {
474465
cfgErr, ok := err.(*configError)
475466
if !ok {
476467
t.Errorf("expected config error code %v but got a different error '%v'", test.expected, err)
@@ -486,25 +477,19 @@ func TestDecodeConfig_Invalid(t *testing.T) {
486477
}
487478
}
488479

489-
func TestLoadEmptyConfig(t *testing.T) {
480+
func TestLoadEmpty(t *testing.T) {
490481
factories, err := componenttest.ExampleComponents()
491482
assert.NoError(t, err)
492483

493-
// Open the file for reading.
494-
file, err := os.Open(path.Join(".", "testdata", "empty-config.yaml"))
495-
require.NoError(t, err)
496-
497-
defer func() {
498-
require.NoError(t, file.Close())
499-
}()
484+
_, err = loadConfigFile(t, path.Join(".", "testdata", "empty-config.yaml"), factories)
485+
assert.NoError(t, err)
486+
}
500487

501-
// Read yaml config from file
502-
v := NewViper()
503-
v.SetConfigType("yaml")
504-
require.NoError(t, v.ReadConfig(file))
488+
func TestLoadEmptyAllSections(t *testing.T) {
489+
factories, err := componenttest.ExampleComponents()
490+
assert.NoError(t, err)
505491

506-
// Load the config from viper using the given factories.
507-
_, err = Load(v, factories)
492+
_, err = loadConfigFile(t, path.Join(".", "testdata", "empty-all-sections.yaml"), factories)
508493
assert.NoError(t, err)
509494
}
510495

@@ -515,11 +500,7 @@ func loadConfigFile(t *testing.T, fileName string, factories component.Factories
515500
require.NoErrorf(t, v.ReadInConfig(), "unable to read the file %v", fileName)
516501

517502
// Load the config from viper using the given factories.
518-
cfg, err := Load(v, factories)
519-
if err != nil {
520-
return nil, err
521-
}
522-
return cfg, ValidateConfig(cfg, zap.NewNop())
503+
return Load(v, factories)
523504
}
524505

525506
type nestedConfig struct {

0 commit comments

Comments
 (0)