diff --git a/.chloggen/headersetter_default_value.yaml b/.chloggen/headersetter_default_value.yaml new file mode 100644 index 000000000000..644b8d56553a --- /dev/null +++ b/.chloggen/headersetter_default_value.yaml @@ -0,0 +1,28 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: headersetterextension + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: adding default_value config + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [34412] + +# (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: | + default_value config item applied in case context value is empty + +# 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: [user] diff --git a/extension/headerssetterextension/README.md b/extension/headerssetterextension/README.md index 98fb3d5e93a9..7cbaf3383c84 100644 --- a/extension/headerssetterextension/README.md +++ b/extension/headerssetterextension/README.md @@ -34,11 +34,12 @@ The following settings are required: - `delete`: Deletes the header. - `value`: The header value is looked up from the `value` property of the extension configuration. + - `default_value`: (Optional) Value used if no entry for header key specified in `from_context` is present in request metadata. - `from_context`: The header value is looked up from the request metadata, such as HTTP headers, using the property value as the key (likely a header name). -The `value` and `from_context` properties are mutually exclusive. +The `value` and `from_context,default_value` properties are mutually exclusive. In order for `from_context` to work, other components in the pipeline also need to be configured appropriately: * If a [batch processor][batch-processor] is present in the pipeline, it must be configured to [preserve client metadata][batch-processor-preserve-metadata]. @@ -54,6 +55,7 @@ extensions: - action: insert key: X-Scope-OrgID from_context: tenant_id + default_value: Org-ID - action: upsert key: User-ID value: user_id diff --git a/extension/headerssetterextension/config.go b/extension/headerssetterextension/config.go index 73c688939c3b..55fe9cb07d1e 100644 --- a/extension/headerssetterextension/config.go +++ b/extension/headerssetterextension/config.go @@ -19,10 +19,11 @@ type Config struct { } type HeaderConfig struct { - Action ActionValue `mapstructure:"action"` - Key *string `mapstructure:"key"` - Value *string `mapstructure:"value"` - FromContext *string `mapstructure:"from_context"` + Action ActionValue `mapstructure:"action"` + Key *string `mapstructure:"key"` + Value *string `mapstructure:"value"` + FromContext *string `mapstructure:"from_context"` + DefaultValue *string `mapstructure:"default_value"` } // ActionValue is the enum to capture the four types of actions to perform on a header diff --git a/extension/headerssetterextension/config_test.go b/extension/headerssetterextension/config_test.go index 11ae3b04ab79..188d116898a5 100644 --- a/extension/headerssetterextension/config_test.go +++ b/extension/headerssetterextension/config_test.go @@ -36,6 +36,12 @@ func TestLoadConfig(t *testing.T) { Action: INSERT, FromContext: stringp("tenant_id"), Value: nil, + }, { + Key: stringp("X-Scope-OrgID"), + Action: INSERT, + FromContext: stringp("tenant_id"), + DefaultValue: stringp("some_id"), + Value: nil, }, { Key: stringp("User-ID"), @@ -148,6 +154,18 @@ func TestValidateConfig(t *testing.T) { }, errMissingSource, }, + { + "header value source is missing snd default value set", + []HeaderConfig{ + { + Key: stringp("name"), + Action: INSERT, + FromContext: stringp("from context"), + DefaultValue: stringp("default"), + }, + }, + nil, + }, { "delete header action", []HeaderConfig{ diff --git a/extension/headerssetterextension/extension.go b/extension/headerssetterextension/extension.go index ae2c0afbb752..c49588987f95 100644 --- a/extension/headerssetterextension/extension.go +++ b/extension/headerssetterextension/extension.go @@ -35,8 +35,13 @@ func newHeadersSetterExtension(cfg *Config, logger *zap.Logger) (auth.Client, er Value: *header.Value, } } else if header.FromContext != nil { + var defaultValue = "" + if header.DefaultValue != nil { + defaultValue = *header.DefaultValue + } s = &source.ContextSource{ - Key: *header.FromContext, + Key: *header.FromContext, + DefaultValue: defaultValue, } } diff --git a/extension/headerssetterextension/extension_test.go b/extension/headerssetterextension/extension_test.go index 409bfd70829e..e43619066b8a 100644 --- a/extension/headerssetterextension/extension_test.go +++ b/extension/headerssetterextension/extension_test.go @@ -218,6 +218,42 @@ var ( "header_name": "", }, }, + { + cfg: &Config{ + HeadersConfig: []HeaderConfig{ + { + Key: &header, + Action: INSERT, + FromContext: stringp("tenant"), + DefaultValue: stringp("default_tenant"), + }, + }, + }, + metadata: client.NewMetadata( + map[string][]string{}, + ), + expectedHeaders: map[string]string{ + "header_name": "default_tenant", + }, + }, + { + cfg: &Config{ + HeadersConfig: []HeaderConfig{ + { + Key: &header, + Action: INSERT, + FromContext: stringp("tenant"), + DefaultValue: stringp("default_tenant"), + }, + }, + }, + metadata: client.NewMetadata( + map[string][]string{"tenant": {"acme"}}, + ), + expectedHeaders: map[string]string{ + "header_name": "acme", + }, + }, } ) diff --git a/extension/headerssetterextension/internal/source/context.go b/extension/headerssetterextension/internal/source/context.go index 7cd40b7dadb2..20b15fb2f7eb 100644 --- a/extension/headerssetterextension/internal/source/context.go +++ b/extension/headerssetterextension/internal/source/context.go @@ -13,7 +13,8 @@ import ( var _ Source = (*ContextSource)(nil) type ContextSource struct { - Key string + Key string + DefaultValue string } func (ts *ContextSource) Get(ctx context.Context) (string, error) { @@ -21,7 +22,7 @@ func (ts *ContextSource) Get(ctx context.Context) (string, error) { ss := cl.Metadata.Get(ts.Key) if len(ss) == 0 { - return "", nil + return ts.DefaultValue, nil } if len(ss) > 1 { diff --git a/extension/headerssetterextension/testdata/config.yaml b/extension/headerssetterextension/testdata/config.yaml index 05dfe5403773..4762f609d97f 100644 --- a/extension/headerssetterextension/testdata/config.yaml +++ b/extension/headerssetterextension/testdata/config.yaml @@ -4,6 +4,10 @@ headers_setter/1: - key: X-Scope-OrgID action: insert from_context: "tenant_id" + - key: X-Scope-OrgID + action: insert + from_context: "tenant_id" + default_value: "some_id" - key: User-ID action: update from_context: "user_id"