Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce simplified parsers #2972

Merged
merged 7 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
no need for json, mapstructure only
  • Loading branch information
jaronoff97 committed May 30, 2024
commit c3e4e61620cf1fad655c63a179749f25ecb03fdd
30 changes: 9 additions & 21 deletions internal/components/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package components

import (
"encoding/json"
"errors"
"regexp"
"strconv"
Expand All @@ -38,7 +37,7 @@
GetPortNumOrDefault(logr.Logger, int32) int32
}

type PortBuilderOption func(portBuilder *corev1.ServicePort)
type PortBuilderOption func(*corev1.ServicePort)

func WithTargetPort(targetPort int32) PortBuilderOption {
return func(servicePort *corev1.ServicePort) {
Expand All @@ -58,15 +57,15 @@
}
}

// ComponentType returns the type for a given component name.
// components have a name like:
// - mycomponent/custom
// - mycomponent
// we extract the "mycomponent" part and see if we have a parser for the component

Check failure on line 64 in internal/components/component.go

View workflow job for this annotation

GitHub Actions / Code standards (linting)

Comment should end in a period (godot)
func ComponentType(name string) string {
// components have a name like:
// - mycomponent/custom
// - mycomponent
// we extract the "mycomponent" part and see if we have a parser for the component
if strings.Contains(name, "/") {
return name[:strings.Index(name, "/")]
}

return name
}

Expand All @@ -77,7 +76,9 @@
r := regexp.MustCompile(":[0-9]+")

if r.MatchString(endpoint) {
port, err = strconv.ParseInt(strings.Replace(r.FindString(endpoint), ":", "", -1), 10, 32)
portStr := r.FindString(endpoint)
cleanedPortStr := strings.Replace(portStr, ":", "", -1)
port, err = strconv.ParseInt(cleanedPortStr, 10, 32)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Port numbers are 16-bit integers, so this should really be 16 instead of 32. We should also check if the value isn't negative.

In general, is there a reason not to use https://pkg.go.dev/net#SplitHostPort for parsing here, instead of the regex?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was copied over from the existing code, but i can swap it :)

Copy link
Contributor Author

@jaronoff97 jaronoff97 May 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually the problem with net.SplitHostPort is that it doesn't handle the case where it contains a scheme at the beginning (obv not a major issue) but that probably is why it wasn't used initially. The code ends up being the same here actually, so I think I may stick with this just changing to a 16 bit int... actually i think we need to use 32 bits here because otherwise we get an out of range error:

strconv.ParseInt: parsing "65535": value out of range

(ex)


if err != nil {
return 0, err
Expand All @@ -102,19 +103,6 @@
ParserName() string
}

func LoadMap[T any](m interface{}, in T) error {
// Convert map to JSON bytes
yamlData, err := json.Marshal(m)
if err != nil {
return err
}
// Unmarshal YAML into the provided struct
if err := json.Unmarshal(yamlData, in); err != nil {
return err
}
return nil
}

func ConstructServicePort(current *corev1.ServicePort, port int32) corev1.ServicePort {
return corev1.ServicePort{
Name: current.Name,
Expand Down
5 changes: 3 additions & 2 deletions internal/components/multi_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"

"github.com/go-logr/logr"
"github.com/mitchellh/mapstructure"
corev1 "k8s.io/api/core/v1"

"github.com/open-telemetry/opentelemetry-operator/internal/naming"
Expand All @@ -28,7 +29,7 @@ var _ ComponentPortParser = &MultiPortReceiver{}
// MultiProtocolEndpointConfig represents the minimal struct for a given YAML configuration input containing a map to
// a struct with either endpoint or listen_address.
type MultiProtocolEndpointConfig struct {
Protocols map[string]*SingleEndpointConfig `json:"protocols"`
Protocols map[string]*SingleEndpointConfig `mapstructure:"protocols"`
}

// MultiPortOption allows the setting of options for a MultiPortReceiver.
Expand All @@ -43,7 +44,7 @@ type MultiPortReceiver struct {

func (m *MultiPortReceiver) Ports(logger logr.Logger, config interface{}) ([]corev1.ServicePort, error) {
multiProtoEndpointCfg := &MultiProtocolEndpointConfig{}
if err := LoadMap[*MultiProtocolEndpointConfig](config, multiProtoEndpointCfg); err != nil {
if err := mapstructure.Decode(config, multiProtoEndpointCfg); err != nil {
return nil, err
}
var ports []corev1.ServicePort
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ func TestMultiEndpointReceiverParsers(t *testing.T) {
_, err := parser.Ports(logger, []interface{}{"junk"})

// verify
assert.ErrorContains(t, err, "cannot unmarshal array")
assert.ErrorContains(t, err, "expected a map, got 'slice'")
})
t.Run("good config, unknown protocol", func(t *testing.T) {
// prepare
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func TestDownstreamParsers(t *testing.T) {
_, err := parser.Ports(logger, func() {})

// verify
assert.ErrorContains(t, err, "unsupported type")
assert.ErrorContains(t, err, "expected a map, got 'func'")
})

t.Run("assigns the expected port", func(t *testing.T) {
Expand Down
7 changes: 4 additions & 3 deletions internal/components/single_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"

"github.com/go-logr/logr"
"github.com/mitchellh/mapstructure"
corev1 "k8s.io/api/core/v1"

"github.com/open-telemetry/opentelemetry-operator/internal/naming"
Expand All @@ -30,8 +31,8 @@ var (
// SingleEndpointConfig represents the minimal struct for a given YAML configuration input containing either
// endpoint or listen_address.
type SingleEndpointConfig struct {
Endpoint string `json:"endpoint,omitempty"`
ListenAddress string `json:"listen_address,omitempty"`
Endpoint string `mapstructure:"endpoint,omitempty"`
ListenAddress string `mapstructure:"listen_address,omitempty"`
}

func (g *SingleEndpointConfig) GetPortNumOrDefault(logger logr.Logger, p int32) int32 {
Expand Down Expand Up @@ -62,7 +63,7 @@ type SingleEndpointParser struct {

func (s *SingleEndpointParser) Ports(logger logr.Logger, config interface{}) ([]corev1.ServicePort, error) {
singleEndpointConfig := &SingleEndpointConfig{}
if err := LoadMap[*SingleEndpointConfig](config, singleEndpointConfig); err != nil {
if err := mapstructure.Decode(config, singleEndpointConfig); err != nil {
return nil, err
}
if _, err := singleEndpointConfig.GetPortNum(); err != nil && s.svcPort.Port == UnsetPort {
Expand Down
Loading