diff --git a/.chloggen/k8sattr-singular.yaml b/.chloggen/k8sattr-singular.yaml new file mode 100644 index 0000000000000..f1127e1a84fb9 --- /dev/null +++ b/.chloggen/k8sattr-singular.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: 'breaking' + +# The name of the component, or a single word describing the area of concern, (e.g. receiver/filelog) +component: processor/k8sattributes + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: "Changed default behavior of Kubernetes label and annotation attribute keys to be singular (e.g. `k8s.pod.label.`) instead of plural (e.g. `k8s.pod.labels.`). This change is controlled by a feature gate which is enabled by default. To revert to the previous plural behavior, disable the `k8sattr.labelsAnnotationsSingular.allow` feature gate." + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [44693] + +# (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/processor/k8sattributesprocessor/README.md b/processor/k8sattributesprocessor/README.md index b59e4b82e59eb..f9258558f8f0b 100644 --- a/processor/k8sattributesprocessor/README.md +++ b/processor/k8sattributesprocessor/README.md @@ -571,7 +571,9 @@ can be converted with the usage of `ExtractPatterns` function: ### `k8sattr.labelsAnnotationsSingular.allow` -The `k8sattr.labelsAnnotationsSingular.allow` feature gate, when enabled, changes the default resource attribute key format from `k8s..labels.` to `k8s..label.` and `k8s..annotations.` to `k8s..annotation.`. +The `k8sattr.labelsAnnotationsSingular.allow` feature gate is currently at beta stage and **enabled by default**. This changes the default resource attribute key format from `k8s..labels.` to `k8s..label.` and `k8s..annotations.` to `k8s..annotation.`. + +To revert to the previous plural format, you can disable the feature gate by setting `--feature-gates=-k8sattr.labelsAnnotationsSingular.allow`. This affects both: - Runtime attribute extraction from Kubernetes metadata diff --git a/processor/k8sattributesprocessor/e2e_test.go b/processor/k8sattributesprocessor/e2e_test.go index c19189dd469c6..64c22805999ff 100644 --- a/processor/k8sattributesprocessor/e2e_test.go +++ b/processor/k8sattributesprocessor/e2e_test.go @@ -154,8 +154,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -178,8 +178,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-job-workload-annotation": newExpectedValue(equal, "job-annotation"), }, }, @@ -203,8 +203,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-statefulset-workload-annotation": newExpectedValue(equal, "statefulset-annotation"), }, }, @@ -230,7 +230,7 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-deployment-workload-annotation": newExpectedValue(equal, "deployment-annotation"), }, }, @@ -254,8 +254,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-daemonset-workload-annotation": newExpectedValue(equal, "daemonset-annotation"), }, }, @@ -281,8 +281,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -305,8 +305,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-job-workload-annotation": newExpectedValue(equal, "job-annotation"), }, }, @@ -330,8 +330,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-statefulset-workload-annotation": newExpectedValue(equal, "statefulset-annotation"), }, }, @@ -357,7 +357,7 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-deployment-workload-annotation": newExpectedValue(equal, "deployment-annotation"), }, }, @@ -381,8 +381,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-daemonset-workload-annotation": newExpectedValue(equal, "daemonset-annotation"), }, }, @@ -408,8 +408,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -432,8 +432,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-job-workload-annotation": newExpectedValue(equal, "job-annotation"), }, }, @@ -457,7 +457,7 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-statefulset-workload-annotation": newExpectedValue(equal, "statefulset-annotation"), }, }, @@ -483,8 +483,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-deployment-workload-annotation": newExpectedValue(equal, "deployment-annotation"), }, }, @@ -508,8 +508,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-daemonset-workload-annotation": newExpectedValue(equal, "daemonset-annotation"), }, }, @@ -535,8 +535,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -559,8 +559,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -583,7 +583,7 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -608,8 +608,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -632,8 +632,8 @@ func TestE2E_ClusterRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, } @@ -917,8 +917,8 @@ func TestE2E_MixRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "0.112.0"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), "k8s.cluster.uid": newExpectedValue(regex, uidRe), }, }, @@ -944,8 +944,8 @@ func TestE2E_MixRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "0.112.0"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), "k8s.cluster.uid": newExpectedValue(regex, uidRe), }, }, @@ -971,8 +971,8 @@ func TestE2E_MixRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "0.112.0"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), "k8s.cluster.uid": newExpectedValue(regex, uidRe), }, }, @@ -998,8 +998,8 @@ func TestE2E_MixRBAC(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), "k8s.cluster.uid": newExpectedValue(regex, uidRe), }, }, @@ -1294,8 +1294,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -1318,8 +1318,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-job-workload-annotation": newExpectedValue(equal, "job-annotation"), }, }, @@ -1343,8 +1343,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-statefulset-workload-annotation": newExpectedValue(equal, "statefulset-annotation"), }, }, @@ -1370,7 +1370,7 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-deployment-workload-annotation": newExpectedValue(equal, "deployment-annotation"), }, }, @@ -1394,8 +1394,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-daemonset-workload-annotation": newExpectedValue(equal, "daemonset-annotation"), }, }, @@ -1421,8 +1421,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -1445,8 +1445,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-job-workload-annotation": newExpectedValue(equal, "job-annotation"), }, }, @@ -1470,8 +1470,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-statefulset-workload-annotation": newExpectedValue(equal, "statefulset-annotation"), }, }, @@ -1497,7 +1497,7 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-deployment-workload-annotation": newExpectedValue(equal, "deployment-annotation"), }, }, @@ -1521,8 +1521,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-daemonset-workload-annotation": newExpectedValue(equal, "daemonset-annotation"), }, }, @@ -1548,8 +1548,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -1572,8 +1572,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-job-workload-annotation": newExpectedValue(equal, "job-annotation"), }, }, @@ -1597,7 +1597,7 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-statefulset-workload-annotation": newExpectedValue(equal, "statefulset-annotation"), }, }, @@ -1623,8 +1623,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-deployment-workload-annotation": newExpectedValue(equal, "deployment-annotation"), }, }, @@ -1648,8 +1648,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), "simple-daemonset-workload-annotation": newExpectedValue(equal, "daemonset-annotation"), }, }, @@ -1675,8 +1675,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -1699,8 +1699,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -1723,7 +1723,7 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -1748,8 +1748,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, { @@ -1772,8 +1772,8 @@ func TestE2E_ClusterRBACCollectorStartAfterTelemetryGen(t *testing.T) { "container.image.repo_digests": newExpectedValue(regex, "ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen@sha256:[0-9a-fA-f]{64}"), "container.image.tag": newExpectedValue(equal, "latest"), "container.id": newExpectedValue(exist, ""), - "k8s.node.labels.foo": newExpectedValue(equal, "too"), - "k8s.namespace.labels.foons": newExpectedValue(equal, "barns"), + "k8s.node.label.foo": newExpectedValue(equal, "too"), + "k8s.namespace.label.foons": newExpectedValue(equal, "barns"), }, }, } diff --git a/processor/k8sattributesprocessor/internal/kube/client.go b/processor/k8sattributesprocessor/internal/kube/client.go index a1929d49e3cfc..13a0f62a54b83 100644 --- a/processor/k8sattributesprocessor/internal/kube/client.go +++ b/processor/k8sattributesprocessor/internal/kube/client.go @@ -67,7 +67,7 @@ const ( var AllowLabelsAnnotationsSingular = featuregate.GlobalRegistry().MustRegister( "k8sattr.labelsAnnotationsSingular.allow", - featuregate.StageAlpha, + featuregate.StageBeta, featuregate.WithRegisterDescription("When enabled, default k8s label and annotation resource attribute keys will be singular, instead of plural"), featuregate.WithRegisterFromVersion("v0.125.0"), ) diff --git a/processor/k8sattributesprocessor/internal/kube/client_test.go b/processor/k8sattributesprocessor/internal/kube/client_test.go index 4d836fca9f63c..366165e88f9b5 100644 --- a/processor/k8sattributesprocessor/internal/kube/client_test.go +++ b/processor/k8sattributesprocessor/internal/kube/client_test.go @@ -715,7 +715,7 @@ func TestExtractionRules(t *testing.T) { additionalAnnotations map[string]string additionalLabels map[string]string attributes map[string]string - singularFeatureGate bool + singularFeatureGate *bool // nil = default (enabled in beta), false = explicitly disabled, true = explicitly enabled }{ { name: "no-rules", @@ -919,12 +919,13 @@ func TestExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.pod.labels.label1": "lv1", - "k8s.pod.labels.label2": "k1=v1 k5=v5 extra!", + "k8s.pod.label.label1": "lv1", + "k8s.pod.label.label2": "k1=v1 k5=v5 extra!", }, + // singularFeatureGate: nil means use default (enabled in beta) }, { - name: "all-labels singular", + name: "all-labels plural", rules: ExtractionRules{ Labels: []FieldExtractionRule{ { @@ -934,10 +935,10 @@ func TestExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.pod.label.label1": "lv1", - "k8s.pod.label.label2": "k1=v1 k5=v5 extra!", + "k8s.pod.labels.label1": "lv1", + "k8s.pod.labels.label2": "k1=v1 k5=v5 extra!", }, - singularFeatureGate: true, + singularFeatureGate: func() *bool { b := false; return &b }(), }, { name: "all-annotations", @@ -950,11 +951,11 @@ func TestExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.pod.annotations.annotation1": "av1", + "k8s.pod.annotation.annotation1": "av1", }, }, { - name: "all-annotations singular", + name: "all-annotations plural", rules: ExtractionRules{ Annotations: []FieldExtractionRule{ { @@ -964,9 +965,9 @@ func TestExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.pod.annotation.annotation1": "av1", + "k8s.pod.annotations.annotation1": "av1", }, - singularFeatureGate: true, + singularFeatureGate: func() *bool { b := false; return &b }(), }, { name: "all-annotations-not-match", @@ -1066,10 +1067,11 @@ func TestExtractionRules(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - if tc.singularFeatureGate { - require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), true)) + if tc.singularFeatureGate != nil { + require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), *tc.singularFeatureGate)) defer func() { - require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), false)) + // Restore to default (enabled in beta) + require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), true)) }() } @@ -1274,7 +1276,7 @@ func TestNamespaceExtractionRules(t *testing.T) { name string rules ExtractionRules attributes map[string]string - singularFeatureGate bool + singularFeatureGate *bool }{ { name: "no-rules", @@ -1315,11 +1317,11 @@ func TestNamespaceExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.namespace.labels.label1": "lv1", + "k8s.namespace.label.label1": "lv1", }, }, { - name: "all-labels singular", + name: "all-labels plural", rules: ExtractionRules{ Labels: []FieldExtractionRule{ { @@ -1329,9 +1331,9 @@ func TestNamespaceExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.namespace.label.label1": "lv1", + "k8s.namespace.labels.label1": "lv1", }, - singularFeatureGate: true, + singularFeatureGate: func() *bool { b := false; return &b }(), }, { name: "all-annotations", @@ -1344,11 +1346,11 @@ func TestNamespaceExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.namespace.annotations.annotation1": "av1", + "k8s.namespace.annotation.annotation1": "av1", }, }, { - name: "all-annotations singular", + name: "all-annotations plural", rules: ExtractionRules{ Annotations: []FieldExtractionRule{ { @@ -1358,17 +1360,17 @@ func TestNamespaceExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.namespace.annotation.annotation1": "av1", + "k8s.namespace.annotations.annotation1": "av1", }, - singularFeatureGate: true, + singularFeatureGate: func() *bool { b := false; return &b }(), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - if tc.singularFeatureGate { - require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), true)) + if tc.singularFeatureGate != nil { + require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), *tc.singularFeatureGate)) defer func() { - require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), false)) + require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), true)) }() } @@ -1532,7 +1534,7 @@ func TestNodeExtractionRules(t *testing.T) { name string rules ExtractionRules attributes map[string]string - singularFeatureGate bool + singularFeatureGate *bool }{ { name: "no-rules", @@ -1573,11 +1575,11 @@ func TestNodeExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.node.labels.label1": "lv1", + "k8s.node.label.label1": "lv1", }, }, { - name: "all-labels singular", + name: "all-labels plural", rules: ExtractionRules{ Labels: []FieldExtractionRule{ { @@ -1587,9 +1589,9 @@ func TestNodeExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.node.label.label1": "lv1", + "k8s.node.labels.label1": "lv1", }, - singularFeatureGate: true, + singularFeatureGate: func() *bool { b := false; return &b }(), }, { name: "all-annotations", @@ -1602,11 +1604,11 @@ func TestNodeExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.node.annotations.annotation1": "av1", + "k8s.node.annotation.annotation1": "av1", }, }, { - name: "all-annotations singular", + name: "all-annotations plural", rules: ExtractionRules{ Annotations: []FieldExtractionRule{ { @@ -1616,17 +1618,17 @@ func TestNodeExtractionRules(t *testing.T) { }, }, attributes: map[string]string{ - "k8s.node.annotation.annotation1": "av1", + "k8s.node.annotations.annotation1": "av1", }, - singularFeatureGate: true, + singularFeatureGate: func() *bool { b := false; return &b }(), }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - if tc.singularFeatureGate { - require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), true)) + if tc.singularFeatureGate != nil { + require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), *tc.singularFeatureGate)) defer func() { - require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), false)) + require.NoError(t, featuregate.GlobalRegistry().Set(AllowLabelsAnnotationsSingular.ID(), true)) }() } diff --git a/processor/k8sattributesprocessor/options_test.go b/processor/k8sattributesprocessor/options_test.go index 4b0a8fc9594dd..5027237a45de3 100644 --- a/processor/k8sattributesprocessor/options_test.go +++ b/processor/k8sattributesprocessor/options_test.go @@ -563,92 +563,16 @@ func TestWithFilterFields(t *testing.T) { } } -func Test_extractFieldRules(t *testing.T) { - type args struct { - fieldType string - fields []FieldExtractConfig - } - tests := []struct { - name string - args args - want []kube.FieldExtractionRule - wantErr bool - }{ - { - name: "default", - args: args{"labels", []FieldExtractConfig{ - { - Key: "key", - From: kube.MetadataFromPod, - }, - }}, - want: []kube.FieldExtractionRule{ - { - Name: "k8s.pod.labels.key", - Key: "key", - From: kube.MetadataFromPod, - }, - }, - }, - { - name: "basic", - args: args{"field", []FieldExtractConfig{ - { - TagName: "name", - Key: "key", - From: kube.MetadataFromPod, - }, - }}, - want: []kube.FieldExtractionRule{ - { - Name: "name", - Key: "key", - From: kube.MetadataFromPod, - }, - }, - }, - { - name: "keyregex-capture-group", - args: args{"labels", []FieldExtractConfig{ - { - TagName: "$0-$1-$2", - KeyRegex: "(key)(.*)", - From: kube.MetadataFromPod, - }, - }}, - want: []kube.FieldExtractionRule{ - { - Name: "$0-$1-$2", - KeyRegex: regexp.MustCompile("^(?:(key)(.*))$"), - HasKeyRegexReference: true, - From: kube.MetadataFromPod, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := extractFieldRules(tt.args.fieldType, tt.args.fields...) - if tt.wantErr { - assert.Error(t, err) - return - } - require.NoError(t, err) - assert.Equal(t, tt.want, got) - }) - } -} - func Test_extractFieldRules_FeatureGate(t *testing.T) { tests := []struct { name string fieldType string fields []FieldExtractConfig featureGateValue bool - wantNamePattern string + wantRule kube.FieldExtractionRule }{ { - name: "labels plural when feature gate disabled", + name: "labels singular when feature gate enabled (default)", fieldType: "labels", fields: []FieldExtractConfig{ { @@ -656,11 +580,15 @@ func Test_extractFieldRules_FeatureGate(t *testing.T) { From: kube.MetadataFromPod, }, }, - featureGateValue: false, - wantNamePattern: "k8s.pod.labels.app", + featureGateValue: true, + wantRule: kube.FieldExtractionRule{ + Name: "k8s.pod.label.app", + Key: "app", + From: kube.MetadataFromPod, + }, }, { - name: "labels singular when feature gate enabled", + name: "labels plural when feature gate disabled", fieldType: "labels", fields: []FieldExtractConfig{ { @@ -668,11 +596,15 @@ func Test_extractFieldRules_FeatureGate(t *testing.T) { From: kube.MetadataFromPod, }, }, - featureGateValue: true, - wantNamePattern: "k8s.pod.label.app", + featureGateValue: false, + wantRule: kube.FieldExtractionRule{ + Name: "k8s.pod.labels.app", + Key: "app", + From: kube.MetadataFromPod, + }, }, { - name: "annotations plural when feature gate disabled", + name: "annotations singular when feature gate enabled (default)", fieldType: "annotations", fields: []FieldExtractConfig{ { @@ -680,11 +612,15 @@ func Test_extractFieldRules_FeatureGate(t *testing.T) { From: kube.MetadataFromPod, }, }, - featureGateValue: false, - wantNamePattern: "k8s.pod.annotations.workload", + featureGateValue: true, + wantRule: kube.FieldExtractionRule{ + Name: "k8s.pod.annotation.workload", + Key: "workload", + From: kube.MetadataFromPod, + }, }, { - name: "annotations singular when feature gate enabled", + name: "annotations plural when feature gate disabled", fieldType: "annotations", fields: []FieldExtractConfig{ { @@ -692,11 +628,15 @@ func Test_extractFieldRules_FeatureGate(t *testing.T) { From: kube.MetadataFromPod, }, }, - featureGateValue: true, - wantNamePattern: "k8s.pod.annotation.workload", + featureGateValue: false, + wantRule: kube.FieldExtractionRule{ + Name: "k8s.pod.annotations.workload", + Key: "workload", + From: kube.MetadataFromPod, + }, }, { - name: "namespace labels singular when feature gate enabled", + name: "namespace labels plural when feature gate disabled", fieldType: "labels", fields: []FieldExtractConfig{ { @@ -704,11 +644,15 @@ func Test_extractFieldRules_FeatureGate(t *testing.T) { From: kube.MetadataFromNamespace, }, }, - featureGateValue: true, - wantNamePattern: "k8s.namespace.label.env", + featureGateValue: false, + wantRule: kube.FieldExtractionRule{ + Name: "k8s.namespace.labels.env", + Key: "env", + From: kube.MetadataFromNamespace, + }, }, { - name: "node annotations singular when feature gate enabled", + name: "node annotations plural when feature gate disabled", fieldType: "annotations", fields: []FieldExtractConfig{ { @@ -716,8 +660,12 @@ func Test_extractFieldRules_FeatureGate(t *testing.T) { From: kube.MetadataFromNode, }, }, - featureGateValue: true, - wantNamePattern: "k8s.node.annotation.zone", + featureGateValue: false, + wantRule: kube.FieldExtractionRule{ + Name: "k8s.node.annotations.zone", + Key: "zone", + From: kube.MetadataFromNode, + }, }, { name: "explicit tag name not affected by feature gate", @@ -730,7 +678,29 @@ func Test_extractFieldRules_FeatureGate(t *testing.T) { }, }, featureGateValue: true, - wantNamePattern: "custom.tag.name", + wantRule: kube.FieldExtractionRule{ + Name: "custom.tag.name", + Key: "app", + From: kube.MetadataFromPod, + }, + }, + { + name: "keyregex with capture group", + fieldType: "labels", + fields: []FieldExtractConfig{ + { + TagName: "$0-$1-$2", + KeyRegex: "(key)(.*)", + From: kube.MetadataFromPod, + }, + }, + featureGateValue: true, + wantRule: kube.FieldExtractionRule{ + Name: "$0-$1-$2", + KeyRegex: regexp.MustCompile("^(?:(key)(.*))$"), + HasKeyRegexReference: true, + From: kube.MetadataFromPod, + }, }, } @@ -739,14 +709,28 @@ func Test_extractFieldRules_FeatureGate(t *testing.T) { // Set feature gate state require.NoError(t, featuregate.GlobalRegistry().Set(kube.AllowLabelsAnnotationsSingular.ID(), tt.featureGateValue)) defer func() { - // Reset to default - require.NoError(t, featuregate.GlobalRegistry().Set(kube.AllowLabelsAnnotationsSingular.ID(), false)) + // Reset to default (enabled in beta) + require.NoError(t, featuregate.GlobalRegistry().Set(kube.AllowLabelsAnnotationsSingular.ID(), true)) }() - got, err := extractFieldRules(tt.fieldType, tt.fields...) + r, err := extractFieldRules(tt.fieldType, tt.fields...) require.NoError(t, err) - require.Len(t, got, 1) - assert.Equal(t, tt.wantNamePattern, got[0].Name) + require.Len(t, r, 1) + + // Compare all relevant fields + assert.Equal(t, tt.wantRule.Name, r[0].Name) + assert.Equal(t, tt.wantRule.Key, r[0].Key) + assert.Equal(t, tt.wantRule.From, r[0].From) + + // Compare regex if present + if tt.wantRule.KeyRegex != nil { + assert.NotNil(t, r[0].KeyRegex) + assert.Equal(t, tt.wantRule.KeyRegex.String(), r[0].KeyRegex.String()) + } else { + assert.Nil(t, r[0].KeyRegex) + } + + assert.Equal(t, tt.wantRule.HasKeyRegexReference, r[0].HasKeyRegexReference) }) } }