Skip to content

Commit 265799d

Browse files
[pkg/stanza]: fix operator field config validation (open-telemetry#40728)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description A few operators with `entry.Field` in their config were validating their configuration in their `Build` function via a comparison to `entry.NewNilField`. This was an inaccuracy; when a field is not provided during the unmarshal step, nothing ever gets run to actually construct the underlying struct field, meaning that the `entry.Field` was functionally set to `entry.Field{}`. This is not the same as `entry.NewNilField` which actually implements and supplies an interface value under the hood. This caused bad configs to pass validation and led to collector panic instead of nice failure messages. This PR changed `entry.NewNilField` to actually produce the correct pattern for a "nil field", while leaving the original implementation intact in `entry.NewNoopField` in case it is useful elsewhere (though at the moment I only saw it used for nil comparisons, which as far as I can tell were either never useful or something got refactored without being caught). I also added functionality to `operatortest.ConfigUnmarshalTest` to check for validation failures by expecting a particular error when calling the operator's `Build` method. <!-- Issue number (e.g. open-telemetry#1234) or full URL to issue, if applicable. --> #### Link to tracking issue Addresses a panic discovered by open-telemetry#40398. <!--Describe what testing was performed and which tests were added.--> #### Testing Tests were added to each operator's config validation. I tested manually via a built collector by running the config from the linked issue and confirming that instead of `panic` I get an error message. ```shell 2025-06-15T01:53:10.582Z info [email protected]/service.go:199 Setting up own telemetry... {"resource": {}} 2025-06-15T01:53:10.582Z info builders/builders.go:26 Development component. May change in the future. {"resource": {}, "otelcol.component.id": "debug", "otelcol.component.kind": "exporter", "otelcol.signal": "logs"} Error: failed to build pipelines: failed to create "filelog/my-app-name" receiver for data type "logs": remove: field is empty 2025/06/15 01:53:10 collector server run finished with error: failed to build pipelines: failed to create "filelog/my-app-name" receiver for data type "logs": remove: field is empty ``` --------- Co-authored-by: Andrzej Stencel <[email protected]>
1 parent 4103fab commit 265799d

File tree

26 files changed

+304
-175
lines changed

26 files changed

+304
-175
lines changed
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: bug_fix
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: filelogreceiver
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Fix `remove`, `copy`, and `move` operator configuration validation.
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: [40728]
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: Previously, the receiver would allow configurations that were guaranteed to cause a Collector panic. The Collector will now fail to start with friendly error messages.
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: [user]

pkg/stanza/entry/field.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ func (r *RootableField) UnmarshalText(text []byte) error {
9696
return err
9797
}
9898

99+
func (f *Field) IsEmpty() bool {
100+
return *f == Field{}
101+
}
102+
99103
func NewField(s string) (Field, error) {
100104
return newField(s, false)
101105
}

pkg/stanza/entry/nil_field.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ package entry // import "github.com/open-telemetry/opentelemetry-collector-contr
66
// NilField is a struct that implements Field, but
77
// does nothing for all its operations. It is useful
88
// as a default no-op field to avoid nil checks.
9+
//
10+
// Deprecated: Originally used for empty Field comparisons,
11+
// use Field.IsEmpty instead.
912
type NilField struct{}
1013

1114
// Get will return always return nil

pkg/stanza/operator/helper/bytesize_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,20 +152,20 @@ func TestUnmarshalByteSize(t *testing.T) {
152152
}(),
153153
},
154154
{
155-
Name: `invalid_3ii3`,
156-
ExpectErr: true,
155+
Name: `invalid_3ii3`,
156+
ExpectUnmarshalErr: true,
157157
},
158158
{
159-
Name: `invalid_--ii3`,
160-
ExpectErr: true,
159+
Name: `invalid_--ii3`,
160+
ExpectUnmarshalErr: true,
161161
},
162162
{
163-
Name: `invalid_map`,
164-
ExpectErr: true,
163+
Name: `invalid_map`,
164+
ExpectUnmarshalErr: true,
165165
},
166166
{
167-
Name: `invalid_map2`,
168-
ExpectErr: true,
167+
Name: `invalid_map2`,
168+
ExpectUnmarshalErr: true,
169169
},
170170
},
171171
}.Run(t)

pkg/stanza/operator/helper/writer_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ func TestUnmarshalWriterConfig(t *testing.T) {
174174
}(),
175175
},
176176
{
177-
Name: "invalid",
178-
ExpectErr: true,
177+
Name: "invalid",
178+
ExpectUnmarshalErr: true,
179179
},
180180
},
181181
}.Run(t)

0 commit comments

Comments
 (0)