Skip to content

Commit e7148d5

Browse files
authored
[processor/k8sattributes] move k8sattr.fieldExtractConfigRegex.disallow feature gate to stable (#37615)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description move k8sattr.fieldExtractConfigRegex.disallow feature gate to stable which was hiding the `FieldExtractConfig.Regex` parameter and was deprecated. According to the standards, it can be now moved to `stable`. <!-- Issue number (e.g. #1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes #25128 --------- Signed-off-by: odubajDT <[email protected]>
1 parent 848f0c0 commit e7148d5

File tree

7 files changed

+45
-215
lines changed

7 files changed

+45
-215
lines changed

.chloggen/regex-deprecation.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: breaking
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: processor/k8sattributes
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: "Move k8sattr.fieldExtractConfigRegex.disallow feature gate to stable"
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [25128]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

processor/k8sattributesprocessor/README.md

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -233,21 +233,18 @@ extract:
233233
- tag_name: a1 # extracts value of annotation from pods with key `annotation-one` and inserts it as a tag with key `a1`
234234
key: annotation-one
235235
from: pod
236-
- tag_name: a2 # extracts value of annotation from namespaces with key `annotation-two` with regexp and inserts it as a tag with key `a2`
236+
- tag_name: a2 # extracts value of annotation from namespaces with key `annotation-two` and inserts it as a tag with key `a2`
237237
key: annotation-two
238-
regex: field=(?P<value>.+)
239238
from: namespace
240-
- tag_name: a3 # extracts value of annotation from nodes with key `annotation-three` with regexp and inserts it as a tag with key `a3`
239+
- tag_name: a3 # extracts value of annotation from nodes with key `annotation-three` and inserts it as a tag with key `a3`
241240
key: annotation-three
242-
regex: field=(?P<value>.+)
243241
from: node
244242
labels:
245243
- tag_name: l1 # extracts value of label from namespaces with key `label1` and inserts it as a tag with key `l1`
246244
key: label1
247245
from: namespace
248-
- tag_name: l2 # extracts value of label from pods with key `label2` with regexp and inserts it as a tag with key `l2`
246+
- tag_name: l2 # extracts value of label from pods with key `label2` and inserts it as a tag with key `l2`
249247
key: label2
250-
regex: field=(?P<value>.+)
251248
from: pod
252249
- tag_name: l3 # extracts value of label from nodes with key `label3` and inserts it as a tag with key `l3`
253250
key: label3
@@ -480,23 +477,7 @@ timestamp value as an RFC3339 compliant timestamp.
480477
### `k8sattr.fieldExtractConfigRegex.disallow`
481478

482479
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.
483-
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`).
484-
485-
#### Example Usage
486-
487-
The following config with the feature gate set will lead to validation error:
488-
489-
`config.yaml`:
490-
491-
```yaml
492-
extract:
493-
labels:
494-
regex: <my-regex1>
495-
annotations:
496-
regex: <my-regex2>
497-
```
498-
499-
Run collector: `./otelcol --config config.yaml --feature-gates=k8sattr.fieldExtractConfigRegex.disallow`
480+
The feature gate is in `stable` stage, which means it can no longer be disabled and is therefore enabled by default.
500481

501482
#### Migration
502483

processor/k8sattributesprocessor/config.go

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ import (
1515
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sattributesprocessor/internal/kube"
1616
)
1717

18+
//nolint:unused
1819
var disallowFieldExtractConfigRegex = featuregate.GlobalRegistry().MustRegister(
1920
"k8sattr.fieldExtractConfigRegex.disallow",
20-
featuregate.StageBeta,
21+
featuregate.StageStable,
2122
featuregate.WithRegisterDescription("When enabled, usage of the FieldExtractConfig.Regex field is disallowed"),
2223
featuregate.WithRegisterFromVersion("v0.106.0"),
24+
featuregate.WithRegisterToVersion("v0.122.0"),
2325
)
2426

2527
// Config defines configuration for k8s attributes processor.
@@ -77,20 +79,6 @@ func (cfg *Config) Validate() error {
7779
return fmt.Errorf("%s is not a valid choice for From. Must be one of: pod, namespace, node", f.From)
7880
}
7981

80-
if f.Regex != "" {
81-
if disallowFieldExtractConfigRegex.IsEnabled() {
82-
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")
83-
}
84-
r, err := regexp.Compile(f.Regex)
85-
if err != nil {
86-
return err
87-
}
88-
names := r.SubexpNames()
89-
if len(names) != 2 || names[1] != "value" {
90-
return fmt.Errorf("regex must contain exactly one named submatch (value)")
91-
}
92-
}
93-
9482
if f.KeyRegex != "" {
9583
_, err := regexp.Compile("^(?:" + f.KeyRegex + ")$")
9684
if err != nil {
@@ -212,29 +200,6 @@ type FieldExtractConfig struct {
212200
// Out of Key or KeyRegex, only one option is expected to be configured at a time.
213201
KeyRegex string `mapstructure:"key_regex"`
214202

215-
// Regex is an optional field used to extract a sub-string from a complex field value.
216-
// The supplied regular expression must contain one named parameter with the string "value"
217-
// as the name. For example, if your pod spec contains the following annotation,
218-
//
219-
// kubernetes.io/change-cause: 2019-08-28T18:34:33Z APP_NAME=my-app GIT_SHA=58a1e39 CI_BUILD=4120
220-
//
221-
// and you'd like to extract the GIT_SHA and the CI_BUILD values as tags, then you must
222-
// specify the following two extraction rules:
223-
//
224-
// extract:
225-
// annotations:
226-
// - tag_name: git.sha
227-
// key: kubernetes.io/change-cause
228-
// regex: GIT_SHA=(?P<value>\w+)
229-
// - tag_name: ci.build
230-
// key: kubernetes.io/change-cause
231-
// regex: JENKINS=(?P<value>[\w]+)
232-
//
233-
// this will add the `git.sha` and `ci.build` resource attributes.
234-
// Deprecated: [v0.106.0] Use the `ExtractPatterns` function in the transform processor instead.
235-
// More information about how to replace the regex field can be found in the k8sattributes processor readme.
236-
Regex string `mapstructure:"regex"`
237-
238203
// From represents the source of the labels/annotations.
239204
// Allowed values are "pod", "namespace", and "node". The default is pod.
240205
From string `mapstructure:"from"`

processor/k8sattributesprocessor/config_test.go

Lines changed: 4 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"go.opentelemetry.io/collector/component"
1414
"go.opentelemetry.io/collector/confmap/confmaptest"
1515
"go.opentelemetry.io/collector/confmap/xconfmap"
16-
"go.opentelemetry.io/collector/featuregate"
1716

1817
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig"
1918
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sattributesprocessor/internal/kube"
@@ -24,9 +23,8 @@ func TestLoadConfig(t *testing.T) {
2423
t.Parallel()
2524

2625
tests := []struct {
27-
id component.ID
28-
expected component.Config
29-
disallowRegex bool
26+
id component.ID
27+
expected component.Config
3028
}{
3129
{
3230
id: component.NewID(metadata.Type),
@@ -48,11 +46,11 @@ func TestLoadConfig(t *testing.T) {
4846
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"},
4947
Annotations: []FieldExtractConfig{
5048
{TagName: "a1", Key: "annotation-one", From: "pod"},
51-
{TagName: "a2", Key: "annotation-two", Regex: "field=(?P<value>.+)", From: kube.MetadataFromPod},
49+
{TagName: "a2", Key: "annotation-two", From: kube.MetadataFromPod},
5250
},
5351
Labels: []FieldExtractConfig{
5452
{TagName: "l1", Key: "label1", From: "pod"},
55-
{TagName: "l2", Key: "label2", Regex: "field=(?P<value>.+)", From: kube.MetadataFromPod},
53+
{TagName: "l2", Key: "label2", From: kube.MetadataFromPod},
5654
},
5755
},
5856
Filter: FilterConfig{
@@ -110,7 +108,6 @@ func TestLoadConfig(t *testing.T) {
110108
},
111109
WaitForMetadataTimeout: 10 * time.Second,
112110
},
113-
disallowRegex: false,
114111
},
115112
{
116113
id: component.NewIDWithName(metadata.Type, "3"),
@@ -135,37 +132,9 @@ func TestLoadConfig(t *testing.T) {
135132
WaitForMetadataTimeout: 10 * time.Second,
136133
},
137134
},
138-
{
139-
id: component.NewIDWithName(metadata.Type, "deprecated-regex"),
140-
expected: &Config{
141-
APIConfig: k8sconfig.APIConfig{AuthType: k8sconfig.AuthTypeKubeConfig},
142-
Passthrough: false,
143-
Extract: ExtractConfig{
144-
Metadata: enabledAttributes(),
145-
Annotations: []FieldExtractConfig{
146-
{Regex: "field=(?P<value>.+)", From: "pod"},
147-
},
148-
Labels: []FieldExtractConfig{
149-
{Regex: "field=(?P<value>.+)", From: "pod"},
150-
},
151-
},
152-
Exclude: ExcludeConfig{
153-
Pods: []ExcludePodConfig{
154-
{Name: "jaeger-agent"},
155-
{Name: "jaeger-collector"},
156-
},
157-
},
158-
WaitForMetadataTimeout: 10 * time.Second,
159-
},
160-
disallowRegex: false,
161-
},
162135
{
163136
id: component.NewIDWithName(metadata.Type, "too_many_sources"),
164137
},
165-
{
166-
id: component.NewIDWithName(metadata.Type, "deprecated-regex"),
167-
disallowRegex: true,
168-
},
169138
{
170139
id: component.NewIDWithName(metadata.Type, "bad_keys_labels"),
171140
},
@@ -178,30 +147,12 @@ func TestLoadConfig(t *testing.T) {
178147
{
179148
id: component.NewIDWithName(metadata.Type, "bad_from_annotations"),
180149
},
181-
{
182-
id: component.NewIDWithName(metadata.Type, "bad_regex_labels"),
183-
},
184-
{
185-
id: component.NewIDWithName(metadata.Type, "bad_regex_annotations"),
186-
},
187150
{
188151
id: component.NewIDWithName(metadata.Type, "bad_keyregex_labels"),
189152
},
190153
{
191154
id: component.NewIDWithName(metadata.Type, "bad_keyregex_annotations"),
192155
},
193-
{
194-
id: component.NewIDWithName(metadata.Type, "bad_regex_groups_labels"),
195-
},
196-
{
197-
id: component.NewIDWithName(metadata.Type, "bad_regex_groups_annotations"),
198-
},
199-
{
200-
id: component.NewIDWithName(metadata.Type, "bad_regex_name_labels"),
201-
},
202-
{
203-
id: component.NewIDWithName(metadata.Type, "bad_regex_name_annotations"),
204-
},
205156
{
206157
id: component.NewIDWithName(metadata.Type, "bad_filter_label_op"),
207158
},
@@ -212,12 +163,6 @@ func TestLoadConfig(t *testing.T) {
212163

213164
for _, tt := range tests {
214165
t.Run(tt.id.String(), func(t *testing.T) {
215-
if !tt.disallowRegex {
216-
require.NoError(t, featuregate.GlobalRegistry().Set(disallowFieldExtractConfigRegex.ID(), false))
217-
t.Cleanup(func() {
218-
require.NoError(t, featuregate.GlobalRegistry().Set(disallowFieldExtractConfigRegex.ID(), true))
219-
})
220-
}
221166
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
222167
require.NoError(t, err)
223168

processor/k8sattributesprocessor/options.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -236,15 +236,6 @@ func extractFieldRules(fieldType string, fields ...FieldExtractConfig) ([]kube.F
236236
name = fmt.Sprintf("k8s.%v.%v.%v", a.From, fieldType, a.Key)
237237
}
238238

239-
var r *regexp.Regexp
240-
if a.Regex != "" {
241-
var err error
242-
r, err = regexp.Compile(a.Regex)
243-
if err != nil {
244-
return rules, err
245-
}
246-
}
247-
248239
var keyRegex *regexp.Regexp
249240
var hasKeyRegexReference bool
250241
if a.KeyRegex != "" {
@@ -260,7 +251,7 @@ func extractFieldRules(fieldType string, fields ...FieldExtractConfig) ([]kube.F
260251
}
261252

262253
rules = append(rules, kube.FieldExtractionRule{
263-
Name: name, Key: a.Key, KeyRegex: keyRegex, HasKeyRegexReference: hasKeyRegexReference, Regex: r, From: a.From,
254+
Name: name, Key: a.Key, KeyRegex: keyRegex, HasKeyRegexReference: hasKeyRegexReference, From: a.From,
264255
})
265256
}
266257
return rules, nil

processor/k8sattributesprocessor/options_test.go

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,14 @@ func TestWithExtractAnnotations(t *testing.T) {
8989
{
9090
TagName: "tag1",
9191
Key: "key1",
92-
Regex: "field=(?P<value>.+)",
9392
From: kube.MetadataFromPod,
9493
},
9594
},
9695
[]kube.FieldExtractionRule{
9796
{
98-
Name: "tag1",
99-
Key: "key1",
100-
Regex: regexp.MustCompile(`field=(?P<value>.+)`),
101-
From: kube.MetadataFromPod,
97+
Name: "tag1",
98+
Key: "key1",
99+
From: kube.MetadataFromPod,
102100
},
103101
},
104102
"",
@@ -228,16 +226,14 @@ func TestWithExtractLabels(t *testing.T) {
228226
{
229227
TagName: "tag1",
230228
Key: "key1",
231-
Regex: "field=(?P<value>.+)",
232229
From: kube.MetadataFromPod,
233230
},
234231
},
235232
[]kube.FieldExtractionRule{
236233
{
237-
Name: "tag1",
238-
Key: "key1",
239-
Regex: regexp.MustCompile(`field=(?P<value>.+)`),
240-
From: kube.MetadataFromPod,
234+
Name: "tag1",
235+
Key: "key1",
236+
From: kube.MetadataFromPod,
241237
},
242238
},
243239
"",
@@ -610,18 +606,6 @@ func Test_extractFieldRules(t *testing.T) {
610606
},
611607
},
612608
},
613-
{
614-
name: "badregex",
615-
args: args{"field", []FieldExtractConfig{
616-
{
617-
TagName: "name",
618-
Key: "key",
619-
Regex: "[",
620-
From: kube.MetadataFromPod,
621-
},
622-
}},
623-
wantErr: true,
624-
},
625609
{
626610
name: "keyregex-capture-group",
627611
args: args{"labels", []FieldExtractConfig{

0 commit comments

Comments
 (0)