Skip to content

Commit d25dc2b

Browse files
authored
Merge branch 'main' into feat/add-getdependencies-v3api
2 parents b32c492 + 39ef71e commit d25dc2b

File tree

4 files changed

+168
-0
lines changed

4 files changed

+168
-0
lines changed

cmd/jaeger/config-elasticsearch.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ extensions:
4040
elasticsearch:
4141
server_urls:
4242
- http://localhost:9200
43+
# custom_headers:
44+
# Host: "my-opensearch-domain.us-east-1.es.amazonaws.com"
45+
# X-Custom-Header: "custom-value"
4346
indices:
4447
index_prefix: "jaeger-main"
4548
spans:

cmd/jaeger/config-opensearch.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ extensions:
4040
opensearch:
4141
server_urls:
4242
- http://localhost:9200
43+
# custom_headers:
44+
# Host: "my-opensearch-domain.us-east-1.es.amazonaws.com"
45+
# X-Custom-Header: "custom-value"
4346
indices:
4447
index_prefix: "jaeger-main"
4548
spans:

internal/storage/elasticsearch/config/config.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ type Configuration struct {
111111
// HTTPCompression can be set to false to disable gzip compression for requests to ElasticSearch
112112
HTTPCompression bool `mapstructure:"http_compression"`
113113

114+
// CustomHeaders contains custom HTTP headers to be sent with every request to Elasticsearch.
115+
// This is useful for scenarios like AWS SigV4 proxy authentication where specific headers
116+
// (like Host) need to be set for proper request signing.
117+
CustomHeaders map[string]string `mapstructure:"custom_headers"`
114118
// ---- elasticsearch client related configs ----
115119
BulkProcessing BulkProcessing `mapstructure:"bulk_processing"`
116120
// Version contains the major Elasticsearch version. If this field is not specified,
@@ -374,6 +378,15 @@ func newElasticsearchV8(ctx context.Context, c *Configuration, logger *zap.Logge
374378
}
375379
options.DiscoverNodesOnStart = c.Sniffing.Enabled
376380
options.CompressRequestBody = c.HTTPCompression
381+
382+
if len(c.CustomHeaders) > 0 {
383+
headers := make(http.Header)
384+
for key, value := range c.CustomHeaders {
385+
headers.Set(key, value)
386+
}
387+
options.Header = headers
388+
}
389+
377390
transport, err := GetHTTPRoundTripper(ctx, c, logger)
378391
if err != nil {
379392
return nil, err
@@ -493,6 +506,12 @@ func (c *Configuration) ApplyDefaults(source *Configuration) {
493506
if !c.HTTPCompression {
494507
c.HTTPCompression = source.HTTPCompression
495508
}
509+
if c.CustomHeaders == nil && len(source.CustomHeaders) > 0 {
510+
c.CustomHeaders = make(map[string]string)
511+
for k, v := range source.CustomHeaders {
512+
c.CustomHeaders[k] = v
513+
}
514+
}
496515
}
497516

498517
// RolloverFrequencyAsNegativeDuration returns the index rollover frequency duration for the given frequency string

internal/storage/elasticsearch/config/config_test.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,149 @@ func TestBulkCallbackInvoke_NilResponse(t *testing.T) {
16131613
)
16141614
}
16151615

1616+
func TestCustomHeaders(t *testing.T) {
1617+
tests := []struct {
1618+
name string
1619+
config Configuration
1620+
expected map[string]string
1621+
}{
1622+
{
1623+
name: "custom headers are set correctly",
1624+
config: Configuration{
1625+
Servers: []string{"http://localhost:9200"},
1626+
CustomHeaders: map[string]string{
1627+
"Host": "my-opensearch.amazonaws.com",
1628+
"X-Custom-Header": "test-value",
1629+
},
1630+
},
1631+
expected: map[string]string{
1632+
"Host": "my-opensearch.amazonaws.com",
1633+
"X-Custom-Header": "test-value",
1634+
},
1635+
},
1636+
{
1637+
name: "empty custom headers",
1638+
config: Configuration{
1639+
Servers: []string{"http://localhost:9200"},
1640+
CustomHeaders: map[string]string{},
1641+
},
1642+
expected: map[string]string{},
1643+
},
1644+
{
1645+
name: "nil custom headers",
1646+
config: Configuration{
1647+
Servers: []string{"http://localhost:9200"},
1648+
CustomHeaders: nil,
1649+
},
1650+
expected: nil,
1651+
},
1652+
}
1653+
1654+
for _, test := range tests {
1655+
t.Run(test.name, func(t *testing.T) {
1656+
if test.expected == nil {
1657+
assert.Nil(t, test.config.CustomHeaders)
1658+
} else {
1659+
assert.Equal(t, test.expected, test.config.CustomHeaders)
1660+
}
1661+
})
1662+
}
1663+
}
1664+
1665+
func TestApplyDefaultsCustomHeaders(t *testing.T) {
1666+
source := &Configuration{
1667+
CustomHeaders: map[string]string{
1668+
"Host": "source-host",
1669+
"X-Custom-Header": "source-value",
1670+
},
1671+
}
1672+
1673+
tests := []struct {
1674+
name string
1675+
target *Configuration
1676+
expected map[string]string
1677+
}{
1678+
{
1679+
name: "target has no headers, apply from source",
1680+
target: &Configuration{},
1681+
expected: map[string]string{
1682+
"Host": "source-host",
1683+
"X-Custom-Header": "source-value",
1684+
},
1685+
},
1686+
{
1687+
name: "target has headers, keep target headers",
1688+
target: &Configuration{
1689+
CustomHeaders: map[string]string{
1690+
"Host": "target-host",
1691+
},
1692+
},
1693+
expected: map[string]string{
1694+
"Host": "target-host",
1695+
},
1696+
},
1697+
{
1698+
name: "target has empty map, keep empty",
1699+
target: &Configuration{
1700+
CustomHeaders: map[string]string{},
1701+
},
1702+
expected: map[string]string{},
1703+
},
1704+
}
1705+
1706+
for _, test := range tests {
1707+
t.Run(test.name, func(t *testing.T) {
1708+
test.target.ApplyDefaults(source)
1709+
assert.Equal(t, test.expected, test.target.CustomHeaders)
1710+
})
1711+
}
1712+
}
1713+
1714+
func TestNewClientWithCustomHeaders(t *testing.T) {
1715+
headersSeen := false
1716+
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
1717+
// Check if custom headers are present
1718+
if req.Header.Get("X-Custom-Header") == "custom-value" {
1719+
headersSeen = true
1720+
}
1721+
res.WriteHeader(http.StatusOK)
1722+
res.Write(mockEsServerResponseWithVersion8)
1723+
}))
1724+
defer testServer.Close()
1725+
1726+
config := Configuration{
1727+
Servers: []string{testServer.URL},
1728+
CustomHeaders: map[string]string{
1729+
"Host": "my-opensearch.amazonaws.com",
1730+
"X-Custom-Header": "custom-value",
1731+
},
1732+
LogLevel: "error",
1733+
Version: 8,
1734+
}
1735+
1736+
logger := zap.NewNop()
1737+
metricsFactory := metrics.NullFactory
1738+
1739+
client, err := NewClient(context.Background(), &config, logger, metricsFactory)
1740+
require.NoError(t, err)
1741+
require.NotNil(t, client)
1742+
1743+
// Verify the configuration has the custom headers set
1744+
// Note: The ES v8 client may not send custom headers during the initial ping/health check,
1745+
// but they will be available for actual Elasticsearch operations (index, search, etc.)
1746+
assert.Equal(t, "my-opensearch.amazonaws.com", config.CustomHeaders["Host"])
1747+
assert.Equal(t, "custom-value", config.CustomHeaders["X-Custom-Header"])
1748+
1749+
if headersSeen {
1750+
t.Log(" Custom headers were transmitted in HTTP request")
1751+
} else {
1752+
t.Log(" Custom headers not sent in ping request (expected - will be sent in data operations)")
1753+
}
1754+
1755+
err = client.Close()
1756+
require.NoError(t, err)
1757+
}
1758+
16161759
func TestMain(m *testing.M) {
16171760
testutils.VerifyGoLeaks(m)
16181761
}

0 commit comments

Comments
 (0)