diff --git a/.chloggen/feat_k8sobserver_ingress.yaml b/.chloggen/feat_k8sobserver_ingress.yaml new file mode 100644 index 0000000000000..4fa82c75ba6dc --- /dev/null +++ b/.chloggen/feat_k8sobserver_ingress.yaml @@ -0,0 +1,27 @@ +# 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. filelogreceiver) +component: k8sobserver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add support for k8s.ingress endpoint. + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [32971] + +# (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: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# 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: [] diff --git a/extension/observer/endpoints.go b/extension/observer/endpoints.go index 89a57b255a89b..5cf5f9bed94e9 100644 --- a/extension/observer/endpoints.go +++ b/extension/observer/endpoints.go @@ -25,6 +25,8 @@ const ( PodType EndpointType = "pod" // K8sServiceType is a service endpoint. K8sServiceType EndpointType = "k8s.service" + // K8sIngressType is a ingress endpoint. + K8sIngressType EndpointType = "k8s.ingress" // K8sNodeType is a Kubernetes Node endpoint. K8sNodeType EndpointType = "k8s.node" // HostPortType is a hostport endpoint. @@ -129,6 +131,43 @@ func (s *K8sService) Type() EndpointType { return K8sServiceType } +// K8sIngress is a discovered k8s ingress. +type K8sIngress struct { + // Name of the ingress. + Name string + // UID is the unique ID in the cluster for the ingress. + UID string + // Labels is a map of user-specified metadata. + Labels map[string]string + // Annotations is a map of user-specified metadata. + Annotations map[string]string + // Namespace must be unique for ingress with same name. + Namespace string + // Scheme represents whether the ingress path is accessible via HTTPS or HTTP. + Scheme string + // Host is the fully qualified domain name of a network host + Host string + // Path that map requests to backends + Path string +} + +func (s *K8sIngress) Env() EndpointEnv { + return map[string]any{ + "uid": s.UID, + "name": s.Name, + "labels": s.Labels, + "annotations": s.Annotations, + "namespace": s.Namespace, + "scheme": s.Scheme, + "host": s.Host, + "path": s.Path, + } +} + +func (s *K8sIngress) Type() EndpointType { + return K8sIngressType +} + // Pod is a discovered k8s pod. type Pod struct { // Name of the pod. diff --git a/extension/observer/k8sobserver/README.md b/extension/observer/k8sobserver/README.md index ea77d04dc1202..9375a7a02efd5 100644 --- a/extension/observer/k8sobserver/README.md +++ b/extension/observer/k8sobserver/README.md @@ -13,7 +13,7 @@ The `k8s_observer` is a [Receiver Creator](../../../receiver/receivercreator/README.md)-compatible "watch observer" that will detect and report -Kubernetes pod, port, service and node endpoints via the Kubernetes API. +Kubernetes pod, port, service, ingress and node endpoints via the Kubernetes API. ## Example Config @@ -25,6 +25,7 @@ extensions: observe_pods: true observe_nodes: true observe_services: true + observe_ingresses: true receivers: receiver_creator: @@ -70,4 +71,5 @@ All fields are optional. | node | string | | The node name to limit the discovery of pod, port, and node endpoints. Providing no value (the default) results in discovering endpoints for all available nodes. | | observe_pods | bool | `true` | Whether to report observer pod and port endpoints. If `true` and `node` is specified it will only discover pod and port endpoints whose `spec.nodeName` matches the provided node name. If `true` and `node` isn't specified, it will discover all available pod and port endpoints. Please note that Collector connectivity to pods from other nodes is dependent on your cluster configuration and isn't guaranteed. | | observe_nodes | bool | `false` | Whether to report observer k8s.node endpoints. If `true` and `node` is specified it will only discover node endpoints whose `metadata.name` matches the provided node name. If `true` and `node` isn't specified, it will discover all available node endpoints. Please note that Collector connectivity to nodes is dependent on your cluster configuration and isn't guaranteed.| -| observe_services | bool | `false` | Whether to report observer k8s.service endpoints.| +| observe_services | bool | `false` | Whether to report observer k8s.service endpoints.| +| observe_ingresses | bool | `false` | Whether to report observer k8s.ingress endpoints.| diff --git a/extension/observer/k8sobserver/config.go b/extension/observer/k8sobserver/config.go index 9f202be4c246e..24821c8945075 100644 --- a/extension/observer/k8sobserver/config.go +++ b/extension/observer/k8sobserver/config.go @@ -36,12 +36,14 @@ type Config struct { ObserveNodes bool `mapstructure:"observe_nodes"` // ObserveServices determines whether to report observer service and port endpoints. `false` by default. ObserveServices bool `mapstructure:"observe_services"` + // ObserveIngresses determines whether to report observer ingress. `false` by default. + ObserveIngresses bool `mapstructure:"observe_ingresses"` } // Validate checks if the extension configuration is valid func (cfg *Config) Validate() error { - if !cfg.ObservePods && !cfg.ObserveNodes && !cfg.ObserveServices { - return fmt.Errorf("one of observe_pods, observe_nodes and observe_services must be true") + if !cfg.ObservePods && !cfg.ObserveNodes && !cfg.ObserveServices && !cfg.ObserveIngresses { + return fmt.Errorf("one of observe_pods, observe_nodes, observe_services and observe_ingresses must be true") } return nil } diff --git a/extension/observer/k8sobserver/config_test.go b/extension/observer/k8sobserver/config_test.go index 5513036795081..65148580d1dc2 100644 --- a/extension/observer/k8sobserver/config_test.go +++ b/extension/observer/k8sobserver/config_test.go @@ -39,11 +39,12 @@ func TestLoadConfig(t *testing.T) { { id: component.NewIDWithName(metadata.Type, "observe-all"), expected: &Config{ - Node: "", - APIConfig: k8sconfig.APIConfig{AuthType: k8sconfig.AuthTypeNone}, - ObservePods: true, - ObserveNodes: true, - ObserveServices: true, + Node: "", + APIConfig: k8sconfig.APIConfig{AuthType: k8sconfig.AuthTypeNone}, + ObservePods: true, + ObserveNodes: true, + ObserveServices: true, + ObserveIngresses: true, }, }, { @@ -52,7 +53,7 @@ func TestLoadConfig(t *testing.T) { }, { id: component.NewIDWithName(metadata.Type, "invalid_no_observing"), - expectedErr: "one of observe_pods, observe_nodes and observe_services must be true", + expectedErr: "one of observe_pods, observe_nodes, observe_services and observe_ingresses must be true", }, } for _, tt := range tests { diff --git a/extension/observer/k8sobserver/handler.go b/extension/observer/k8sobserver/handler.go index 859738a5c9c09..f1c89bb24b4b8 100644 --- a/extension/observer/k8sobserver/handler.go +++ b/extension/observer/k8sobserver/handler.go @@ -9,6 +9,7 @@ import ( "go.uber.org/zap" v1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" "k8s.io/client-go/tools/cache" "github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer" @@ -49,6 +50,8 @@ func (h *handler) OnAdd(objectInterface any, _ bool) { endpoints = convertPodToEndpoints(h.idNamespace, object) case *v1.Service: endpoints = convertServiceToEndpoints(h.idNamespace, object) + case *networkingv1.Ingress: + endpoints = convertIngressToEndpoints(h.idNamespace, object) case *v1.Node: endpoints = append(endpoints, convertNodeToEndpoint(h.idNamespace, object)) default: // unsupported @@ -92,6 +95,19 @@ func (h *handler) OnUpdate(oldObjectInterface, newObjectInterface any) { newEndpoints[e.ID] = e } + case *networkingv1.Ingress: + newIngress, ok := newObjectInterface.(*networkingv1.Ingress) + if !ok { + h.logger.Warn("skip updating endpoint for ingress as the update is of different type", zap.Any("oldIngress", oldObjectInterface), zap.Any("newObject", newObjectInterface)) + return + } + for _, e := range convertIngressToEndpoints(h.idNamespace, oldObject) { + oldEndpoints[e.ID] = e + } + for _, e := range convertIngressToEndpoints(h.idNamespace, newIngress) { + newEndpoints[e.ID] = e + } + case *v1.Node: newNode, ok := newObjectInterface.(*v1.Node) if !ok { @@ -165,6 +181,10 @@ func (h *handler) OnDelete(objectInterface any) { if object != nil { endpoints = convertServiceToEndpoints(h.idNamespace, object) } + case *networkingv1.Ingress: + if object != nil { + endpoints = convertIngressToEndpoints(h.idNamespace, object) + } case *v1.Node: if object != nil { endpoints = append(endpoints, convertNodeToEndpoint(h.idNamespace, object)) diff --git a/extension/observer/k8sobserver/handler_test.go b/extension/observer/k8sobserver/handler_test.go index 402b5fcc42138..8e813c650a7ab 100644 --- a/extension/observer/k8sobserver/handler_test.go +++ b/extension/observer/k8sobserver/handler_test.go @@ -165,6 +165,70 @@ func TestServiceEndpointsChanged(t *testing.T) { }, th.ListEndpoints()) } +func TestIngressEndpointsAdded(t *testing.T) { + th := newTestHandler() + th.OnAdd(ingress, true) + assert.ElementsMatch(t, []observer.Endpoint{ + { + ID: "test-1/ingress-1-UID/host-1/", + Target: "https://host-1/", + Details: &observer.K8sIngress{ + Name: "application-ingress", + Namespace: "default", + UID: "test-1/ingress-1-UID/host-1/", + Labels: map[string]string{"env": "prod"}, + Scheme: "https", + Host: "host-1", + Path: "/", + }, + }}, th.ListEndpoints()) +} + +func TestIngressEndpointsRemoved(t *testing.T) { + th := newTestHandler() + th.OnAdd(ingress, true) + th.OnDelete(ingress) + assert.Empty(t, th.ListEndpoints()) +} + +func TestIngressEndpointsChanged(t *testing.T) { + th := newTestHandler() + // Nothing changed. + th.OnUpdate(ingress, ingress) + require.Empty(t, th.ListEndpoints()) + + // Labels changed. + changedLabels := ingress.DeepCopy() + changedLabels.Labels["new-label"] = "value" + th.OnUpdate(ingress, changedLabels) + + endpoints := th.ListEndpoints() + require.ElementsMatch(t, + []observer.EndpointID{"test-1/ingress-1-UID/host-1/"}, + []observer.EndpointID{endpoints[0].ID}, + ) + + // Running state changed, one added and one removed. + updatedIngress := ingress.DeepCopy() + updatedIngress.Labels["updated-label"] = "true" + th.OnUpdate(ingress, updatedIngress) + require.ElementsMatch(t, []observer.Endpoint{ + { + ID: "test-1/ingress-1-UID/host-1/", + Target: "https://host-1/", + Details: &observer.K8sIngress{ + Name: "application-ingress", + Namespace: "default", + UID: "test-1/ingress-1-UID/host-1/", + Labels: map[string]string{"env": "prod", "updated-label": "true"}, + Scheme: "https", + Host: "host-1", + Path: "/", + }, + }, + }, th.ListEndpoints()) +} + func TestNodeEndpointsAdded(t *testing.T) { th := newTestHandler() th.OnAdd(node1V1, true) diff --git a/extension/observer/k8sobserver/ingress_endpoint.go b/extension/observer/k8sobserver/ingress_endpoint.go new file mode 100644 index 0000000000000..57c6a1af3a160 --- /dev/null +++ b/extension/observer/k8sobserver/ingress_endpoint.go @@ -0,0 +1,103 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package k8sobserver // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer/k8sobserver" + +import ( + "fmt" + "net/url" + "strings" + + v1 "k8s.io/api/networking/v1" + + "github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer" +) + +// convertIngressToEndpoints converts a ingress instance into a slice of endpoints. The endpoints +// include an endpoint for each path that is mapped to an ingress. +func convertIngressToEndpoints(idNamespace string, ingress *v1.Ingress) []observer.Endpoint { + endpoints := []observer.Endpoint{} + + // Loop through every ingress rule to get every defined path. + for _, rule := range ingress.Spec.Rules { + scheme := getScheme(rule.Host, getTLSHosts(ingress)) + + if rule.HTTP != nil { + // Create endpoint for each ingress rule. + for _, path := range rule.HTTP.Paths { + endpointID := observer.EndpointID(fmt.Sprintf("%s/%s/%s%s", idNamespace, ingress.UID, rule.Host, path.Path)) + endpoints = append(endpoints, observer.Endpoint{ + ID: endpointID, + Target: (&url.URL{ + Scheme: scheme, + Host: rule.Host, + Path: path.Path, + }).String(), + Details: &observer.K8sIngress{ + Name: ingress.Name, + UID: string(endpointID), + Labels: ingress.Labels, + Annotations: ingress.Annotations, + Namespace: ingress.Namespace, + Scheme: scheme, + Host: rule.Host, + Path: path.Path, + }, + }) + } + } + + } + + return endpoints +} + +// getTLSHosts return a list of tls hosts for an ingress ressource. +func getTLSHosts(i *v1.Ingress) []string { + var hosts []string + + for _, tls := range i.Spec.TLS { + hosts = append(hosts, tls.Hosts...) + } + + return hosts +} + +// matchesHostPattern returns true if the host matches the host pattern or wildcard pattern. +func matchesHostPattern(pattern string, host string) bool { + // if host match the pattern (host pattern). + if pattern == host { + return true + } + + // if string does not contains any dot, don't do the next part as it's for wildcard pattern. + if !strings.Contains(host, ".") { + return false + } + + patternParts := strings.Split(pattern, ".") + hostParts := strings.Split(host, ".") + + // If the first part of the pattern is not a wildcard pattern. + if patternParts[0] != "*" { + return false + } + + // If host and pattern without wildcard part does not match. + if strings.Join(patternParts[1:], ".") != strings.Join(hostParts[1:], ".") { + return false + } + + return true +} + +// getScheme return the scheme of an ingress host based on tls configuration. +func getScheme(host string, tlsHosts []string) string { + for _, pattern := range tlsHosts { + if matchesHostPattern(pattern, host) { + return "https" + } + } + + return "http" +} diff --git a/extension/observer/k8sobserver/ingress_endpoint_test.go b/extension/observer/k8sobserver/ingress_endpoint_test.go new file mode 100644 index 0000000000000..dcdb67c1da109 --- /dev/null +++ b/extension/observer/k8sobserver/ingress_endpoint_test.go @@ -0,0 +1,59 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package k8sobserver // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer/k8sobserver" + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer" +) + +func TestIngressObjectToPortEndpoint(t *testing.T) { + expectedEndpoints := []observer.Endpoint{ + { + ID: "namespace/ingress-1-UID/host-1/", + Target: "https://host-1/", + Details: &observer.K8sIngress{ + Name: "application-ingress", + Namespace: "default", + UID: "namespace/ingress-1-UID/host-1/", + Labels: map[string]string{"env": "prod"}, + Scheme: "https", + Host: "host-1", + Path: "/", + }, + }, + { + ID: "namespace/ingress-1-UID/host.2.host/", + Target: "https://host.2.host/", + Details: &observer.K8sIngress{ + Name: "application-ingress", + Namespace: "default", + UID: "namespace/ingress-1-UID/host.2.host/", + Labels: map[string]string{"env": "prod"}, + Scheme: "https", + Host: "host.2.host", + Path: "/", + }, + }, + { + ID: "namespace/ingress-1-UID/host.3.host/test", + Target: "http://host.3.host/test", + Details: &observer.K8sIngress{ + Name: "application-ingress", + Namespace: "default", + UID: "namespace/ingress-1-UID/host.3.host/test", + Labels: map[string]string{"env": "prod"}, + Scheme: "http", + Host: "host.3.host", + Path: "/test", + }, + }, + } + + endpoints := convertIngressToEndpoints("namespace", ingressMultipleHost) + require.Equal(t, expectedEndpoints, endpoints) +} diff --git a/extension/observer/k8sobserver/k8s_fixtures_test.go b/extension/observer/k8sobserver/k8s_fixtures_test.go index 4f0acd4aa273c..887f01a0eef15 100644 --- a/extension/observer/k8sobserver/k8s_fixtures_test.go +++ b/extension/observer/k8sobserver/k8s_fixtures_test.go @@ -5,6 +5,7 @@ package k8sobserver import ( v1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) @@ -134,6 +135,97 @@ var serviceWithClusterIPV2 = func() *v1.Service { return service }() +var ingress = &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "application-ingress", + UID: types.UID("ingress-1-UID"), + Labels: map[string]string{ + "env": "prod", + }, + }, + Spec: networkingv1.IngressSpec{ + Rules: []networkingv1.IngressRule{ + { + Host: "host-1", + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{ + Paths: []networkingv1.HTTPIngressPath{ + { + Path: "/", + }, + }, + }, + }, + }, + }, + TLS: []networkingv1.IngressTLS{ + { + Hosts: []string{"host-1"}, + }, + }, + }, +} + +var ingressMultipleHost = &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "application-ingress", + UID: types.UID("ingress-1-UID"), + Labels: map[string]string{ + "env": "prod", + }, + }, + Spec: networkingv1.IngressSpec{ + Rules: []networkingv1.IngressRule{ + { + Host: "host-invalid", + }, + { + Host: "host-1", + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{ + Paths: []networkingv1.HTTPIngressPath{ + { + Path: "/", + }, + }, + }, + }, + }, + { + Host: "host.2.host", + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{ + Paths: []networkingv1.HTTPIngressPath{ + { + Path: "/", + }, + }, + }, + }, + }, + { + Host: "host.3.host", + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{ + Paths: []networkingv1.HTTPIngressPath{ + { + Path: "/test", + }, + }, + }, + }, + }, + }, + TLS: []networkingv1.IngressTLS{ + { + Hosts: []string{"host-1", "*.2.host"}, + }, + }, + }, +} + // newNode is a helper function for creating Nodes for testing. func newNode(name, hostname string) *v1.Node { return &v1.Node{ diff --git a/extension/observer/k8sobserver/testdata/config.yaml b/extension/observer/k8sobserver/testdata/config.yaml index 8e61638290254..6ff12eadc1e8f 100644 --- a/extension/observer/k8sobserver/testdata/config.yaml +++ b/extension/observer/k8sobserver/testdata/config.yaml @@ -7,9 +7,11 @@ k8s_observer/observe-all: observe_nodes: true observe_pods: true observe_services: true + observe_ingresses: true k8s_observer/invalid_auth: auth_type: not a real auth type k8s_observer/invalid_no_observing: observe_nodes: false observe_pods: false observe_services: false + observe_ingresses: false diff --git a/receiver/receivercreator/README.md b/receiver/receivercreator/README.md index 6356e252983cf..3c5146eda4204 100644 --- a/receiver/receivercreator/README.md +++ b/receiver/receivercreator/README.md @@ -222,6 +222,21 @@ targeting it will have different variables available. | service_type | The type of the kubernetes service: ClusterIP, NodePort, LoadBalancer, ExternalName | String | | cluster_ip | The cluster IP assigned to the service | String | +### Kubernetes Ingress + +| Variable | Description | Data Type | +|----------------|---------------------------------------------------------------------------------------|-------------------------------| +| type | `"k8s.ingress"` | String | +| id | ID of source endpoint | String | +| name | The name of the Kubernetes ingress | String | +| namespace | The namespace of the ingress | String | +| uid | The unique ID for the ingress | String | +| labels | The map of labels set on the ingress | Map with String key and value | +| annotations | The map of annotations set on the ingress | Map with String key and value | +| scheme | Scheme represents whether the ingress path is accessible via HTTPS or HTTP. | String | +| host | Host is the FQDN that map to backends | String | +| path | Path that map requests to backends | String | + ### Kubernetes Node | Variable | Description | Data Type | @@ -247,6 +262,7 @@ extensions: k8s_observer: observe_nodes: true observe_services: true + observe_ingresses: true host_observer: receivers: @@ -318,6 +334,17 @@ receivers: - endpoint: 'http://`endpoint`:`"prometheus.io/port" in annotations ? annotations["prometheus.io/port"] : 9090``"prometheus.io/path" in annotations ? annotations["prometheus.io/path"] : "/health"`' method: GET collection_interval: 10s + receiver_creator/4: + watch_observers: [k8s_observer] + receivers: + httpcheck: + # Configure probing if standard prometheus annotations are set on the pod. + rule: type == "k8s.ingress" && annotations["prometheus.io/probe"] == "true" + config: + targets: + - endpoint: '`scheme`://`endpoint`:`port``"prometheus.io/path" in annotations ? annotations["prometheus.io/path"] : "/health"`' + method: GET + collection_interval: 10s processors: exampleprocessor: @@ -328,7 +355,7 @@ exporters: service: pipelines: metrics: - receivers: [receiver_creator/1, receiver_creator/2, receiver_creator/3] + receivers: [receiver_creator/1, receiver_creator/2, receiver_creator/3, receiver_creator/4] processors: [exampleprocessor] exporters: [exampleexporter] extensions: [k8s_observer, host_observer] diff --git a/receiver/receivercreator/config.go b/receiver/receivercreator/config.go index 281a9e0feadf2..c12109946910f 100644 --- a/receiver/receivercreator/config.go +++ b/receiver/receivercreator/config.go @@ -92,7 +92,7 @@ func (cfg *Config) Unmarshal(componentParser *confmap.Conf) error { for endpointType := range cfg.ResourceAttributes { switch endpointType { - case observer.ContainerType, observer.K8sServiceType, observer.HostPortType, observer.K8sNodeType, observer.PodType, observer.PortType: + case observer.ContainerType, observer.K8sServiceType, observer.K8sIngressType, observer.HostPortType, observer.K8sNodeType, observer.PodType, observer.PortType: default: return fmt.Errorf("resource attributes for unsupported endpoint type %q", endpointType) } diff --git a/receiver/receivercreator/config_test.go b/receiver/receivercreator/config_test.go index 7d4dbd9d05406..c58700c35cfc1 100644 --- a/receiver/receivercreator/config_test.go +++ b/receiver/receivercreator/config_test.go @@ -114,6 +114,7 @@ func TestLoadConfig(t *testing.T) { observer.PortType: {"port.key": "port.value"}, observer.HostPortType: {"hostport.key": "hostport.value"}, observer.K8sServiceType: {"k8s.service.key": "k8s.service.value"}, + observer.K8sIngressType: {"k8s.ingress.key": "k8s.ingress.value"}, observer.K8sNodeType: {"k8s.node.key": "k8s.node.value"}, }, }, diff --git a/receiver/receivercreator/factory.go b/receiver/receivercreator/factory.go index fd07f1d900928..abba7f8139fe7 100644 --- a/receiver/receivercreator/factory.go +++ b/receiver/receivercreator/factory.go @@ -42,6 +42,9 @@ func createDefaultConfig() component.Config { observer.K8sServiceType: map[string]string{ conventions.AttributeK8SNamespaceName: "`namespace`", }, + observer.K8sIngressType: map[string]string{ + conventions.AttributeK8SNamespaceName: "`namespace`", + }, observer.PortType: map[string]string{ conventions.AttributeK8SPodName: "`pod.name`", conventions.AttributeK8SPodUID: "`pod.uid`", diff --git a/receiver/receivercreator/rules.go b/receiver/receivercreator/rules.go index 1e8d68715948f..422e7813ff1b5 100644 --- a/receiver/receivercreator/rules.go +++ b/receiver/receivercreator/rules.go @@ -22,7 +22,7 @@ type rule struct { // ruleRe is used to verify the rule starts type check. var ruleRe = regexp.MustCompile( - fmt.Sprintf(`^type\s*==\s*(%q|%q|%q|%q|%q|%q)`, observer.PodType, observer.K8sServiceType, observer.PortType, observer.HostPortType, observer.ContainerType, observer.K8sNodeType), + fmt.Sprintf(`^type\s*==\s*(%q|%q|%q|%q|%q|%q|%q)`, observer.PodType, observer.K8sServiceType, observer.K8sIngressType, observer.PortType, observer.HostPortType, observer.ContainerType, observer.K8sNodeType), ) // newRule creates a new rule instance. diff --git a/receiver/receivercreator/testdata/config.yaml b/receiver/receivercreator/testdata/config.yaml index f0632e39de086..040e0e04d92fe 100644 --- a/receiver/receivercreator/testdata/config.yaml +++ b/receiver/receivercreator/testdata/config.yaml @@ -27,5 +27,7 @@ receiver_creator/1: hostport.key: hostport.value k8s.service: k8s.service.key: k8s.service.value + k8s.ingress: + k8s.ingress.key: k8s.ingress.value k8s.node: k8s.node.key: k8s.node.value