From a5e788f5ce2c17816b847d4cacb1bef1e5a6cda4 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Fri, 31 Jan 2025 08:29:36 +0100 Subject: [PATCH] [processor/k8sattributes] remove deprecated FieldExtractConfig.Regex parameter Signed-off-by: odubajDT --- .chloggen/regex-deprecation.yaml | 27 ++++++++ processor/k8sattributesprocessor/README.md | 57 +---------------- processor/k8sattributesprocessor/config.go | 45 ------------- .../k8sattributesprocessor/config_test.go | 63 ++----------------- processor/k8sattributesprocessor/options.go | 11 +--- .../k8sattributesprocessor/options_test.go | 28 ++------- .../testdata/config.yaml | 63 ------------------- 7 files changed, 41 insertions(+), 253 deletions(-) create mode 100644 .chloggen/regex-deprecation.yaml diff --git a/.chloggen/regex-deprecation.yaml b/.chloggen/regex-deprecation.yaml new file mode 100644 index 000000000000..5a8b5c9fedde --- /dev/null +++ b/.chloggen/regex-deprecation.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. filelogreceiver) +component: processor/k8sattributes + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: "Remove deprecated FieldExtractConfig.Regex parameter" + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [25128] + +# (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 7f0d9aef8475..3648373e5311 100644 --- a/processor/k8sattributesprocessor/README.md +++ b/processor/k8sattributesprocessor/README.md @@ -233,21 +233,18 @@ extract: - tag_name: a1 # extracts value of annotation from pods with key `annotation-one` and inserts it as a tag with key `a1` key: annotation-one from: pod - - tag_name: a2 # extracts value of annotation from namespaces with key `annotation-two` with regexp and inserts it as a tag with key `a2` + - tag_name: a2 # extracts value of annotation from namespaces with key `annotation-two` and inserts it as a tag with key `a2` key: annotation-two - regex: field=(?P.+) from: namespace - - tag_name: a3 # extracts value of annotation from nodes with key `annotation-three` with regexp and inserts it as a tag with key `a3` + - tag_name: a3 # extracts value of annotation from nodes with key `annotation-three` and inserts it as a tag with key `a3` key: annotation-three - regex: field=(?P.+) from: node labels: - tag_name: l1 # extracts value of label from namespaces with key `label1` and inserts it as a tag with key `l1` key: label1 from: namespace - - tag_name: l2 # extracts value of label from pods with key `label2` with regexp and inserts it as a tag with key `l2` + - tag_name: l2 # extracts value of label from pods with key `label2` and inserts it as a tag with key `l2` key: label2 - regex: field=(?P.+) from: pod - tag_name: l3 # extracts value of label from nodes with key `label3` and inserts it as a tag with key `l3` key: label3 @@ -474,51 +471,3 @@ as tags. By default, the `k8s.pod.start_time` uses [Time.MarshalText()](https://pkg.go.dev/time#Time.MarshalText) to format the timestamp value as an RFC3339 compliant timestamp. - -## Feature Gate - -### `k8sattr.fieldExtractConfigRegex.disallow` - -The `k8sattr.fieldExtractConfigRegex.disallow` [feature gate](https://github.com/open-telemetry/opentelemetry-collector/blob/main/featuregate/README.md#collector-feature-gates) disallows the usage of the `extract.annotations.regex` and `extract.labels.regex` fields. -The validation performed on the configuration will fail, if at least one of the parameters is set (non-empty) and `k8sattr.fieldExtractConfigRegex.disallow` is set to `true` (default `false`). - -#### Example Usage - -The following config with the feature gate set will lead to validation error: - -`config.yaml`: - - ```yaml - extract: - labels: - regex: - annotations: - regex: - ``` - - Run collector: `./otelcol --config config.yaml --feature-gates=k8sattr.fieldExtractConfigRegex.disallow` - -#### Migration - -Deprecation of the `extract.annotations.regex` and `extract.labels.regex` fields means that it is recommended to use the `ExtractPatterns` function from the transform processor instead. To convert your current configuration please check the `ExtractPatterns` function [documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/ottlfuncs#extractpatterns). You should use the `pattern` parameter of `ExtractPatterns` instead of using the `extract.annotations.regex` and `extract.labels.regex` fields. - -##### Example - -The following configuration of `k8sattributes processor`: - -`config.yaml`: - - ```yaml - annotations: - - tag_name: a2 # extracts value of annotation with key `annotation2` with regexp and inserts it as a tag with key `a2` - key: annotation2 - regex: field=(?P.+) - from: pod - ``` - -can be converted with the usage of `ExtractPatterns` function: - -```yaml - - set(cache["annotations"], ExtractPatterns(attributes["k8s.pod.annotations["annotation2"], "field=(?P.+))") - - set(k8s.pod.annotations["a2"], cache["annotations"]["value"]) -``` diff --git a/processor/k8sattributesprocessor/config.go b/processor/k8sattributesprocessor/config.go index 336a50cd3809..13f36f33632a 100644 --- a/processor/k8sattributesprocessor/config.go +++ b/processor/k8sattributesprocessor/config.go @@ -8,20 +8,12 @@ import ( "regexp" "time" - "go.opentelemetry.io/collector/featuregate" conventions "go.opentelemetry.io/collector/semconv/v1.6.1" "github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sattributesprocessor/internal/kube" ) -var disallowFieldExtractConfigRegex = featuregate.GlobalRegistry().MustRegister( - "k8sattr.fieldExtractConfigRegex.disallow", - featuregate.StageBeta, - featuregate.WithRegisterDescription("When enabled, usage of the FieldExtractConfig.Regex field is disallowed"), - featuregate.WithRegisterFromVersion("v0.106.0"), -) - // Config defines configuration for k8s attributes processor. type Config struct { k8sconfig.APIConfig `mapstructure:",squash"` @@ -77,20 +69,6 @@ func (cfg *Config) Validate() error { return fmt.Errorf("%s is not a valid choice for From. Must be one of: pod, namespace, node", f.From) } - if f.Regex != "" { - if disallowFieldExtractConfigRegex.IsEnabled() { - return fmt.Errorf("the extract.annotations.regex and extract.labels.regex fields have been deprecated, please use the `ExtractPatterns` function in the transform processor instead") - } - r, err := regexp.Compile(f.Regex) - if err != nil { - return err - } - names := r.SubexpNames() - if len(names) != 2 || names[1] != "value" { - return fmt.Errorf("regex must contain exactly one named submatch (value)") - } - } - if f.KeyRegex != "" { _, err := regexp.Compile("^(?:" + f.KeyRegex + ")$") if err != nil { @@ -212,29 +190,6 @@ type FieldExtractConfig struct { // Out of Key or KeyRegex, only one option is expected to be configured at a time. KeyRegex string `mapstructure:"key_regex"` - // Regex is an optional field used to extract a sub-string from a complex field value. - // The supplied regular expression must contain one named parameter with the string "value" - // as the name. For example, if your pod spec contains the following annotation, - // - // kubernetes.io/change-cause: 2019-08-28T18:34:33Z APP_NAME=my-app GIT_SHA=58a1e39 CI_BUILD=4120 - // - // and you'd like to extract the GIT_SHA and the CI_BUILD values as tags, then you must - // specify the following two extraction rules: - // - // extract: - // annotations: - // - tag_name: git.sha - // key: kubernetes.io/change-cause - // regex: GIT_SHA=(?P\w+) - // - tag_name: ci.build - // key: kubernetes.io/change-cause - // regex: JENKINS=(?P[\w]+) - // - // this will add the `git.sha` and `ci.build` resource attributes. - // Deprecated: [v0.106.0] Use the `ExtractPatterns` function in the transform processor instead. - // More information about how to replace the regex field can be found in the k8sattributes processor readme. - Regex string `mapstructure:"regex"` - // From represents the source of the labels/annotations. // Allowed values are "pod", "namespace", and "node". The default is pod. From string `mapstructure:"from"` diff --git a/processor/k8sattributesprocessor/config_test.go b/processor/k8sattributesprocessor/config_test.go index fb452190e0d2..96c851d74034 100644 --- a/processor/k8sattributesprocessor/config_test.go +++ b/processor/k8sattributesprocessor/config_test.go @@ -13,7 +13,6 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/confmap/confmaptest" "go.opentelemetry.io/collector/confmap/xconfmap" - "go.opentelemetry.io/collector/featuregate" "github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sattributesprocessor/internal/kube" @@ -24,9 +23,8 @@ func TestLoadConfig(t *testing.T) { t.Parallel() tests := []struct { - id component.ID - expected component.Config - disallowRegex bool + id component.ID + expected component.Config }{ { id: component.NewID(metadata.Type), @@ -48,11 +46,11 @@ func TestLoadConfig(t *testing.T) { Metadata: []string{"k8s.pod.name", "k8s.pod.uid", "k8s.pod.ip", "k8s.deployment.name", "k8s.namespace.name", "k8s.node.name", "k8s.pod.start_time", "k8s.cluster.uid"}, Annotations: []FieldExtractConfig{ {TagName: "a1", Key: "annotation-one", From: "pod"}, - {TagName: "a2", Key: "annotation-two", Regex: "field=(?P.+)", From: kube.MetadataFromPod}, + {TagName: "a2", Key: "annotation-two", From: kube.MetadataFromPod}, }, Labels: []FieldExtractConfig{ {TagName: "l1", Key: "label1", From: "pod"}, - {TagName: "l2", Key: "label2", Regex: "field=(?P.+)", From: kube.MetadataFromPod}, + {TagName: "l2", Key: "label2", From: kube.MetadataFromPod}, }, }, Filter: FilterConfig{ @@ -110,7 +108,6 @@ func TestLoadConfig(t *testing.T) { }, WaitForMetadataTimeout: 10 * time.Second, }, - disallowRegex: false, }, { id: component.NewIDWithName(metadata.Type, "3"), @@ -135,37 +132,9 @@ func TestLoadConfig(t *testing.T) { WaitForMetadataTimeout: 10 * time.Second, }, }, - { - id: component.NewIDWithName(metadata.Type, "deprecated-regex"), - expected: &Config{ - APIConfig: k8sconfig.APIConfig{AuthType: k8sconfig.AuthTypeKubeConfig}, - Passthrough: false, - Extract: ExtractConfig{ - Metadata: enabledAttributes(), - Annotations: []FieldExtractConfig{ - {Regex: "field=(?P.+)", From: "pod"}, - }, - Labels: []FieldExtractConfig{ - {Regex: "field=(?P.+)", From: "pod"}, - }, - }, - Exclude: ExcludeConfig{ - Pods: []ExcludePodConfig{ - {Name: "jaeger-agent"}, - {Name: "jaeger-collector"}, - }, - }, - WaitForMetadataTimeout: 10 * time.Second, - }, - disallowRegex: false, - }, { id: component.NewIDWithName(metadata.Type, "too_many_sources"), }, - { - id: component.NewIDWithName(metadata.Type, "deprecated-regex"), - disallowRegex: true, - }, { id: component.NewIDWithName(metadata.Type, "bad_keys_labels"), }, @@ -178,30 +147,12 @@ func TestLoadConfig(t *testing.T) { { id: component.NewIDWithName(metadata.Type, "bad_from_annotations"), }, - { - id: component.NewIDWithName(metadata.Type, "bad_regex_labels"), - }, - { - id: component.NewIDWithName(metadata.Type, "bad_regex_annotations"), - }, { id: component.NewIDWithName(metadata.Type, "bad_keyregex_labels"), }, { id: component.NewIDWithName(metadata.Type, "bad_keyregex_annotations"), }, - { - id: component.NewIDWithName(metadata.Type, "bad_regex_groups_labels"), - }, - { - id: component.NewIDWithName(metadata.Type, "bad_regex_groups_annotations"), - }, - { - id: component.NewIDWithName(metadata.Type, "bad_regex_name_labels"), - }, - { - id: component.NewIDWithName(metadata.Type, "bad_regex_name_annotations"), - }, { id: component.NewIDWithName(metadata.Type, "bad_filter_label_op"), }, @@ -212,12 +163,6 @@ func TestLoadConfig(t *testing.T) { for _, tt := range tests { t.Run(tt.id.String(), func(t *testing.T) { - if !tt.disallowRegex { - require.NoError(t, featuregate.GlobalRegistry().Set(disallowFieldExtractConfigRegex.ID(), false)) - t.Cleanup(func() { - require.NoError(t, featuregate.GlobalRegistry().Set(disallowFieldExtractConfigRegex.ID(), true)) - }) - } cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml")) require.NoError(t, err) diff --git a/processor/k8sattributesprocessor/options.go b/processor/k8sattributesprocessor/options.go index 4ccccb0d4638..b1e2920401d9 100644 --- a/processor/k8sattributesprocessor/options.go +++ b/processor/k8sattributesprocessor/options.go @@ -236,15 +236,6 @@ func extractFieldRules(fieldType string, fields ...FieldExtractConfig) ([]kube.F name = fmt.Sprintf("k8s.%v.%v.%v", a.From, fieldType, a.Key) } - var r *regexp.Regexp - if a.Regex != "" { - var err error - r, err = regexp.Compile(a.Regex) - if err != nil { - return rules, err - } - } - var keyRegex *regexp.Regexp var hasKeyRegexReference bool if a.KeyRegex != "" { @@ -260,7 +251,7 @@ func extractFieldRules(fieldType string, fields ...FieldExtractConfig) ([]kube.F } rules = append(rules, kube.FieldExtractionRule{ - Name: name, Key: a.Key, KeyRegex: keyRegex, HasKeyRegexReference: hasKeyRegexReference, Regex: r, From: a.From, + Name: name, Key: a.Key, KeyRegex: keyRegex, HasKeyRegexReference: hasKeyRegexReference, From: a.From, }) } return rules, nil diff --git a/processor/k8sattributesprocessor/options_test.go b/processor/k8sattributesprocessor/options_test.go index 17ca2716a19f..3355988083a0 100644 --- a/processor/k8sattributesprocessor/options_test.go +++ b/processor/k8sattributesprocessor/options_test.go @@ -89,16 +89,14 @@ func TestWithExtractAnnotations(t *testing.T) { { TagName: "tag1", Key: "key1", - Regex: "field=(?P.+)", From: kube.MetadataFromPod, }, }, []kube.FieldExtractionRule{ { - Name: "tag1", - Key: "key1", - Regex: regexp.MustCompile(`field=(?P.+)`), - From: kube.MetadataFromPod, + Name: "tag1", + Key: "key1", + From: kube.MetadataFromPod, }, }, "", @@ -228,16 +226,14 @@ func TestWithExtractLabels(t *testing.T) { { TagName: "tag1", Key: "key1", - Regex: "field=(?P.+)", From: kube.MetadataFromPod, }, }, []kube.FieldExtractionRule{ { - Name: "tag1", - Key: "key1", - Regex: regexp.MustCompile(`field=(?P.+)`), - From: kube.MetadataFromPod, + Name: "tag1", + Key: "key1", + From: kube.MetadataFromPod, }, }, "", @@ -610,18 +606,6 @@ func Test_extractFieldRules(t *testing.T) { }, }, }, - { - name: "badregex", - args: args{"field", []FieldExtractConfig{ - { - TagName: "name", - Key: "key", - Regex: "[", - From: kube.MetadataFromPod, - }, - }}, - wantErr: true, - }, { name: "keyregex-capture-group", args: args{"labels", []FieldExtractConfig{ diff --git a/processor/k8sattributesprocessor/testdata/config.yaml b/processor/k8sattributesprocessor/testdata/config.yaml index 9ac386ad4763..6a6a355c8fe6 100644 --- a/processor/k8sattributesprocessor/testdata/config.yaml +++ b/processor/k8sattributesprocessor/testdata/config.yaml @@ -27,7 +27,6 @@ k8sattributes/2: from: pod - tag_name: a2 # extracts value of annotation with key `annotation-two` with regexp and inserts it as a tag with key `a2` key: annotation-two - regex: field=(?P.+) from: pod labels: - tag_name: l1 # extracts value of label with key `label1` and inserts it as a tag with key `l1` @@ -35,7 +34,6 @@ k8sattributes/2: from: pod - tag_name: l2 # extracts value of label with key `label1` with regexp and inserts it as a tag with key `l2` key: label2 - regex: field=(?P.+) from: pod filter: @@ -106,17 +104,6 @@ k8sattributes/too_many_sources: - from: connection name: ip -k8sattributes/deprecated-regex: - passthrough: false - auth_type: "kubeConfig" - extract: - labels: - - regex: field=(?P.+) - from: pod - annotations: - - regex: field=(?P.+) - from: pod - k8sattributes/bad_keys_labels: extract: labels: @@ -145,22 +132,6 @@ k8sattributes/bad_from_annotations: key: annotation1 from: unknown -k8sattributes/bad_regex_labels: - extract: - labels: - - tag_name: a1 - key: label1 - from: pod - regex: "[" - -k8sattributes/bad_regex_annotations: - extract: - annotations: - - tag_name: a1 - key: annotation1 - from: pod - regex: "[" - k8sattributes/bad_keyregex_labels: extract: labels: @@ -175,40 +146,6 @@ k8sattributes/bad_keyregex_annotations: from: pod key_regex: "[" - -k8sattributes/bad_regex_groups_labels: - extract: - labels: - - tag_name: a1 - key: label1 - from: pod - regex: "((.*)*)" - -k8sattributes/bad_regex_groups_annotations: - extract: - annotations: - - tag_name: a1 - key: annotation1 - from: pod - regex: "((.*)*)" - - -k8sattributes/bad_regex_name_labels: - extract: - labels: - - tag_name: a1 - key: label1 - from: pod - regex: "field=(?P.+)" - -k8sattributes/bad_regex_name_annotations: - extract: - annotations: - - tag_name: a1 - key: annotation1 - from: pod - regex: "field=(?P.+)" - k8sattributes/bad_filter_label_op: filter: labels: