internal/manifests/collector/adapters/config_to_ports.go (103 lines of code) (raw):

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package adapters import ( "fmt" "net" "sort" "strconv" "strings" "github.com/go-logr/logr" "github.com/mitchellh/mapstructure" corev1 "k8s.io/api/core/v1" "github.com/aws/amazon-cloudwatch-agent-operator/internal/manifests/collector/parser" receiverParser "github.com/aws/amazon-cloudwatch-agent-operator/internal/manifests/collector/parser/receiver" ) type ComponentType int const ( ComponentTypeReceiver ComponentType = iota ) func (c ComponentType) String() string { return [...]string{"receiver", "exporter"}[c] } // ConfigToMetricsPort gets the port number for the metrics endpoint from the collector config if it has been set. func ConfigToMetricsPort(logger logr.Logger, config map[interface{}]interface{}) (int32, error) { // we don't need to unmarshal the whole config, just follow the keys down to // the metrics address. type metricsCfg struct { Address string } type telemetryCfg struct { Metrics metricsCfg } type serviceCfg struct { Telemetry telemetryCfg } type cfg struct { Service serviceCfg } var cOut cfg err := mapstructure.Decode(config, &cOut) if err != nil { return 0, err } _, port, netErr := net.SplitHostPort(cOut.Service.Telemetry.Metrics.Address) if netErr != nil && strings.Contains(netErr.Error(), "missing port in address") { return 8888, nil } else if netErr != nil { return 0, netErr } i64, err := strconv.ParseInt(port, 10, 32) if err != nil { return 0, err } return int32(i64), nil } func GetServicePortsFromCWAgentOtelConfig(logger logr.Logger, config map[interface{}]interface{}) ([]corev1.ServicePort, error) { ports, err := ConfigToComponentPorts(logger, ComponentTypeReceiver, config) if err != nil { logger.Error(err, "there was a problem while getting the ports from the receivers") return nil, err } return ports, nil } // ConfigToComponentPorts converts the incoming configuration object into a set of service ports required by the exporters. func ConfigToComponentPorts(logger logr.Logger, cType ComponentType, config map[interface{}]interface{}) ([]corev1.ServicePort, error) { // now, we gather which ports we might need to open // for that, we get all the exporters and check their `endpoint` properties, // extracting the port from it. The port name has to be a "DNS_LABEL", so, we try to make it follow the pattern: // examples: // ```yaml // components: // componentexample: // endpoint: 0.0.0.0:12345 // componentexample/settings: // endpoint: 0.0.0.0:12346 // in this case, we have 2 ports, named: "componentexample" and "componentexample-settings" componentsProperty, ok := config[fmt.Sprintf("%ss", cType.String())] if !ok { return nil, fmt.Errorf("no %ss available as part of the configuration", cType) } components, ok := componentsProperty.(map[interface{}]interface{}) if !ok { return nil, fmt.Errorf("%ss doesn't contain valid components", cType.String()) } compEnabled := getEnabledComponents(config, cType) if compEnabled == nil { return nil, fmt.Errorf("no enabled %ss available as part of the configuration", cType) } ports := []corev1.ServicePort{} for key, val := range components { // This check will pass only the enabled components, // then only the related ports will be opened. if !compEnabled[key] { continue } extractedComponent, ok := val.(map[interface{}]interface{}) if !ok { logger.V(2).Info("component doesn't seem to be a map of properties", cType.String(), key) extractedComponent = map[interface{}]interface{}{} } cmptName := key.(string) var cmptParser parser.ComponentPortParser var err error cmptParser, err = receiverParser.For(logger, cmptName, extractedComponent) if err != nil { logger.V(2).Info("no parser found for '%s'", cmptName) continue } exprtPorts, err := cmptParser.Ports() if err != nil { logger.Error(err, "parser for '%s' has returned an error: %w", cmptName, err) continue } if len(exprtPorts) > 0 { ports = append(ports, exprtPorts...) } } sort.Slice(ports, func(i, j int) bool { return ports[i].Name < ports[j].Name }) return ports, nil }