Skip to content

Commit 89c07dd

Browse files
authored
Merge branch 'main' into custom_receiverhelper
2 parents b77091f + d8db3e2 commit 89c07dd

File tree

21 files changed

+355
-19
lines changed

21 files changed

+355
-19
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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. otlpreceiver)
7+
component: configoptional
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Allow validating nested types
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [13579]
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: '`configoptional.Optional` now implements `xconfmap.Validator`'
19+
20+
# Optional: The change log or logs in which this entry should be included.
21+
# e.g. '[user]' or '[user, api]'
22+
# Include 'user' if the change is relevant to end users.
23+
# Include 'api' if there is a change to a library API.
24+
# Default: '[user]'
25+
change_logs: [user, api]

config/configgrpc/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ require (
5353
github.com/pmezard/go-difflib v1.0.0 // indirect
5454
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
5555
go.opentelemetry.io/collector/confmap v1.38.0 // indirect
56+
go.opentelemetry.io/collector/confmap/xconfmap v0.132.0 // indirect
5657
go.opentelemetry.io/collector/featuregate v1.38.0 // indirect
5758
go.opentelemetry.io/collector/internal/telemetry v0.132.0 // indirect
5859
go.opentelemetry.io/collector/pdata/pprofile v0.132.0 // indirect
@@ -119,3 +120,5 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate
119120
replace go.opentelemetry.io/collector/extension/extensionmiddleware/extensionmiddlewaretest => ../../extension/extensionmiddleware/extensionmiddlewaretest
120121

121122
replace go.opentelemetry.io/collector/confmap => ../../confmap
123+
124+
replace go.opentelemetry.io/collector/confmap/xconfmap => ../../confmap/xconfmap

config/confighttp/xconfighttp/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ require (
4747
go.opentelemetry.io/collector/config/configoptional v0.132.0 // indirect
4848
go.opentelemetry.io/collector/config/configtls v1.38.0 // indirect
4949
go.opentelemetry.io/collector/confmap v1.38.0 // indirect
50+
go.opentelemetry.io/collector/confmap/xconfmap v0.132.0 // indirect
5051
go.opentelemetry.io/collector/extension/extensionauth v1.38.0 // indirect
5152
go.opentelemetry.io/collector/extension/extensionmiddleware v0.132.0 // indirect
5253
go.opentelemetry.io/collector/featuregate v1.38.0 // indirect

config/configoptional/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.24
55
require (
66
github.com/stretchr/testify v1.10.0
77
go.opentelemetry.io/collector/confmap v1.38.0
8+
go.opentelemetry.io/collector/confmap/xconfmap v0.132.0
89
go.uber.org/goleak v1.3.0
910
)
1011

@@ -29,3 +30,5 @@ require (
2930
replace go.opentelemetry.io/collector/confmap => ../../confmap
3031

3132
replace go.opentelemetry.io/collector/featuregate => ../../featuregate
33+
34+
replace go.opentelemetry.io/collector/confmap/xconfmap => ../../confmap/xconfmap

config/configoptional/optional.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strings"
1111

1212
"go.opentelemetry.io/collector/confmap"
13+
"go.opentelemetry.io/collector/confmap/xconfmap"
1314
)
1415

1516
type flavor int
@@ -189,3 +190,26 @@ func (o Optional[T]) Marshal(conf *confmap.Conf) error {
189190

190191
return nil
191192
}
193+
194+
var _ xconfmap.Validator = (*Optional[any])(nil)
195+
196+
// Validate implements [xconfmap.Validator]. This is required because the
197+
// private fields in [xconfmap.Validator] can't be seen by the reflection used
198+
// by [xconfmap.Validate], and therefore we have to continue the validation
199+
// chain manually. This method isn't meant to be called directly, and should
200+
// generally only be called by [xconfmap.Validate].
201+
func (o *Optional[T]) Validate() error {
202+
// When the flavor is None, the user has not passed this value,
203+
// and therefore we should not validate it. The parent struct holding
204+
// the Optional type can determine whether a None value is valid for
205+
// a given config.
206+
//
207+
// If the flavor is still Default, then the user has not passed this
208+
// value and we should also not validate it.
209+
if o.flavor == noneFlavor || o.flavor == defaultFlavor {
210+
return nil
211+
}
212+
213+
// For the some flavor, validate the actual value.
214+
return xconfmap.Validate(o.value)
215+
}

config/configoptional/optional_test.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
package configoptional
55

66
import (
7+
"errors"
78
"fmt"
89
"testing"
910

1011
"github.com/stretchr/testify/assert"
1112
"github.com/stretchr/testify/require"
1213

1314
"go.opentelemetry.io/collector/confmap"
15+
"go.opentelemetry.io/collector/confmap/confmaptest"
16+
"go.opentelemetry.io/collector/confmap/xconfmap"
1417
)
1518

1619
type Config[T any] struct {
@@ -460,3 +463,123 @@ func TestComparePointerMarshal(t *testing.T) {
460463
})
461464
}
462465
}
466+
467+
type invalid struct{}
468+
469+
func (invalid) Validate() error {
470+
return errors.New("invalid")
471+
}
472+
473+
var _ xconfmap.Validator = invalid{}
474+
475+
type hasNested struct {
476+
CouldBe Optional[invalid]
477+
}
478+
479+
func TestOptionalValidate(t *testing.T) {
480+
require.NoError(t, xconfmap.Validate(hasNested{
481+
CouldBe: None[invalid](),
482+
}))
483+
require.NoError(t, xconfmap.Validate(hasNested{
484+
CouldBe: Default(invalid{}),
485+
}))
486+
require.Error(t, xconfmap.Validate(hasNested{
487+
CouldBe: Some(invalid{}),
488+
}))
489+
}
490+
491+
type validatedConfig struct {
492+
Default Optional[optionalConfig] `mapstructure:"default"`
493+
Some Optional[someConfig] `mapstructure:"some"`
494+
}
495+
496+
var _ xconfmap.Validator = (*optionalConfig)(nil)
497+
498+
type optionalConfig struct {
499+
StringVal string `mapstructure:"string_val"`
500+
}
501+
502+
func (n optionalConfig) Validate() error {
503+
if n.StringVal == "invalid" {
504+
return errors.New("field `string_val` cannot be set to `invalid`")
505+
}
506+
507+
return nil
508+
}
509+
510+
type someConfig struct {
511+
Nested Optional[optionalConfig] `mapstructure:"nested"`
512+
}
513+
514+
func newDefaultValidatedConfig() validatedConfig {
515+
return validatedConfig{
516+
Default: Default(optionalConfig{StringVal: "valid"}),
517+
}
518+
}
519+
520+
func newInvalidDefaultConfig() validatedConfig {
521+
return validatedConfig{
522+
Default: Default(optionalConfig{StringVal: "invalid"}),
523+
}
524+
}
525+
526+
func TestOptionalFileValidate(t *testing.T) {
527+
cases := []struct {
528+
name string
529+
variant string
530+
cfg func() validatedConfig
531+
err error
532+
}{
533+
{
534+
name: "valid default with just key set and no subfields",
535+
variant: "implicit",
536+
cfg: newDefaultValidatedConfig,
537+
},
538+
{
539+
name: "valid default with keys set in default",
540+
variant: "explicit",
541+
cfg: newDefaultValidatedConfig,
542+
},
543+
{
544+
name: "invalid config",
545+
variant: "invalid",
546+
cfg: newDefaultValidatedConfig,
547+
err: errors.New("default: field `string_val` cannot be set to `invalid`\nsome: nested: field `string_val` cannot be set to `invalid`"),
548+
},
549+
{
550+
name: "invalid default throws an error",
551+
variant: "implicit",
552+
cfg: newInvalidDefaultConfig,
553+
err: errors.New("default: field `string_val` cannot be set to `invalid`"),
554+
},
555+
{
556+
name: "invalid default does not throw an error when key is not set",
557+
variant: "no_default",
558+
cfg: newInvalidDefaultConfig,
559+
},
560+
{
561+
name: "invalid default invalid default does not throw an error when the value is overridden",
562+
variant: "explicit",
563+
cfg: newInvalidDefaultConfig,
564+
},
565+
}
566+
567+
for _, tt := range cases {
568+
t.Run(tt.name, func(t *testing.T) {
569+
conf, err := confmaptest.LoadConf(fmt.Sprintf("testdata/validate_%s.yaml", tt.variant))
570+
require.NoError(t, err)
571+
572+
cfg := tt.cfg()
573+
574+
err = conf.Unmarshal(&cfg)
575+
require.NoError(t, err)
576+
577+
err = xconfmap.Validate(cfg)
578+
if tt.err == nil {
579+
require.NoError(t, err)
580+
} else {
581+
require.EqualError(t, err, tt.err.Error())
582+
}
583+
})
584+
}
585+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
default:
2+
string_val: valid
3+
some:
4+
nested:
5+
string_val: valid
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
default:
2+
some:
3+
nested:
4+
string_val: value1
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
default:
2+
string_val: invalid
3+
some:
4+
nested:
5+
string_val: invalid
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
some:
2+
nested:
3+
string_val: value1

0 commit comments

Comments
 (0)