From 98975742d62c73fd308c5c3b058413356ad45467 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 23 Oct 2024 10:18:14 -0700 Subject: [PATCH] Add UnmarshalText for StabilityLevel (#11520) This PR also starts using the fact that StabilityLevel implements UnmarshalText and cleans up the mdatagen stability structure. Signed-off-by: Bogdan Drutu --- .chloggen/stabilityunmarshal.yaml | 25 ++++++++ cmd/mdatagen/internal/metadata_test.go | 2 +- cmd/mdatagen/internal/status.go | 46 +++------------ component/component.go | 25 ++++++++ component/component_test.go | 82 +++++++++++++++++++++----- 5 files changed, 126 insertions(+), 54 deletions(-) create mode 100644 .chloggen/stabilityunmarshal.yaml diff --git a/.chloggen/stabilityunmarshal.yaml b/.chloggen/stabilityunmarshal.yaml new file mode 100644 index 00000000000..62a6f67fecd --- /dev/null +++ b/.chloggen/stabilityunmarshal.yaml @@ -0,0 +1,25 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: component + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add UnmarshalText for StabilityLevel + +# One or more tracking issues or pull requests related to the change +issues: [11520] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [api] diff --git a/cmd/mdatagen/internal/metadata_test.go b/cmd/mdatagen/internal/metadata_test.go index 6b68cfd91e5..83b102ce315 100644 --- a/cmd/mdatagen/internal/metadata_test.go +++ b/cmd/mdatagen/internal/metadata_test.go @@ -39,7 +39,7 @@ func TestValidate(t *testing.T) { }, { name: "testdata/invalid_stability.yaml", - wantErr: "decoding failed due to the following error(s):\n\nerror decoding 'status.stability': invalid stability level: incorrectstability", + wantErr: "decoding failed due to the following error(s):\n\nerror decoding 'status.stability': unsupported stability level: \"incorrectstability\"", }, { name: "testdata/no_stability_component.yaml", diff --git a/cmd/mdatagen/internal/status.go b/cmd/mdatagen/internal/status.go index ef06ac1a6a1..0b991c9243a 100644 --- a/cmd/mdatagen/internal/status.go +++ b/cmd/mdatagen/internal/status.go @@ -7,10 +7,8 @@ import ( "errors" "fmt" "sort" - "strings" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/confmap" ) // Distros is a collection of distributions that can be referenced in the metadata.yaml files. @@ -70,7 +68,7 @@ func (s *Status) Validate() error { if err := s.validateClass(); err != nil { errs = errors.Join(errs, err) } - if err := s.validateStability(); err != nil { + if err := s.Stability.Validate(); err != nil { errs = errors.Join(errs, err) } return errs @@ -86,16 +84,18 @@ func (s *Status) validateClass() error { return nil } -func (s *Status) validateStability() error { +type StabilityMap map[component.StabilityLevel][]string + +func (ms StabilityMap) Validate() error { var errs error - if len(s.Stability) == 0 { + if len(ms) == 0 { return errors.New("missing stability") } - for stability, component := range s.Stability { - if len(component) == 0 { + for stability, cmps := range ms { + if len(cmps) == 0 { errs = errors.Join(errs, fmt.Errorf("missing component for stability: %v", stability)) } - for _, c := range component { + for _, c := range cmps { if c != "metrics" && c != "traces" && c != "logs" && @@ -123,33 +123,3 @@ func (s *Status) validateStability() error { } return errs } - -type StabilityMap map[component.StabilityLevel][]string - -func (ms *StabilityMap) Unmarshal(parser *confmap.Conf) error { - *ms = make(StabilityMap) - raw := make(map[string][]string) - err := parser.Unmarshal(&raw) - if err != nil { - return err - } - for k, v := range raw { - switch strings.ToLower(k) { - case strings.ToLower(component.StabilityLevelUnmaintained.String()): - (*ms)[component.StabilityLevelUnmaintained] = v - case strings.ToLower(component.StabilityLevelDeprecated.String()): - (*ms)[component.StabilityLevelDeprecated] = v - case strings.ToLower(component.StabilityLevelDevelopment.String()): - (*ms)[component.StabilityLevelDevelopment] = v - case strings.ToLower(component.StabilityLevelAlpha.String()): - (*ms)[component.StabilityLevelAlpha] = v - case strings.ToLower(component.StabilityLevelBeta.String()): - (*ms)[component.StabilityLevelBeta] = v - case strings.ToLower(component.StabilityLevelStable.String()): - (*ms)[component.StabilityLevelStable] = v - default: - return errors.New("invalid stability level: " + k) - } - } - return nil -} diff --git a/component/component.go b/component/component.go index 59c6cace1fc..90397a89aca 100644 --- a/component/component.go +++ b/component/component.go @@ -7,6 +7,8 @@ package component // import "go.opentelemetry.io/collector/component" import ( "context" + "fmt" + "strings" ) // Component is either a receiver, exporter, processor, connector, or an extension. @@ -119,6 +121,29 @@ const ( StabilityLevelStable ) +func (sl *StabilityLevel) UnmarshalText(in []byte) error { + str := strings.ToLower(string(in)) + switch str { + case "undefined": + *sl = StabilityLevelUndefined + case "unmaintained": + *sl = StabilityLevelUnmaintained + case "deprecated": + *sl = StabilityLevelDeprecated + case "development": + *sl = StabilityLevelDevelopment + case "alpha": + *sl = StabilityLevelAlpha + case "beta": + *sl = StabilityLevelBeta + case "stable": + *sl = StabilityLevelStable + default: + return fmt.Errorf("unsupported stability level: %q", string(in)) + } + return nil +} + func (sl StabilityLevel) String() string { switch sl { case StabilityLevelUndefined: diff --git a/component/component_test.go b/component/component_test.go index 8a6c7d669dd..8ca603ceda4 100644 --- a/component/component_test.go +++ b/component/component_test.go @@ -10,24 +10,76 @@ import ( ) func TestKindString(t *testing.T) { - assert.EqualValues(t, "", Kind(0).String()) - assert.EqualValues(t, "Receiver", KindReceiver.String()) - assert.EqualValues(t, "Processor", KindProcessor.String()) - assert.EqualValues(t, "Exporter", KindExporter.String()) - assert.EqualValues(t, "Extension", KindExtension.String()) - assert.EqualValues(t, "Connector", KindConnector.String()) - assert.EqualValues(t, "", Kind(100).String()) + assert.Equal(t, "", Kind(0).String()) + assert.Equal(t, "Receiver", KindReceiver.String()) + assert.Equal(t, "Processor", KindProcessor.String()) + assert.Equal(t, "Exporter", KindExporter.String()) + assert.Equal(t, "Extension", KindExtension.String()) + assert.Equal(t, "Connector", KindConnector.String()) + assert.Equal(t, "", Kind(100).String()) +} + +func TestStabilityLevelUnmarshal(t *testing.T) { + tests := []struct { + input string + output StabilityLevel + expectedErr string + }{ + { + input: "Undefined", + output: StabilityLevelUndefined, + }, + { + input: "UnmaintaineD", + output: StabilityLevelUnmaintained, + }, + { + input: "DepreCated", + output: StabilityLevelDeprecated, + }, + { + input: "Development", + output: StabilityLevelDevelopment, + }, + { + input: "alpha", + output: StabilityLevelAlpha, + }, + { + input: "BETA", + output: StabilityLevelBeta, + }, + { + input: "sTABLe", + output: StabilityLevelStable, + }, + { + input: "notfound", + expectedErr: "unsupported stability level: \"notfound\"", + }, + } + for _, test := range tests { + t.Run(test.input, func(t *testing.T) { + var sl StabilityLevel + err := sl.UnmarshalText([]byte(test.input)) + if test.expectedErr != "" { + assert.EqualError(t, err, test.expectedErr) + } else { + assert.Equal(t, test.output, sl) + } + }) + } } func TestStabilityLevelString(t *testing.T) { - assert.EqualValues(t, "Undefined", StabilityLevelUndefined.String()) - assert.EqualValues(t, "Unmaintained", StabilityLevelUnmaintained.String()) - assert.EqualValues(t, "Deprecated", StabilityLevelDeprecated.String()) - assert.EqualValues(t, "Development", StabilityLevelDevelopment.String()) - assert.EqualValues(t, "Alpha", StabilityLevelAlpha.String()) - assert.EqualValues(t, "Beta", StabilityLevelBeta.String()) - assert.EqualValues(t, "Stable", StabilityLevelStable.String()) - assert.EqualValues(t, "", StabilityLevel(100).String()) + assert.Equal(t, "Undefined", StabilityLevelUndefined.String()) + assert.Equal(t, "Unmaintained", StabilityLevelUnmaintained.String()) + assert.Equal(t, "Deprecated", StabilityLevelDeprecated.String()) + assert.Equal(t, "Development", StabilityLevelDevelopment.String()) + assert.Equal(t, "Alpha", StabilityLevelAlpha.String()) + assert.Equal(t, "Beta", StabilityLevelBeta.String()) + assert.Equal(t, "Stable", StabilityLevelStable.String()) + assert.Equal(t, "", StabilityLevel(100).String()) } func TestStabilityLevelLogMessage(t *testing.T) {