Skip to content

Commit 8fbfa7c

Browse files
committed
Refactor how service metrics endpoint parsing works
Now, when there would be an error it gets logged and the default values are returned. With this refactor the method encapsulates all defaulting logic that was slightly spread around different places.
1 parent b01c2c4 commit 8fbfa7c

File tree

6 files changed

+33
-55
lines changed

6 files changed

+33
-55
lines changed

apis/v1beta1/collector_webhook_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ func TestCollectorDefaultingWebhook(t *testing.T) {
555555
ctx := context.Background()
556556
err := cvw.Default(ctx, &test.otelcol)
557557
if test.expected.Spec.Config.Service.Telemetry == nil {
558-
assert.NoError(t, test.expected.Spec.Config.Service.ApplyDefaults(), "could not apply defaults")
558+
assert.NoError(t, test.expected.Spec.Config.Service.ApplyDefaults(logr.Discard()), "could not apply defaults")
559559
}
560560
assert.NoError(t, err)
561561
assert.Equal(t, test.expected, test.otelcol)

apis/v1beta1/config.go

+24-38
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"bytes"
1919
"encoding/json"
2020
"fmt"
21-
"net"
2221
"reflect"
2322
"sort"
2423
"strconv"
@@ -269,7 +268,7 @@ func (c *Config) getEnvironmentVariablesForComponentKinds(logger logr.Logger, co
269268

270269
// applyDefaultForComponentKinds applies defaults to the endpoints for the given ComponentKind(s).
271270
func (c *Config) applyDefaultForComponentKinds(logger logr.Logger, componentKinds ...ComponentKind) error {
272-
if err := c.Service.ApplyDefaults(); err != nil {
271+
if err := c.Service.ApplyDefaults(logger); err != nil {
273272
return err
274273
}
275274
enabledComponents := c.GetEnabledComponents()
@@ -427,59 +426,46 @@ type Service struct {
427426
Pipelines map[string]*Pipeline `json:"pipelines" yaml:"pipelines"`
428427
}
429428

430-
const defaultServicePort int32 = 8888
429+
type serviceParseError string
431430

432-
// MetricsEndpoint gets the port number and host address for the metrics endpoint from the collector config if it has been set.
433-
func (s *Service) MetricsEndpoint() (string, int32, error) {
434-
defaultAddr := "0.0.0.0"
435-
if s.GetTelemetry() == nil {
436-
// telemetry isn't set, use the default
437-
return defaultAddr, defaultServicePort, nil
438-
}
439-
host, port, netErr := net.SplitHostPort(s.GetTelemetry().Metrics.Address)
440-
if netErr != nil && strings.Contains(netErr.Error(), "missing port in address") {
441-
return defaultAddr, defaultServicePort, nil
442-
} else if netErr != nil {
443-
return "", 0, netErr
444-
}
445-
i64, err := strconv.ParseInt(port, 10, 32)
446-
if err != nil {
447-
return "", 0, err
448-
}
449-
450-
if host == "" {
451-
host = defaultAddr
452-
}
453-
454-
return host, int32(i64), nil
431+
func (s serviceParseError) Error() string {
432+
return string(s)
455433
}
456434

457-
// NaivePort attempts gets the port number from the host address without doing any validation regarding the address itself.
435+
const (
436+
defaultServicePort int32 = 8888
437+
defaultServiceHost = "0.0.0.0"
438+
)
439+
440+
// MetricsEndpoint attempts gets the host and port number from the host address without doing any validation regarding the
441+
// address itself.
458442
// It works even before env var expansion happens, when a simple `net.SplitHostPort` would fail because of the extra colon
459443
// from the env var, i.e. the address looks like "${env:POD_IP}:4317" or "${env:POD_IP}".
460444
// It does not work in cases which the port itself is a variable, i.e. "${env:POD_IP}:${env:PORT}".
461-
func (s *Service) NaivePort() (int32, error) {
445+
// It does not work for IPv6 hostnames/addresses.
446+
func (s *Service) MetricsEndpoint(logger logr.Logger) (string, int32) {
462447
telemetry := s.GetTelemetry()
463448
if telemetry == nil {
464-
return defaultServicePort, nil
449+
return defaultServiceHost, defaultServicePort
465450
}
466451
splitAddress := strings.Split(telemetry.Metrics.Address, ":")
467452
if len(splitAddress) == 1 {
468-
return defaultServicePort, nil
453+
return defaultServiceHost, defaultServicePort
469454
}
470-
port, err := strconv.Atoi(splitAddress[len(splitAddress)-1])
455+
port, err := strconv.ParseInt(splitAddress[len(splitAddress)-1], 10, 32)
471456
if err != nil {
472-
return 0, err
457+
errMsg := fmt.Sprintf("couldn't determine metrics port from configuration, using default: %s:%d",
458+
defaultServiceHost, defaultServicePort)
459+
logger.Info(errMsg, "error", err)
460+
return defaultServiceHost, defaultServicePort
473461
}
474-
return int32(port), nil
462+
host := strings.Join(splitAddress[0:len(splitAddress)-1], ":")
463+
return host, int32(port)
475464
}
476465

477466
// ApplyDefaults inserts configuration defaults if it has not been set.
478-
func (s *Service) ApplyDefaults() error {
479-
telemetryAddr, telemetryPort, err := s.MetricsEndpoint()
480-
if err != nil {
481-
return err
482-
}
467+
func (s *Service) ApplyDefaults(logger logr.Logger) error {
468+
telemetryAddr, telemetryPort := s.MetricsEndpoint(logger)
483469
tm := &AnyConfig{
484470
Object: map[string]interface{}{
485471
"metrics": map[string]interface{}{

apis/v1beta1/config_test.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,7 @@ func TestGetTelemetryFromYAMLIsNil(t *testing.T) {
216216
assert.Nil(t, cfg.Service.GetTelemetry())
217217
}
218218

219-
func TestConfigToMetricsPort(t *testing.T) {
220-
219+
func TestConfigMetricsEndpoint(t *testing.T) {
221220
for _, tt := range []struct {
222221
desc string
223222
expectedAddr string
@@ -239,7 +238,7 @@ func TestConfigToMetricsPort(t *testing.T) {
239238
},
240239
},
241240
{
242-
"bad address",
241+
"missing port",
243242
"0.0.0.0",
244243
8888,
245244
Service{
@@ -296,9 +295,9 @@ func TestConfigToMetricsPort(t *testing.T) {
296295
},
297296
} {
298297
t.Run(tt.desc, func(t *testing.T) {
298+
logger := logr.Discard()
299299
// these are acceptable failures, we return to the collector's default metric port
300-
addr, port, err := tt.config.MetricsEndpoint()
301-
assert.NoError(t, err)
300+
addr, port := tt.config.MetricsEndpoint(logger)
302301
assert.Equal(t, tt.expectedAddr, addr)
303302
assert.Equal(t, tt.expectedPort, port)
304303
})

internal/manifests/collector/container.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,7 @@ func getConfigContainerPorts(logger logr.Logger, conf v1beta1.Config) (map[strin
229229
}
230230
}
231231

232-
_, metricsPort, err := conf.Service.MetricsEndpoint()
233-
if err != nil {
234-
logger.Info("couldn't determine metrics port from configuration, using 8888 default value", "error", err)
235-
metricsPort = 8888
236-
}
232+
_, metricsPort := conf.Service.MetricsEndpoint(logger)
237233
ports["metrics"] = corev1.ContainerPort{
238234
Name: "metrics",
239235
ContainerPort: metricsPort,

internal/manifests/collector/service.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,7 @@ func MonitoringService(params manifests.Params) (*corev1.Service, error) {
8383
return nil, err
8484
}
8585

86-
metricsPort, err := params.OtelCol.Spec.Config.Service.NaivePort()
87-
if err != nil {
88-
return nil, err
89-
}
86+
_, metricsPort := params.OtelCol.Spec.Config.Service.MetricsEndpoint(params.Log)
9087

9188
return &corev1.Service{
9289
ObjectMeta: metav1.ObjectMeta{

pkg/collector/upgrade/v0_111_0.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ import (
1818
"github.com/open-telemetry/opentelemetry-operator/apis/v1beta1"
1919
)
2020

21-
func upgrade0_111_0(_ VersionUpgrade, otelcol *v1beta1.OpenTelemetryCollector) (*v1beta1.OpenTelemetryCollector, error) { //nolint:unparam
22-
return otelcol, otelcol.Spec.Config.Service.ApplyDefaults()
21+
func upgrade0_111_0(u VersionUpgrade, otelcol *v1beta1.OpenTelemetryCollector) (*v1beta1.OpenTelemetryCollector, error) { //nolint:unparam
22+
return otelcol, otelcol.Spec.Config.Service.ApplyDefaults(u.Log)
2323
}

0 commit comments

Comments
 (0)