Skip to content

Commit 2d0b64c

Browse files
authored
Merge branch 'main' into fix-release-tests-forfips
2 parents a2aaee4 + 3f5f899 commit 2d0b64c

File tree

45 files changed

+787
-1087
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+787
-1087
lines changed

.buildkite/scripts/third-party-test-credentials.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set -euo pipefail
77
# The second/lowercase export is what the tests expect/require
88

99
if [[ "${USE_3RD_PARTY_AZURE_CREDENTIALS:-}" == "true" ]]; then
10+
# These credentials expire periodically and must be manually renewed - the process is in the onboarding/process docs.
1011
json=$(vault read -format=json secret/ci/elastic-elasticsearch/migrated/azure_thirdparty_test_creds)
1112

1213
AZURE_STORAGE_ACCOUNT_SECRET=$(echo "$json" | jq -r .data.account_id)
@@ -19,6 +20,7 @@ if [[ "${USE_3RD_PARTY_AZURE_CREDENTIALS:-}" == "true" ]]; then
1920
fi
2021

2122
if [[ "${USE_3RD_PARTY_AZURE_SAS_CREDENTIALS:-}" == "true" ]]; then
23+
# These credentials expire periodically and must be manually renewed - the process is in the onboarding/process docs.
2224
json=$(vault read -format=json secret/ci/elastic-elasticsearch/migrated/azure_thirdparty_sas_test_creds)
2325

2426
AZURE_STORAGE_ACCOUNT_SECRET=$(echo "$json" | jq -r .data.account_id)

docs/changelog/127817.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 127817
2+
summary: Replace auto-read with proper flow-control in HTTP pipeline
3+
area: Network
4+
type: enhancement
5+
issues: []

