Skip to content

Commit 5f13d28

Browse files
Merge branch 'main' of github.com:elastic/elasticsearch into custom-inference-service
2 parents 8a82163 + 5df5cb8 commit 5f13d28

File tree

119 files changed

+4009
-962
lines changed

Some content is hidden

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

119 files changed

+4009
-962
lines changed

.buildkite/scripts/dra-workflow.trigger.sh

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,34 @@
22

33
set -euo pipefail
44

5-
echo "steps:"
6-
75
source .buildkite/scripts/branches.sh
86

7+
# We use that filtering to keep different schedule for different branches
8+
if [ -n "${INCLUDED_BRANCHES:-}" ]; then
9+
# If set, only trigger the pipeline for the specified branches
10+
IFS=',' read -r -a BRANCHES <<< "${INCLUDED_BRANCHES}"
11+
elif [ -n "${EXCLUDED_BRANCHES:-}" ]; then
12+
# If set, listed branches will be excluded from the list of branches in branches.json
13+
IFS=',' read -r -a EXCLUDED_BRANCHES <<< "${EXCLUDED_BRANCHES}"
14+
FILTERED_BRANCHES=()
15+
for BRANCH in "${BRANCHES[@]}"; do
16+
EXCLUDE=false
17+
for EXCLUDED_BRANCH in "${EXCLUDED_BRANCHES[@]}"; do
18+
if [ "$BRANCH" == "$EXCLUDED_BRANCH" ]; then
19+
EXCLUDE=true
20+
break
21+
fi
22+
done
23+
if [ "$EXCLUDE" = false ]; then
24+
FILTERED_BRANCHES+=("$BRANCH")
25+
fi
26+
done
27+
BRANCHES=("${FILTERED_BRANCHES[@]}")
28+
fi
29+
30+
31+
echo "steps:"
32+
933
for BRANCH in "${BRANCHES[@]}"; do
1034
INTAKE_PIPELINE_SLUG="elasticsearch-intake"
1135
BUILD_JSON=$(curl -sH "Authorization: Bearer ${BUILDKITE_API_TOKEN}" "https://api.buildkite.com/v2/organizations/elastic/pipelines/${INTAKE_PIPELINE_SLUG}/builds?branch=${BRANCH}&state=passed&per_page=1" | jq '.[0] | {commit: .commit, url: .web_url}')

BUILDING.md

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ In case of updating a dependency, ensure to remove the unused entry of the outda
8282

8383
You can also automate the generation of this entry by running your build using the `--write-verification-metadata` commandline option:
8484
```
85-
>./gradlew --write-verification-metadata sha256 precommit
85+
./gradlew --write-verification-metadata sha256 precommit
8686
```
8787

8888
The `--write-verification-metadata` Gradle option is generally able to resolve reachable configurations,
@@ -92,10 +92,10 @@ uses the changed dependencies. In most cases, `precommit` or `check` are good ca
9292
We prefer sha256 checksums as md5 and sha1 are not considered safe anymore these days. The generated entry
9393
will have the `origin` attribute been set to `Generated by Gradle`.
9494

95-
>A manual confirmation of the Gradle generated checksums is currently not mandatory.
96-
>If you want to add a level of verification you can manually confirm the checksum (e.g. by looking it up on the website of the library)
97-
>Please replace the content of the `origin` attribute by `official site` in that case.
98-
>
95+
> [!Tip]
96+
> A manual confirmation of the Gradle generated checksums is currently not mandatory.
97+
> If you want to add a level of verification you can manually confirm the checksum (e.g. by looking it up on the website of the library)
98+
> Please replace the content of the `origin` attribute by `official site` in that case.
9999
100100
#### Custom plugin and task implementations
101101

@@ -229,13 +229,9 @@ In addition to snapshot builds JitPack supports building Pull Requests. Simply u
229229
3. Run the Gradle build as needed. Keep in mind the initial resolution might take a bit longer as this needs to be built
230230
by JitPack in the background before we can resolve the adhoc built dependency.
231231

232-
---
233-
234-
**NOTE**
235-
236-
You should only use that approach locally or on a developer branch for production dependencies as we do
232+
> [!Note]
233+
> You should only use that approach locally or on a developer branch for production dependencies as we do
237234
not want to ship unreleased libraries into our releases.
238-
---
239235

240236
#### How to use a custom third party artifact?
241237

@@ -265,12 +261,9 @@ allprojects {
265261
```
266262
4. Run the Gradle build as needed with `--write-verification-metadata` to ensure the Gradle dependency verification does not fail on your custom dependency.
267263

268-
---
269-
**NOTE**
270-
271-
As Gradle prefers to use modules whose descriptor has been created from real meta-data rather than being generated,
264+
> [!Note]
265+
> As Gradle prefers to use modules whose descriptor has been created from real meta-data rather than being generated,
272266
flat directory repositories cannot be used to override artifacts with real meta-data from other repositories declared in the build.
273-
For example, if Gradle finds only `jmxri-1.2.1.jar` in a flat directory repository, but `jmxri-1.2.1.pom` in another repository
267+
> For example, if Gradle finds only `jmxri-1.2.1.jar` in a flat directory repository, but `jmxri-1.2.1.pom` in another repository
274268
that supports meta-data, it will use the second repository to provide the module.
275-
Therefore, it is recommended to declare a version that is not resolvable from public repositories we use (e.g. Maven Central)
276-
---
269+
> Therefore, it is recommended to declare a version that is not resolvable from public repositories we use (e.g. Maven Central)

CONTRIBUTING.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,8 @@ It is important that the only code covered by the Elastic licence is contained
401401
within the top-level `x-pack` directory. The build will fail its pre-commit
402402
checks if contributed code does not have the appropriate license headers.
403403

404-
> **NOTE:** If you have imported the project into IntelliJ IDEA the project will
404+
> [!NOTE]
405+
> If you have imported the project into IntelliJ IDEA the project will
405406
> be automatically configured to add the correct license header to new source
406407
> files based on the source location.
407408

docs/changelog/127383.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 127383
2+
summary: Don't push down filters on the right hand side of an inlinejoin
3+
area: ES|QL
4+
type: bug
5+
issues: []

docs/changelog/127573.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 127573
2+
summary: "[Failure store] Introduce default retention for failure indices"
3+
area: Data streams
4+
type: enhancement
5+
issues: []

docs/changelog/127668.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 127668
2+
summary: Fix transport versions
3+
area: "ES|QL"
4+
type: bug
5+
issues:
6+
- 127667
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
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.entitlement.initialization;
11+
12+
import org.elasticsearch.core.internal.provider.ProviderLocator;
13+
import org.elasticsearch.entitlement.bridge.EntitlementChecker;
14+
import org.elasticsearch.entitlement.instrumentation.CheckMethod;
15+
import org.elasticsearch.entitlement.instrumentation.InstrumentationService;
16+
import org.elasticsearch.entitlement.instrumentation.Instrumenter;
17+
import org.elasticsearch.entitlement.instrumentation.MethodKey;
18+
import org.elasticsearch.entitlement.instrumentation.Transformer;
19+
20+
import java.lang.instrument.Instrumentation;
21+
import java.lang.instrument.UnmodifiableClassException;
22+
import java.net.URI;
23+
import java.nio.channels.spi.SelectorProvider;
24+
import java.nio.file.AccessMode;
25+
import java.nio.file.CopyOption;
26+
import java.nio.file.DirectoryStream;
27+
import java.nio.file.FileStore;
28+
import java.nio.file.FileSystems;
29+
import java.nio.file.LinkOption;
30+
import java.nio.file.OpenOption;
31+
import java.nio.file.Path;
32+
import java.nio.file.WatchEvent;
33+
import java.nio.file.WatchService;
34+
import java.nio.file.attribute.FileAttribute;
35+
import java.nio.file.spi.FileSystemProvider;
36+
import java.util.ArrayList;
37+
import java.util.HashMap;
38+
import java.util.List;
39+
import java.util.Map;
40+
import java.util.Set;
41+
import java.util.concurrent.ExecutorService;
42+
import java.util.function.Function;
43+
import java.util.stream.Collectors;
44+
import java.util.stream.Stream;
45+
import java.util.stream.StreamSupport;
46+
47+
class DynamicInstrumentation {
48+
49+
interface InstrumentationInfoFactory {
50+
InstrumentationService.InstrumentationInfo of(String methodName, Class<?>... parameterTypes) throws ClassNotFoundException,
51+
NoSuchMethodException;
52+
}
53+
54+
private static final InstrumentationService INSTRUMENTATION_SERVICE = new ProviderLocator<>(
55+
"entitlement",
56+
InstrumentationService.class,
57+
"org.elasticsearch.entitlement.instrumentation",
58+
Set.of()
59+
).get();
60+
61+
/**
62+
* Initializes the dynamic (agent-based) instrumentation:
63+
* <ol>
64+
* <li>
65+
* Finds the version-specific subclass of {@link EntitlementChecker} to use
66+
* </li>
67+
* <li>
68+
* Builds the set of methods to instrument using {@link InstrumentationService#lookupMethods}
69+
* </li>
70+
* <li>
71+
* Augment this set “dynamically” using {@link InstrumentationService#lookupImplementationMethod}
72+
* </li>
73+
* <li>
74+
* Creates an {@link Instrumenter} via {@link InstrumentationService#newInstrumenter}, and adds a new {@link Transformer} (derived from
75+
* {@link java.lang.instrument.ClassFileTransformer}) that uses it. Transformers are invoked when a class is about to load, after its
76+
* bytes have been deserialized to memory but before the class is initialized.
77+
* </li>
78+
* <li>
79+
* Re-transforms all already loaded classes: we force the {@link Instrumenter} to run on classes that might have been already loaded
80+
* before entitlement initialization by calling the {@link java.lang.instrument.Instrumentation#retransformClasses} method on all
81+
* classes that were already loaded.
82+
* </li>
83+
* </ol>
84+
* <p>
85+
* The third step is needed as the JDK exposes some API through interfaces that have different (internal) implementations
86+
* depending on the JVM host platform. As we cannot instrument an interfaces, we find its concrete implementation.
87+
* A prime example is {@link FileSystemProvider}, which has different implementations (e.g. {@code UnixFileSystemProvider} or
88+
* {@code WindowsFileSystemProvider}). At runtime, we find the implementation class which is currently used by the JVM, and add
89+
* its methods to the set of methods to instrument. See e.g. {@link DynamicInstrumentation#fileSystemProviderChecks}.
90+
* </p>
91+
*
92+
* @param inst the JVM instrumentation class instance
93+
* @param checkerInterface the interface to use to find methods to instrument and to use in the injected instrumentation code
94+
* @param verifyBytecode whether we should perform bytecode verification before and after instrumenting each method
95+
*/
96+
static void initialize(Instrumentation inst, Class<?> checkerInterface, boolean verifyBytecode) throws ClassNotFoundException,
97+
NoSuchMethodException, UnmodifiableClassException {
98+
99+
var checkMethods = getMethodsToInstrument(checkerInterface);
100+
var classesToTransform = checkMethods.keySet().stream().map(MethodKey::className).collect(Collectors.toSet());
101+
102+
Instrumenter instrumenter = INSTRUMENTATION_SERVICE.newInstrumenter(checkerInterface, checkMethods);
103+
var transformer = new Transformer(instrumenter, classesToTransform, verifyBytecode);
104+
inst.addTransformer(transformer, true);
105+
106+
var classesToRetransform = findClassesToRetransform(inst.getAllLoadedClasses(), classesToTransform);
107+
try {
108+
inst.retransformClasses(classesToRetransform);
109+
} catch (VerifyError e) {
110+
// Turn on verification and try to retransform one class at the time to get detailed diagnostic
111+
transformer.enableClassVerification();
112+
113+
for (var classToRetransform : classesToRetransform) {
114+
inst.retransformClasses(classToRetransform);
115+
}
116+
117+
// We should have failed already in the loop above, but just in case we did not, rethrow.
118+
throw e;
119+
}
120+
}
121+
122+
private static Map<MethodKey, CheckMethod> getMethodsToInstrument(Class<?> checkerInterface) throws ClassNotFoundException,
123+
NoSuchMethodException {
124+
Map<MethodKey, CheckMethod> checkMethods = new HashMap<>(INSTRUMENTATION_SERVICE.lookupMethods(checkerInterface));
125+
Stream.of(
126+
fileSystemProviderChecks(),
127+
fileStoreChecks(),
128+
pathChecks(),
129+
Stream.of(
130+
INSTRUMENTATION_SERVICE.lookupImplementationMethod(
131+
SelectorProvider.class,
132+
"inheritedChannel",
133+
SelectorProvider.provider().getClass(),
134+
EntitlementChecker.class,
135+
"checkSelectorProviderInheritedChannel"
136+
)
137+
)
138+
)
139+
.flatMap(Function.identity())
140+
.forEach(instrumentation -> checkMethods.put(instrumentation.targetMethod(), instrumentation.checkMethod()));
141+
142+
return checkMethods;
143+
}
144+
145+
private static Stream<InstrumentationService.InstrumentationInfo> fileSystemProviderChecks() throws ClassNotFoundException,
146+
NoSuchMethodException {
147+
var fileSystemProviderClass = FileSystems.getDefault().provider().getClass();
148+
149+
var instrumentation = new InstrumentationInfoFactory() {
150+
@Override
151+
public InstrumentationService.InstrumentationInfo of(String methodName, Class<?>... parameterTypes)
152+
throws ClassNotFoundException, NoSuchMethodException {
153+
return INSTRUMENTATION_SERVICE.lookupImplementationMethod(
154+
FileSystemProvider.class,
155+
methodName,
156+
fileSystemProviderClass,
157+
EntitlementChecker.class,
158+
"check" + Character.toUpperCase(methodName.charAt(0)) + methodName.substring(1),
159+
parameterTypes
160+
);
161+
}
162+
};
163+
164+
return Stream.of(
165+
instrumentation.of("newFileSystem", URI.class, Map.class),
166+
instrumentation.of("newFileSystem", Path.class, Map.class),
167+
instrumentation.of("newInputStream", Path.class, OpenOption[].class),
168+
instrumentation.of("newOutputStream", Path.class, OpenOption[].class),
169+
instrumentation.of("newFileChannel", Path.class, Set.class, FileAttribute[].class),
170+
instrumentation.of("newAsynchronousFileChannel", Path.class, Set.class, ExecutorService.class, FileAttribute[].class),
171+
instrumentation.of("newByteChannel", Path.class, Set.class, FileAttribute[].class),
172+
instrumentation.of("newDirectoryStream", Path.class, DirectoryStream.Filter.class),
173+
instrumentation.of("createDirectory", Path.class, FileAttribute[].class),
174+
instrumentation.of("createSymbolicLink", Path.class, Path.class, FileAttribute[].class),
175+
instrumentation.of("createLink", Path.class, Path.class),
176+
instrumentation.of("delete", Path.class),
177+
instrumentation.of("deleteIfExists", Path.class),
178+
instrumentation.of("readSymbolicLink", Path.class),
179+
instrumentation.of("copy", Path.class, Path.class, CopyOption[].class),
180+
instrumentation.of("move", Path.class, Path.class, CopyOption[].class),
181+
instrumentation.of("isSameFile", Path.class, Path.class),
182+
instrumentation.of("isHidden", Path.class),
183+
instrumentation.of("getFileStore", Path.class),
184+
instrumentation.of("checkAccess", Path.class, AccessMode[].class),
185+
instrumentation.of("getFileAttributeView", Path.class, Class.class, LinkOption[].class),
186+
instrumentation.of("readAttributes", Path.class, Class.class, LinkOption[].class),
187+
instrumentation.of("readAttributes", Path.class, String.class, LinkOption[].class),
188+
instrumentation.of("readAttributesIfExists", Path.class, Class.class, LinkOption[].class),
189+
instrumentation.of("setAttribute", Path.class, String.class, Object.class, LinkOption[].class),
190+
instrumentation.of("exists", Path.class, LinkOption[].class)
191+
);
192+
}
193+
194+
private static Stream<InstrumentationService.InstrumentationInfo> fileStoreChecks() {
195+
var fileStoreClasses = StreamSupport.stream(FileSystems.getDefault().getFileStores().spliterator(), false)
196+
.map(FileStore::getClass)
197+
.distinct();
198+
return fileStoreClasses.flatMap(fileStoreClass -> {
199+
var instrumentation = new InstrumentationInfoFactory() {
200+
@Override
201+
public InstrumentationService.InstrumentationInfo of(String methodName, Class<?>... parameterTypes)
202+
throws ClassNotFoundException, NoSuchMethodException {
203+
return INSTRUMENTATION_SERVICE.lookupImplementationMethod(
204+
FileStore.class,
205+
methodName,
206+
fileStoreClass,
207+
EntitlementChecker.class,
208+
"check" + Character.toUpperCase(methodName.charAt(0)) + methodName.substring(1),
209+
parameterTypes
210+
);
211+
}
212+
};
213+
214+
try {
215+
return Stream.of(
216+
instrumentation.of("getFileStoreAttributeView", Class.class),
217+
instrumentation.of("getAttribute", String.class),
218+
instrumentation.of("getBlockSize"),
219+
instrumentation.of("getTotalSpace"),
220+
instrumentation.of("getUnallocatedSpace"),
221+
instrumentation.of("getUsableSpace"),
222+
instrumentation.of("isReadOnly"),
223+
instrumentation.of("name"),
224+
instrumentation.of("type")
225+
226+
);
227+
} catch (NoSuchMethodException | ClassNotFoundException e) {
228+
throw new RuntimeException(e);
229+
}
230+
});
231+
}
232+
233+
private static Stream<InstrumentationService.InstrumentationInfo> pathChecks() {
234+
var pathClasses = StreamSupport.stream(FileSystems.getDefault().getRootDirectories().spliterator(), false)
235+
.map(Path::getClass)
236+
.distinct();
237+
return pathClasses.flatMap(pathClass -> {
238+
InstrumentationInfoFactory instrumentation = (String methodName, Class<?>... parameterTypes) -> INSTRUMENTATION_SERVICE
239+
.lookupImplementationMethod(
240+
Path.class,
241+
methodName,
242+
pathClass,
243+
EntitlementChecker.class,
244+
"checkPath" + Character.toUpperCase(methodName.charAt(0)) + methodName.substring(1),
245+
parameterTypes
246+
);
247+
248+
try {
249+
return Stream.of(
250+
instrumentation.of("toRealPath", LinkOption[].class),
251+
instrumentation.of("register", WatchService.class, WatchEvent.Kind[].class),
252+
instrumentation.of("register", WatchService.class, WatchEvent.Kind[].class, WatchEvent.Modifier[].class)
253+
);
254+
} catch (NoSuchMethodException | ClassNotFoundException e) {
255+
throw new RuntimeException(e);
256+
}
257+
});
258+
}
259+
260+
private static Class<?>[] findClassesToRetransform(Class<?>[] loadedClasses, Set<String> classesToTransform) {
261+
List<Class<?>> retransform = new ArrayList<>();
262+
for (Class<?> loadedClass : loadedClasses) {
263+
if (classesToTransform.contains(loadedClass.getName().replace(".", "/"))) {
264+
retransform.add(loadedClass);
265+
}
266+
}
267+
return retransform.toArray(new Class<?>[0]);
268+
}
269+
}

0 commit comments

Comments
 (0)