Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .chloggen/list-map-duality.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 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. otlpreceiver)
component: all

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Change type of `configgrpc.ClientConfig.Headers`, `confighttp.ClientConfig.Headers`, and `confighttp.ServerConfig.ResponseHeaders`

# One or more tracking issues or pull requests related to the change
issues: [13930]

# (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: |
`configopaque.MapList` is a new alternative to `map[string]configopaque.String` which can unmarshal
both maps and lists of name/value pairs.

For example, if `headers` is a field of type `configopaque.MapList`,
then the following YAML configs will unmarshal to the same thing:
```yaml
headers:
"foo": "bar"

headers:
- name: "foo"
value: "bar"
```

# 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: [api]
1 change: 1 addition & 0 deletions .github/workflows/utils/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@
"logstest",
"lycheeverse",
"mapconverter",
"maplist",
"mapstructure",
"marshalers",
"mdatagen",
Expand Down
1 change: 1 addition & 0 deletions cmd/builder/internal/builder/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ var replaceModules = []string{
"/extension/zpagesextension",
"/extension/xextension",
"/featuregate",
"/internal/maplist",
"/internal/memorylimiter",
"/internal/fanoutconsumer",
"/internal/sharedcomponent",
Expand Down
2 changes: 2 additions & 0 deletions cmd/mdatagen/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,5 @@ replace go.opentelemetry.io/collector/pdata/xpdata => ../../pdata/xpdata
replace go.opentelemetry.io/collector/exporter/exporterhelper => ../../exporter/exporterhelper

replace go.opentelemetry.io/collector/service/telemetry/telemetrytest => ../../service/telemetry/telemetrytest

replace go.opentelemetry.io/collector/internal/maplist => ../../internal/maplist
1 change: 1 addition & 0 deletions cmd/otelcorecol/builder-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ replaces:
- go.opentelemetry.io/collector/extension/xextension => ../../extension/xextension
- go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension
- go.opentelemetry.io/collector/featuregate => ../../featuregate
- go.opentelemetry.io/collector/internal/maplist => ../../internal/maplist
- go.opentelemetry.io/collector/internal/memorylimiter => ../../internal/memorylimiter
- go.opentelemetry.io/collector/internal/fanoutconsumer => ../../internal/fanoutconsumer
- go.opentelemetry.io/collector/internal/telemetry => ../../internal/telemetry
Expand Down
3 changes: 3 additions & 0 deletions cmd/otelcorecol/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ require (
go.opentelemetry.io/collector/extension/xextension v0.137.0 // indirect
go.opentelemetry.io/collector/featuregate v1.43.0 // indirect
go.opentelemetry.io/collector/internal/fanoutconsumer v0.137.0 // indirect
go.opentelemetry.io/collector/internal/maplist v0.137.0 // indirect
go.opentelemetry.io/collector/internal/memorylimiter v0.137.0 // indirect
go.opentelemetry.io/collector/internal/sharedcomponent v0.137.0 // indirect
go.opentelemetry.io/collector/internal/telemetry v0.137.0 // indirect
Expand Down Expand Up @@ -282,6 +283,8 @@ replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extensi

replace go.opentelemetry.io/collector/featuregate => ../../featuregate

replace go.opentelemetry.io/collector/internal/maplist => ../../internal/maplist

replace go.opentelemetry.io/collector/internal/memorylimiter => ../../internal/memorylimiter

replace go.opentelemetry.io/collector/internal/fanoutconsumer => ../../internal/fanoutconsumer
Expand Down
6 changes: 6 additions & 0 deletions cmd/otelcorecol/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions config/configgrpc/configgrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ type ClientConfig struct {
WaitForReady bool `mapstructure:"wait_for_ready,omitempty"`

// The headers associated with gRPC requests.
Headers map[string]configopaque.String `mapstructure:"headers,omitempty"`
Headers configopaque.MapList `mapstructure:"headers,omitempty"`

// Sets the balancer in grpclb_policy to discover the servers. Default is pick_first.
// https://github.com/grpc/grpc-go/blob/master/examples/features/load_balancing/README.md
Expand Down Expand Up @@ -289,7 +289,7 @@ func (cc *ClientConfig) ToClientConn(
func (cc *ClientConfig) addHeadersIfAbsent(ctx context.Context) context.Context {
kv := make([]string, 0, 2*len(cc.Headers))
existingMd, _ := metadata.FromOutgoingContext(ctx)
for k, v := range cc.Headers {
for k, v := range cc.Headers.Pairs {
if len(existingMd.Get(k)) == 0 {
kv = append(kv, k, string(v))
}
Expand Down
20 changes: 10 additions & 10 deletions config/configgrpc/configgrpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ func TestAllGrpcClientSettings(t *testing.T) {
{
name: "test all with gzip compression",
settings: ClientConfig{
Headers: map[string]configopaque.String{
Headers: configopaque.MapListFromMap(map[string]configopaque.String{
"test": "test",
},
}),
Endpoint: "localhost:1234",
Compression: configcompression.TypeGzip,
TLS: configtls.ClientConfig{
Expand All @@ -192,9 +192,9 @@ func TestAllGrpcClientSettings(t *testing.T) {
{
name: "test all with snappy compression",
settings: ClientConfig{
Headers: map[string]configopaque.String{
Headers: configopaque.MapListFromMap(map[string]configopaque.String{
"test": "test",
},
}),
Endpoint: "localhost:1234",
Compression: configcompression.TypeSnappy,
TLS: configtls.ClientConfig{
Expand All @@ -221,9 +221,9 @@ func TestAllGrpcClientSettings(t *testing.T) {
{
name: "test all with zstd compression",
settings: ClientConfig{
Headers: map[string]configopaque.String{
Headers: configopaque.MapListFromMap(map[string]configopaque.String{
"test": "test",
},
}),
Endpoint: "localhost:1234",
Compression: configcompression.TypeZstd,
TLS: configtls.ClientConfig{
Expand Down Expand Up @@ -285,9 +285,9 @@ func TestHeaders(t *testing.T) {
TLS: configtls.ClientConfig{
Insecure: true,
},
Headers: map[string]configopaque.String{
Headers: configopaque.MapListFromMap(map[string]configopaque.String{
"testheader": "testvalue",
},
}),
})
require.NoError(t, errResp)
assert.NotNil(t, resp)
Expand Down Expand Up @@ -434,9 +434,9 @@ func TestGrpcServerAuthSettings(t *testing.T) {

func TestGrpcClientConfigInvalidBalancer(t *testing.T) {
settings := ClientConfig{
Headers: map[string]configopaque.String{
Headers: configopaque.MapListFromMap(map[string]configopaque.String{
"test": "test",
},
}),
Endpoint: "localhost:1234",
Compression: "gzip",
TLS: configtls.ClientConfig{
Expand Down
3 changes: 3 additions & 0 deletions config/configgrpc/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ require (
go.opentelemetry.io/collector/confmap v1.43.0 // indirect
go.opentelemetry.io/collector/confmap/xconfmap v0.137.0 // indirect
go.opentelemetry.io/collector/featuregate v1.43.0 // indirect
go.opentelemetry.io/collector/internal/maplist v0.137.0 // indirect
go.opentelemetry.io/collector/internal/telemetry v0.137.0 // indirect
go.opentelemetry.io/collector/pdata/pprofile v0.137.0 // indirect
go.opentelemetry.io/contrib/bridges/otelzap v0.13.0 // indirect
Expand Down Expand Up @@ -97,6 +98,8 @@ replace go.opentelemetry.io/collector/config/configmiddleware => ../configmiddle

replace go.opentelemetry.io/collector/extension/extensionmiddleware => ../../extension/extensionmiddleware

replace go.opentelemetry.io/collector/internal/maplist => ../../internal/maplist

replace go.opentelemetry.io/collector/pdata => ../../pdata

replace go.opentelemetry.io/collector/pdata/testdata => ../../pdata/testdata
Expand Down
6 changes: 6 additions & 0 deletions config/configgrpc/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 4 additions & 5 deletions config/confighttp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type ClientConfig struct {
// Additional headers attached to each HTTP request sent by the client.
// Existing header values are overwritten if collision happens.
// Header values are opaque since they may be sensitive.
Headers map[string]configopaque.String `mapstructure:"headers,omitempty"`
Headers configopaque.MapList `mapstructure:"headers,omitempty"`

// Auth configuration for outgoing HTTP calls.
Auth configoptional.Optional[configauth.Config] `mapstructure:"auth,omitempty"`
Expand Down Expand Up @@ -130,7 +130,6 @@ func NewDefaultClientConfig() ClientConfig {
defaultTransport := http.DefaultTransport.(*http.Transport)

return ClientConfig{
Headers: map[string]configopaque.String{},
MaxIdleConns: defaultTransport.MaxIdleConns,
IdleConnTimeout: defaultTransport.IdleConnTimeout,
ForceAttemptHTTP2: true,
Expand Down Expand Up @@ -283,18 +282,18 @@ func (cc *ClientConfig) ToClient(ctx context.Context, host component.Host, setti
// Custom RoundTripper that adds headers.
type headerRoundTripper struct {
transport http.RoundTripper
headers map[string]configopaque.String
headers configopaque.MapList
}

// RoundTrip is a custom RoundTripper that adds headers to the request.
func (interceptor *headerRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
// Set Host header if provided
hostHeader, found := interceptor.headers["Host"]
hostHeader, found := interceptor.headers.Get("Host")
if found && hostHeader != "" {
// `Host` field should be set to override default `Host` header value which is Endpoint
req.Host = string(hostHeader)
}
for k, v := range interceptor.headers {
for k, v := range interceptor.headers.Pairs {
req.Header.Set(k, string(v))
}

Expand Down
10 changes: 5 additions & 5 deletions config/confighttp/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ func TestHTTPClientSettingWithAuthConfig(t *testing.T) {
settings: ClientConfig{
Endpoint: "localhost:1234",
Auth: configoptional.Some(configauth.Config{AuthenticatorID: mockID}),
Headers: map[string]configopaque.String{"foo": "bar"},
Headers: configopaque.MapListFromMap(map[string]configopaque.String{"foo": "bar"}),
},
shouldErr: false,
host: &mockHost{
Expand Down Expand Up @@ -530,7 +530,7 @@ func TestHttpClientHeaders(t *testing.T) {
ReadBufferSize: 0,
WriteBufferSize: 0,
Timeout: 0,
Headers: tt.headers,
Headers: configopaque.MapListFromMap(tt.headers),
}
client, _ := setting.ToClient(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings())
req, err := http.NewRequest(http.MethodGet, setting.Endpoint, http.NoBody)
Expand Down Expand Up @@ -566,7 +566,7 @@ func TestHttpClientHostHeader(t *testing.T) {
ReadBufferSize: 0,
WriteBufferSize: 0,
Timeout: 0,
Headers: tt.headers,
Headers: configopaque.MapListFromMap(tt.headers),
}
client, _ := setting.ToClient(context.Background(), componenttest.NewNopHost(), componenttest.NewNopTelemetrySettings())
req, err := http.NewRequest(http.MethodGet, setting.Endpoint, http.NoBody)
Expand Down Expand Up @@ -724,10 +724,10 @@ func TestClientUnmarshalYAMLComprehensiveConfig(t *testing.T) {
assert.Equal(t, "example.com", clientConfig.TLS.ServerName)

// Verify headers
expectedHeaders := map[string]configopaque.String{
expectedHeaders := configopaque.MapListFromMap(map[string]configopaque.String{
"User-Agent": "OpenTelemetry-Collector/1.0",
"X-Custom-Header": "custom-value",
}
})
assert.Equal(t, expectedHeaders, clientConfig.Headers)

// Verify middlewares
Expand Down
3 changes: 3 additions & 0 deletions config/confighttp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ require (
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/collector/confmap v1.43.0
go.opentelemetry.io/collector/confmap/xconfmap v0.137.0
go.opentelemetry.io/collector/internal/maplist v0.137.0 // indirect
go.opentelemetry.io/collector/internal/telemetry v0.137.0 // indirect
go.opentelemetry.io/collector/pdata v1.43.0 // indirect
go.opentelemetry.io/contrib/bridges/otelzap v0.13.0 // indirect
Expand Down Expand Up @@ -104,6 +105,8 @@ replace go.opentelemetry.io/collector/client => ../../client

replace go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest => ../../extension/extensionauth/extensionauthtest

replace go.opentelemetry.io/collector/internal/maplist => ../../internal/maplist

replace go.opentelemetry.io/collector/internal/telemetry => ../../internal/telemetry

replace go.opentelemetry.io/collector/pipeline => ../../pipeline
Expand Down
6 changes: 6 additions & 0 deletions config/confighttp/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions config/confighttp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type ServerConfig struct {

// Additional headers attached to each HTTP response sent to the client.
// Header values are opaque since they may be sensitive.
ResponseHeaders map[string]configopaque.String `mapstructure:"response_headers"`
ResponseHeaders configopaque.MapList `mapstructure:"response_headers,omitempty"`

// CompressionAlgorithms configures the list of compression algorithms the server can accept. Default: ["", "gzip", "zstd", "zlib", "snappy", "deflate"]
CompressionAlgorithms []string `mapstructure:"compression_algorithms,omitempty"`
Expand Down Expand Up @@ -102,7 +102,6 @@ type ServerConfig struct {
// We encourage to use this function to create an object of ServerConfig.
func NewDefaultServerConfig() ServerConfig {
return ServerConfig{
ResponseHeaders: map[string]configopaque.String{},
WriteTimeout: 30 * time.Second,
ReadHeaderTimeout: 1 * time.Minute,
IdleTimeout: 1 * time.Minute,
Expand Down Expand Up @@ -287,11 +286,11 @@ func (sc *ServerConfig) ToServer(ctx context.Context, host component.Host, setti
return server, err
}

func responseHeadersHandler(handler http.Handler, headers map[string]configopaque.String) http.Handler {
func responseHeadersHandler(handler http.Handler, headers configopaque.MapList) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h := w.Header()

for k, v := range headers {
for k, v := range headers.Pairs {
h.Set(k, string(v))
}

Expand Down
8 changes: 4 additions & 4 deletions config/confighttp/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ func TestHttpServerHeaders(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
sc := &ServerConfig{
Endpoint: "localhost:0",
ResponseHeaders: tt.headers,
ResponseHeaders: configopaque.MapListFromMap(tt.headers),
}

ln, err := sc.ToListener(context.Background())
Expand Down Expand Up @@ -950,7 +950,7 @@ func BenchmarkHttpRequest(b *testing.B) {

func TestDefaultHTTPServerSettings(t *testing.T) {
httpServerSettings := NewDefaultServerConfig()
assert.NotNil(t, httpServerSettings.ResponseHeaders)
assert.Nil(t, httpServerSettings.ResponseHeaders)
assert.NotNil(t, httpServerSettings.CORS)
assert.NotNil(t, httpServerSettings.TLS)
assert.Equal(t, 1*time.Minute, httpServerSettings.IdleTimeout)
Expand Down Expand Up @@ -1138,10 +1138,10 @@ func TestServerUnmarshalYAMLComprehensiveConfig(t *testing.T) {
assert.Equal(t, 7200, serverConfig.CORS.Get().MaxAge)

// Verify response headers
expectedResponseHeaders := map[string]configopaque.String{
expectedResponseHeaders := configopaque.MapListFromMap(map[string]configopaque.String{
"Server": "OpenTelemetry-Collector",
"X-Flavor": "apple",
}
})
assert.Equal(t, expectedResponseHeaders, serverConfig.ResponseHeaders)

// Verify compression algorithms
Expand Down
Loading
Loading