docs/reference/query-languages/esql/kibana/definition/commands/change_point.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/dissect.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/drop.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/enrich.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/eval.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/explain.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/fork.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/grok.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/inlinestats.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/insist.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/keep.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/limit.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/lookup.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/lookup_join.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/mv_expand.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/rename.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/rerank.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/rrf.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/sample.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/sort.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/stats.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/commands/where.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/entitlement/agent/src/main/java/org/elasticsearch/entitlement/agent/EntitlementAgent.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,16 @@
2525
*/
2626
public class EntitlementAgent {
2727

28+
/**
29+
* The agent main method
30+
* @param agentArgs arguments passed to the agent.For our agent, this is the class to load and use for Entitlement Initialization.
31+
* See e.g. {@code EntitlementsBootstrap#loadAgent}
32+
* @param inst The {@link Instrumentation} instance to use for injecting Entitlements checks
33+
*/
2834
public static void agentmain(String agentArgs, Instrumentation inst) {
2935
final Class<?> initClazz;
3036
try {
31-
initClazz = Class.forName("org.elasticsearch.entitlement.initialization.EntitlementInitialization");
37+
initClazz = Class.forName(agentArgs);
3238
} catch (ClassNotFoundException e) {
3339
throw new AssertionError("entitlement agent does could not find EntitlementInitialization", e);
3440
}

libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/EntitlementBootstrap.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ private static void loadAgent(String agentPath) {
138138
try {
139139
VirtualMachine vm = VirtualMachine.attach(Long.toString(ProcessHandle.current().pid()));
140140
try {
141-
vm.loadAgent(agentPath);
141+
vm.loadAgent(agentPath, EntitlementInitialization.class.getName());
142142
} finally {
143143
vm.detach();
144144
}
@@ -154,7 +154,7 @@ private static void exportInitializationToAgent() {
154154
EntitlementInitialization.class.getModule().addExports(initPkg, unnamedModule);
155155
}
156156

157-
private static String findAgentJar() {
157+
public static String findAgentJar() {
158158
String propertyName = "es.entitlement.agentJar";
159159
String propertyValue = System.getProperty(propertyName);
160160
if (propertyValue != null) {

modules/repository-azure/src/internalClusterTest/java/org/elasticsearch/repositories/azure/AzureStorageCleanupThirdPartyTests.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@
4848
import static org.hamcrest.Matchers.equalTo;
4949
import static org.hamcrest.Matchers.not;
5050

51+
/**
52+
* These tests sometimes run against a genuine Azure endpoint with credentials obtained from Vault. These credentials expire periodically
53+
* and must be manually renewed; the process is in the onboarding/process docs.
54+
*/
5155
public class AzureStorageCleanupThirdPartyTests extends AbstractThirdPartyRepositoryTestCase {
5256
private static final Logger logger = LogManager.getLogger(AzureStorageCleanupThirdPartyTests.class);
5357
private static final boolean USE_FIXTURE = Booleans.parseBoolean(System.getProperty("test.azure.fixture", "true"));

modules/transport-netty4/src/internalClusterTest/java/org/elasticsearch/http/netty4/Netty4IncrementalRequestHandlingIT.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ public void testClientConnectionCloseMidStream() throws Exception {
208208

209209
// await stream handler is ready and request full content
210210
var handler = clientContext.awaitRestChannelAccepted(opaqueId);
211-
assertBusy(() -> assertNotEquals(0, handler.stream.bufSize()));
212211

213212
assertFalse(handler.isClosed());
214213

@@ -218,7 +217,6 @@ public void testClientConnectionCloseMidStream() throws Exception {
218217
assertEquals(requestTransmittedLength, handler.readUntilClose());
219218

220219
assertTrue(handler.isClosed());
221-
assertEquals(0, handler.stream.bufSize());
222220
}
223221
}
224222

@@ -235,7 +233,6 @@ public void testServerCloseConnectionMidStream() throws Exception {
235233

236234
// await stream handler is ready and request full content
237235
var handler = clientContext.awaitRestChannelAccepted(opaqueId);
238-
assertBusy(() -> assertNotEquals(0, handler.stream.bufSize()));
239236
assertFalse(handler.isClosed());
240237

241238
// terminate connection on server and wait resources are released
@@ -244,7 +241,6 @@ public void testServerCloseConnectionMidStream() throws Exception {
244241
handler.channel.request().getHttpChannel().close();
245242
assertThat(safeGet(exceptionFuture), instanceOf(ClosedChannelException.class));
246243
assertTrue(handler.isClosed());
247-
assertBusy(() -> assertEquals(0, handler.stream.bufSize()));
248244
}
249245
}
250246

@@ -260,7 +256,6 @@ public void testServerExceptionMidStream() throws Exception {
260256

261257
// await stream handler is ready and request full content
262258
var handler = clientContext.awaitRestChannelAccepted(opaqueId);
263-
assertBusy(() -> assertNotEquals(0, handler.stream.bufSize()));
264259
assertFalse(handler.isClosed());
265260

266261
// terminate connection on server and wait resources are released
@@ -272,7 +267,6 @@ public void testServerExceptionMidStream() throws Exception {
272267
final var exception = asInstanceOf(RuntimeException.class, safeGet(exceptionFuture));
273268
assertEquals(ServerRequestHandler.SIMULATED_EXCEPTION_MESSAGE, exception.getMessage());
274269
safeAwait(handler.closedLatch);
275-
assertBusy(() -> assertEquals(0, handler.stream.bufSize()));
276270
}
277271
}
278272

@@ -313,7 +307,7 @@ public void testClientBackpressure() throws Exception {
313307
});
314308
handler.readBytes(partSize);
315309
}
316-
assertTrue(handler.stream.hasLast());
310+
assertTrue(handler.receivedLastChunk);
317311
}
318312
}
319313

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.http.netty4;
11+
12+
import io.netty.channel.ChannelDuplexHandler;
13+
import io.netty.channel.ChannelHandlerContext;
14+
import io.netty.util.concurrent.ScheduledFuture;
15+
16+
import org.apache.logging.log4j.LogManager;
17+
import org.apache.logging.log4j.Logger;
18+
import org.elasticsearch.common.time.TimeProvider;
19+
import org.elasticsearch.common.util.concurrent.FutureUtils;
20+
21+
import java.util.concurrent.TimeUnit;
22+
23+
/**
24+
* When channel auto-read is disabled handlers are responsible to read from channel.
25+
* But it's hard to detect when read is missing. This helper class print warnings
26+
* when no reads where detected in given time interval. Normally, in tests, 10 seconds is enough
27+
* to avoid test hang for too long, but can be increased if needed.
28+
*/
29+
class MissingReadDetector extends ChannelDuplexHandler {
30+
31+
private static final Logger logger = LogManager.getLogger(MissingReadDetector.class);
32+
33+
private final long interval;
34+
private final TimeProvider timer;
35+
private boolean pendingRead;
36+
private long lastRead;
37+
private ScheduledFuture<?> checker;
38+
39+
MissingReadDetector(TimeProvider timer, long missingReadIntervalMillis) {
40+
this.interval = missingReadIntervalMillis;
41+
this.timer = timer;
42+
}
43+
44+
@Override
45+
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
46+
checker = ctx.channel().eventLoop().scheduleAtFixedRate(() -> {
47+
if (pendingRead == false) {
48+
long now = timer.absoluteTimeInMillis();
49+
if (now >= lastRead + interval) {
50+
logger.warn("chan-id={} haven't read from channel for [{}ms]", ctx.channel().id(), (now - lastRead));
51+
}
52+
}
53+
}, interval, interval, TimeUnit.MILLISECONDS);
54+
super.handlerAdded(ctx);
55+
}
56+
57+
@Override
58+
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
59+
if (checker != null) {
60+
FutureUtils.cancel(checker);
61+
}
62+
super.handlerRemoved(ctx);
63+
}
64+
65+
@Override
66+
public void read(ChannelHandlerContext ctx) throws Exception {
67+
pendingRead = true;
68+
ctx.read();
69+
}
70+
71+
@Override
72+
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
73+
assert ctx.channel().config().isAutoRead() == false : "auto-read must be always disabled";
74+
pendingRead = false;
75+
lastRead = timer.absoluteTimeInMillis();
76+
ctx.fireChannelRead(msg);
77+
}
78+
}

modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpAggregator.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.netty.handler.codec.http.HttpObjectAggregator;
1616
import io.netty.handler.codec.http.HttpRequest;
1717
import io.netty.handler.codec.http.HttpRequestDecoder;
18+
import io.netty.handler.codec.http.LastHttpContent;
1819

1920
import org.elasticsearch.http.HttpPreRequest;
2021
import org.elasticsearch.http.netty4.internal.HttpHeadersAuthenticatorUtils;
@@ -48,6 +49,9 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
4849
}
4950
if (aggregating || msg instanceof FullHttpRequest) {
5051
super.channelRead(ctx, msg);
52+
if (msg instanceof LastHttpContent == false) {
53+
ctx.read(); // HttpObjectAggregator is tricky with auto-read off, it might not call read again, calling on its behalf
54+
}
5155
} else {
5256
streamContentSizeHandler.channelRead(ctx, msg);
5357
}

modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpContentSizeHandler.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ private void handleRequest(ChannelHandlerContext ctx, HttpRequest request) {
123123
isContinueExpected = true;
124124
} else {
125125
ctx.writeAndFlush(EXPECTATION_FAILED_CLOSE.retainedDuplicate()).addListener(ChannelFutureListener.CLOSE);
126+
ctx.read();
126127
return;
127128
}
128129
}
@@ -136,6 +137,7 @@ private void handleRequest(ChannelHandlerContext ctx, HttpRequest request) {
136137
decoder.reset();
137138
}
138139
ctx.writeAndFlush(TOO_LARGE.retainedDuplicate()).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
140+
ctx.read();
139141
} else {
140142
ignoreContent = false;
141143
currentContentLength = 0;
@@ -150,11 +152,13 @@ private void handleRequest(ChannelHandlerContext ctx, HttpRequest request) {
150152
private void handleContent(ChannelHandlerContext ctx, HttpContent msg) {
151153
if (ignoreContent) {
152154
msg.release();
155+
ctx.read();
153156
} else {
154157
currentContentLength += msg.content().readableBytes();
155158
if (currentContentLength > maxContentLength) {
156159
msg.release();
157160
ctx.writeAndFlush(TOO_LARGE_CLOSE.retainedDuplicate()).addListener(ChannelFutureListener.CLOSE);
161+
ctx.read();
158162
} else {
159163
ctx.fireChannelRead(msg);
160164
}

0 commit comments

Comments
 (0)