diff --git a/.ci/bwcVersions b/.ci/bwcVersions
index 81181301895e..6dabe613c827 100644
--- a/.ci/bwcVersions
+++ b/.ci/bwcVersions
@@ -57,6 +57,8 @@ BWC_VERSION:
- "7.17.6"
- "7.17.7"
- "7.17.8"
+ - "7.17.9"
+ - "7.17.10"
- "8.0.0"
- "8.0.1"
- "8.1.0"
@@ -78,5 +80,8 @@ BWC_VERSION:
- "8.5.0"
- "8.5.1"
- "8.5.2"
+ - "8.5.3"
- "8.6.0"
+ - "8.6.1"
+ - "8.6.2"
- "8.7.0"
diff --git a/.ci/jobs.t/elastic+elasticsearch+dra-snapshot.yml b/.ci/jobs.t/elastic+elasticsearch+dra-snapshot.yml
new file mode 100644
index 000000000000..37fdd85ee656
--- /dev/null
+++ b/.ci/jobs.t/elastic+elasticsearch+dra-snapshot.yml
@@ -0,0 +1,67 @@
+---
+- job:
+ name: elastic+elasticsearch+%BRANCH%+dra-snapshot
+ workspace: /dev/shm/elastic+elasticsearch+%BRANCH%+dra-snapshot
+ display-name: "elastic / elasticsearch # %BRANCH% - DRA snapshot"
+ description: "Publishing Daily Releasable Artifacts (DRAs) of Elasticsearch %BRANCH% snapshots.\n"
+ node: "ubuntu-20.04"
+ builders:
+ - inject:
+ properties-file: '.ci/java-versions.properties'
+ properties-content: |
+ JAVA_HOME=$HOME/.java/$ES_BUILD_JAVA
+ RUNTIME_JAVA_HOME=$HOME/.java/$ES_RUNTIME_JAVA
+ - shell: |
+ #!/usr/local/bin/runbld --redirect-stderr
+ WORKFLOW="snapshot"
+ RM_BRANCH="%BRANCH%" && [[ "%BRANCH%" == "main" ]] && RM_BRANCH=master
+ ES_VERSION=$(cat build-tools-internal/version.properties \
+ | grep elasticsearch \
+ | sed "s/elasticsearch *= *//g")
+ VERSION_SUFFIX="" && [[ "$WORKFLOW" == "snapshot" ]] && VERSION_SUFFIX="-SNAPSHOT"
+ BEATS_BUILD_ID="$(./.ci/scripts/resolve-dra-manifest.sh beats $RM_BRANCH $ES_VERSION $WORKFLOW)"
+ ML_CPP_BUILD_ID="$(./.ci/scripts/resolve-dra-manifest.sh ml-cpp $RM_BRANCH $ES_VERSION $WORKFLOW)"
+ set -euo pipefail
+ set +x
+ VAULT_TOKEN=$(vault write -field=token auth/approle/login role_id=$VAULT_ROLE_ID secret_id=$VAULT_SECRET_ID)
+ export VAULT_TOKEN
+ $WORKSPACE/.ci/scripts/run-gradle.sh -Ddra.artifacts=true \
+ -Ddra.artifacts.dependency.beats=${BEATS_BUILD_ID} \
+ -Ddra.artifacts.dependency.ml-cpp=${ML_CPP_BUILD_ID} \
+ -Ddra.workflow=$WORKFLOW \
+ -Dcsv=$WORKSPACE/build/distributions/dependencies-${ES_VERSION}${VERSION_SUFFIX}.csv \
+ buildReleaseArtifacts \
+ exportCompressedDockerImages \
+ :distribution:generateDependenciesReport
+
+ unset VAULT_TOKEN
+ set -x
+ $WORKSPACE/x-pack/plugin/sql/connectors/tableau/package.sh asm qualifier="$VERSION_SUFFIX"
+
+ # we regenerate this file as part of the release manager invocation
+ rm $WORKSPACE/build/distributions/elasticsearch-jdbc-${ES_VERSION}${VERSION_SUFFIX}.taco.sha512
+
+ # Allow other users access to read the artifacts so they are readable in the
+ # container
+ find $WORKSPACE -type f -path "*/build/distributions/*" -exec chmod a+r {} \;
+
+ # Allow other users write access to create checksum files
+ find $WORKSPACE -type d -path "*/build/distributions" -exec chmod a+w {} \;
+
+ # Artifacts should be generated
+ docker run --rm \
+ --name release-manager \
+ -e VAULT_ADDR \
+ -e VAULT_ROLE_ID \
+ -e VAULT_SECRET_ID \
+ --mount type=bind,readonly=false,src="$PWD",target=/artifacts \
+ docker.elastic.co/infra/release-manager:latest \
+ cli collect \
+ --project elasticsearch \
+ --branch "$RM_BRANCH" \
+ --commit "$GIT_COMMIT" \
+ --workflow "$WORKFLOW" \
+ --version "$ES_VERSION" \
+ --artifact-set main \
+ --dependency beats:https://artifacts-${WORKFLOW}.elastic.co/beats/${BEATS_BUILD_ID}/manifest-${ES_VERSION}${VERSION_SUFFIX}.json \
+ --dependency ml-cpp:https://artifacts-${WORKFLOW}.elastic.co/ml-cpp/${ML_CPP_BUILD_ID}/manifest-${ES_VERSION}${VERSION_SUFFIX}.json
diff --git a/.ci/jobs.t/elastic+elasticsearch+dra-staging-trigger.yml b/.ci/jobs.t/elastic+elasticsearch+dra-staging-trigger.yml
new file mode 100644
index 000000000000..87df5e07c2e4
--- /dev/null
+++ b/.ci/jobs.t/elastic+elasticsearch+dra-staging-trigger.yml
@@ -0,0 +1,6 @@
+---
+jjbb-template: periodic-trigger-lgc.yml
+vars:
+ - periodic-job: elastic+elasticsearch+%BRANCH%+dra-staging
+ - lgc-job: elastic+elasticsearch+%BRANCH%+intake
+ - cron: "H H/12 * * *"
diff --git a/.ci/jobs.t/elastic+elasticsearch+dra-staging.yml b/.ci/jobs.t/elastic+elasticsearch+dra-staging.yml
index d558872abeb9..40a759e20ba2 100644
--- a/.ci/jobs.t/elastic+elasticsearch+dra-staging.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+dra-staging.yml
@@ -1,6 +1,6 @@
---
- job:
- name: elastic+elasticsearch+%BRANCH%+dra-snapshot
+ name: elastic+elasticsearch+%BRANCH%+dra-staging
workspace: /dev/shm/elastic+elasticsearch+%BRANCH%+dra-staging
display-name: "elastic / elasticsearch # %BRANCH% - DRA staging"
description: "Publishing Daily Releasable Artifacts (DRAs) of Elasticsearch %BRANCH% staging.\n"
@@ -13,6 +13,12 @@
RUNTIME_JAVA_HOME=$HOME/.java/$ES_RUNTIME_JAVA
- shell: |
#!/usr/local/bin/runbld --redirect-stderr
+
+ # Don't publish main branch to staging
+ if [ "%BRANCH%" == "main" ]; then
+ exit 0
+ fi
+
WORKFLOW="staging"
RM_BRANCH="%BRANCH%" && [[ "%BRANCH%" == "main" ]] && RM_BRANCH=master
ES_VERSION=$(cat build-tools-internal/version.properties \
diff --git a/.ci/jobs.t/elastic+elasticsearch+intake.yml b/.ci/jobs.t/elastic+elasticsearch+intake.yml
index f4aa32ec7e75..138318897b52 100644
--- a/.ci/jobs.t/elastic+elasticsearch+intake.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+intake.yml
@@ -54,6 +54,13 @@
kill-phase-on: NEVER
current-parameters: true
git-revision: true
+ - multijob:
+ name: Publish snapshot artifacts
+ projects:
+ - name: elastic+elasticsearch+%BRANCH%+dra-snapshot
+ kill-phase-on: NEVER
+ current-parameters: true
+ git-revision: true
- multijob:
name: Update last good commit
projects:
diff --git a/.ci/jobs.t/elastic+elasticsearch+multijob+platform-support-arm.yml b/.ci/jobs.t/elastic+elasticsearch+multijob+platform-support-arm.yml
index a5e590bc4a76..773db8ff2f92 100644
--- a/.ci/jobs.t/elastic+elasticsearch+multijob+platform-support-arm.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+multijob+platform-support-arm.yml
@@ -3,8 +3,7 @@
name: elastic+elasticsearch+%BRANCH%+multijob+platform-support-arm
display-name: "elastic / elasticsearch # %BRANCH% - arm compatibility"
description: "Elasticsearch %BRANCH% ARM (aarch64) compatibility testing.\n"
- # Don't use ramdisk for now as we are exhausting memory and causing oomkiller to trigger
- # child-workspace: "/dev/shm/elastic+elasticsearch+%BRANCH%+multijob+platform-support-arm"
+ child-workspace: "/dev/shm/elastic+elasticsearch+%BRANCH%+multijob+platform-support-arm"
project-type: matrix
node: master
scm:
@@ -17,6 +16,15 @@
values:
- "almalinux-8-aarch64&&immutable"
- "ubuntu-1804-aarch64&&immutable"
+ - axis:
+ type: user-defined
+ name: GRADLE_TASK
+ values:
+ - 'checkPart1'
+ - 'checkPart2'
+ - 'checkPart3'
+ - 'bwcTestSnapshots'
+ - 'checkRestCompat'
builders:
- inject:
properties-file: '.ci/java-versions-aarch64.properties'
@@ -28,4 +36,4 @@
JAVA16_HOME=$HOME/.java/jdk16
- shell: |
#!/usr/local/bin/runbld --redirect-stderr
- $WORKSPACE/.ci/scripts/run-gradle.sh -Dbwc.checkout.align=true check
+ $WORKSPACE/.ci/scripts/run-gradle.sh -Dbwc.checkout.align=true $GRADLE_TASK
diff --git a/.ci/jobs.t/elastic+elasticsearch+multijob+platform-support-unix.yml b/.ci/jobs.t/elastic+elasticsearch+multijob+platform-support-unix.yml
index 6aec8b04a2f3..23f647f5af88 100644
--- a/.ci/jobs.t/elastic+elasticsearch+multijob+platform-support-unix.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+multijob+platform-support-unix.yml
@@ -5,6 +5,7 @@
description: "Elasticsearch %BRANCH% unix compatibility testing.\n"
project-type: matrix
node: master
+ child-workspace: "/var/lib/jenkins/workspace/elastic+elasticsearch+%BRANCH%+multijob+platform-support-unix"
scm:
- git:
wipe-workspace: false
diff --git a/.ci/jobs.t/elastic+elasticsearch+periodic+dra-snapshots-trigger.yml b/.ci/jobs.t/elastic+elasticsearch+periodic+dra-snapshots-trigger.yml
deleted file mode 100644
index 7f1c639770ae..000000000000
--- a/.ci/jobs.t/elastic+elasticsearch+periodic+dra-snapshots-trigger.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-jjbb-template: periodic-trigger-lgc.yml
-vars:
- - periodic-job: elastic+elasticsearch+%BRANCH%+periodic+dra-snapshot
- - lgc-job: elastic+elasticsearch+%BRANCH%+intake
- - cron: "H H/12 * * *"
diff --git a/.ci/jobs.t/elastic+elasticsearch+periodic+dra-snapshots.yml b/.ci/jobs.t/elastic+elasticsearch+periodic+dra-snapshots.yml
deleted file mode 100644
index e0c7e7d122d3..000000000000
--- a/.ci/jobs.t/elastic+elasticsearch+periodic+dra-snapshots.yml
+++ /dev/null
@@ -1,67 +0,0 @@
----
-- job:
- name: elastic+elasticsearch+%BRANCH%+periodic+dra-snapshot
- workspace: /dev/shm/elastic+elasticsearch+%BRANCH%+periodic+dra-snapshot
- display-name: "elastic / elasticsearch # %BRANCH% - DRA snapshot"
- description: "Publishing Daily Releasable Artifacts (DRAs) of Elasticsearch %BRANCH% snapshots.\n"
- node: "ubuntu-20.04"
- builders:
- - inject:
- properties-file: '.ci/java-versions.properties'
- properties-content: |
- JAVA_HOME=$HOME/.java/$ES_BUILD_JAVA
- RUNTIME_JAVA_HOME=$HOME/.java/$ES_RUNTIME_JAVA
- - shell: |
- #!/usr/local/bin/runbld --redirect-stderr
- WORKFLOW="snapshot"
- RM_BRANCH="%BRANCH%" && [[ "%BRANCH%" == "main" ]] && RM_BRANCH=master
- ES_VERSION=$(cat build-tools-internal/version.properties \
- | grep elasticsearch \
- | sed "s/elasticsearch *= *//g")
- VERSION_SUFFIX="" && [[ "$WORKFLOW" == "snapshot" ]] && VERSION_SUFFIX="-SNAPSHOT"
- BEATS_BUILD_ID="$(./.ci/scripts/resolve-dra-manifest.sh beats $RM_BRANCH $ES_VERSION $WORKFLOW)"
- ML_CPP_BUILD_ID="$(./.ci/scripts/resolve-dra-manifest.sh ml-cpp $RM_BRANCH $ES_VERSION $WORKFLOW)"
- set -euo pipefail
- set +x
- VAULT_TOKEN=$(vault write -field=token auth/approle/login role_id=$VAULT_ROLE_ID secret_id=$VAULT_SECRET_ID)
- export VAULT_TOKEN
- $WORKSPACE/.ci/scripts/run-gradle.sh -Ddra.artifacts=true \
- -Ddra.artifacts.dependency.beats=${BEATS_BUILD_ID} \
- -Ddra.artifacts.dependency.ml-cpp=${ML_CPP_BUILD_ID} \
- -Ddra.workflow=$WORKFLOW \
- -Dcsv=$WORKSPACE/build/distributions/dependencies-${ES_VERSION}${VERSION_SUFFIX}.csv \
- buildReleaseArtifacts \
- exportCompressedDockerImages \
- :distribution:generateDependenciesReport
-
- unset VAULT_TOKEN
- set -x
- $WORKSPACE/x-pack/plugin/sql/connectors/tableau/package.sh asm qualifier="$VERSION_SUFFIX"
-
- # we regenerate this file as part of the release manager invocation
- rm $WORKSPACE/build/distributions/elasticsearch-jdbc-${ES_VERSION}${VERSION_SUFFIX}.taco.sha512
-
- # Allow other users access to read the artifacts so they are readable in the
- # container
- find $WORKSPACE -type f -path "*/build/distributions/*" -exec chmod a+r {} \;
-
- # Allow other users write access to create checksum files
- find $WORKSPACE -type d -path "*/build/distributions" -exec chmod a+w {} \;
-
- # Artifacts should be generated
- docker run --rm \
- --name release-manager \
- -e VAULT_ADDR \
- -e VAULT_ROLE_ID \
- -e VAULT_SECRET_ID \
- --mount type=bind,readonly=false,src="$PWD",target=/artifacts \
- docker.elastic.co/infra/release-manager:latest \
- cli collect \
- --project elasticsearch \
- --branch "$RM_BRANCH" \
- --commit "$GIT_COMMIT" \
- --workflow "$WORKFLOW" \
- --version "$ES_VERSION" \
- --artifact-set main \
- --dependency beats:https://artifacts-${WORKFLOW}.elastic.co/beats/${BEATS_BUILD_ID}/manifest-${ES_VERSION}${VERSION_SUFFIX}.json \
- --dependency ml-cpp:https://artifacts-${WORKFLOW}.elastic.co/ml-cpp/${ML_CPP_BUILD_ID}/manifest-${ES_VERSION}${VERSION_SUFFIX}.json
diff --git a/.ci/jobs.t/elastic+elasticsearch+periodic+ear.yml b/.ci/jobs.t/elastic+elasticsearch+periodic+ear.yml
index 47a8d4f48cc5..de4886c9f8eb 100644
--- a/.ci/jobs.t/elastic+elasticsearch+periodic+ear.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+periodic+ear.yml
@@ -16,7 +16,7 @@
#!/bin/bash
# Configure a dm-crypt volume backed by a file
set -e
- dd if=/dev/zero of=dm-crypt.img bs=1 count=0 seek=60GB
+ dd if=/dev/zero of=dm-crypt.img bs=1 count=0 seek=80GB
dd if=/dev/urandom of=key.secret bs=2k count=1
LOOP=$(losetup -f)
sudo losetup $LOOP dm-crypt.img
diff --git a/.ci/jobs.t/elastic+elasticsearch+periodic+java-preview-features-trigger.yml b/.ci/jobs.t/elastic+elasticsearch+periodic+java-preview-features-trigger.yml
deleted file mode 100644
index 9b1893362c05..000000000000
--- a/.ci/jobs.t/elastic+elasticsearch+periodic+java-preview-features-trigger.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-jjbb-template: periodic-trigger-lgc.yml
-vars:
- - periodic-job: elastic+elasticsearch+%BRANCH%+periodic+java-preview-features
- - lgc-job: elastic+elasticsearch+%BRANCH%+intake
- - cron: "H H/12 * * *"
diff --git a/.ci/jobs.t/elastic+elasticsearch+periodic+java-preview-features.yml b/.ci/jobs.t/elastic+elasticsearch+periodic+java-preview-features.yml
deleted file mode 100644
index 592bb2c3941c..000000000000
--- a/.ci/jobs.t/elastic+elasticsearch+periodic+java-preview-features.yml
+++ /dev/null
@@ -1,38 +0,0 @@
----
-- job:
- name: "elastic+elasticsearch+%BRANCH%+periodic+java-preview-features"
- display-name: "elastic / elasticsearch # %BRANCH% - java preview features"
- description: "Testing of the Elasticsearch %BRANCH% branch with java preview features enabled.\n"
- project-type: matrix
- child-workspace: /dev/shm/elastic+elasticsearch+%BRANCH%+periodic+java-preview-features
- node: master
- scm:
- - git:
- wipe-workspace: false
- axes:
- - axis:
- type: slave
- name: nodes
- values:
- - "general-purpose"
- # We shred out these jobs to avoid running out of memory given since we use a ramdisk workspace
- - axis:
- type: user-defined
- name: GRADLE_TASK
- values:
- - 'checkPart1'
- - 'checkPart2'
- - 'checkPart3'
- - 'bwcTestSnapshots'
- - 'checkRestCompat'
- builders:
- - inject:
- properties-file: '.ci/java-versions.properties'
- properties-content: |
- JAVA_HOME=$HOME/.java/$ES_BUILD_JAVA
- RUNTIME_JAVA_HOME=$HOME/.java/openjdk19
- JAVA11_HOME=$HOME/.java/java11
- JAVA16_HOME=$HOME/.java/openjdk16
- - shell: |
- #!/usr/local/bin/runbld --redirect-stderr
- $WORKSPACE/.ci/scripts/run-gradle.sh -Dtests.jvm.argline="--enable-preview" -Dbwc.checkout.align=true $GRADLE_TASK
diff --git a/.ci/jobs.t/elastic+elasticsearch+periodic+release-tests.yml b/.ci/jobs.t/elastic+elasticsearch+periodic+release-tests.yml
index 0ce470d37b34..7447deb49dcf 100644
--- a/.ci/jobs.t/elastic+elasticsearch+periodic+release-tests.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+periodic+release-tests.yml
@@ -23,7 +23,9 @@
mkdir -p ${BEATS_DIR}
curl --fail -o "${BEATS_DIR}/metricbeat-${ES_VERSION}-linux-x86_64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/metricbeat/metricbeat-${ES_VERSION}-SNAPSHOT-linux-x86_64.tar.gz
- curl --fail -o "${BEATS_DIR}/filebeat-${ES_VERSION}-linux-x86_64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/filebeat/filebeat-${ES_VERSION}-SNAPSHOT-linux-x86_64.tar.gz
+ curl --fail -o "${BEATS_DIR}/metricbeat-${ES_VERSION}-linux-arm64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/metricbeat/metricbeat-${ES_VERSION}-SNAPSHOT-linux-arm64.tar.gz
+ curl --fail -o "${BEATS_DIR}/filebeat-${ES_VERSION}-linux-x86_64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/metricbeat/metricbeat-${ES_VERSION}-SNAPSHOT-linux-x86_64.tar.gz
+ curl --fail -o "${BEATS_DIR}/filebeat-${ES_VERSION}-linux-arm64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/filebeat/filebeat-${ES_VERSION}-SNAPSHOT-linux-arm64.tar.gz
# Fetch ML artifacts
export ML_IVY_REPO=$(mktemp -d)
diff --git a/.ci/jobs.t/elastic+elasticsearch+pull-request+bwc-snapshots-windows.yml b/.ci/jobs.t/elastic+elasticsearch+pull-request+bwc-snapshots-windows.yml
new file mode 100644
index 000000000000..9cd24f1391e0
--- /dev/null
+++ b/.ci/jobs.t/elastic+elasticsearch+pull-request+bwc-snapshots-windows.yml
@@ -0,0 +1,55 @@
+---
+- job:
+ name: "elastic+elasticsearch+pull-request+bwc-snapshots-windows"
+ display-name: "elastic / elasticsearch - pull request bwc windows"
+ description: "Testing of Elasticsearch pull requests - bwc windows"
+ project-type: matrix
+ node: master
+ child-workspace: "C:\\Users\\jenkins\\workspace\\bwc-snapshots\\${BUILD_NUMBER}"
+ scm:
+ - git:
+ refspec: "+refs/pull/${ghprbPullId}/*:refs/remotes/origin/pr/${ghprbPullId}/*"
+ branches:
+ - "${ghprbActualCommit}"
+ triggers:
+ - github-pull-request:
+ org-list:
+ - elastic
+ allow-whitelist-orgs-as-admins: true
+ trigger-phrase: '.*run\W+elasticsearch-ci/bwc-snapshots-windows.*'
+ github-hooks: true
+ status-context: elasticsearch-ci/bwc-snapshots-windows
+ cancel-builds-on-update: true
+ black-list-target-branches:
+ - 6.8
+ excluded-regions:
+ - ^docs/.*
+ white-list-labels:
+ - 'test-windows'
+ black-list-labels:
+ - '>test-mute'
+ axes:
+ - axis:
+ type: slave
+ name: nodes
+ values:
+ - "windows-immutable"
+ - axis:
+ type: yaml
+ filename: ".ci/snapshotBwcVersions"
+ name: "BWC_VERSION"
+ builders:
+ - inject:
+ properties-file: '.ci/java-versions.properties'
+ properties-content: |
+ JAVA_HOME=$USERPROFILE\\.java\\$ES_BUILD_JAVA
+ RUNTIME_JAVA_HOME=$USERPROFILE\\.java\\$ES_RUNTIME_JAVA
+ JAVA11_HOME=$USERPROFILE\\.java\\java11
+ JAVA16_HOME=$USERPROFILE\\.java\\openjdk16
+ - batch: |
+ del /f /s /q %USERPROFILE%\.gradle\init.d\*.*
+ mkdir %USERPROFILE%\.gradle\init.d
+ copy .ci\init.gradle %USERPROFILE%\.gradle\init.d\
+ (
+ echo call %GRADLEW_BAT% --max-workers=4 -Dbwc.checkout.align=true v%BWC_VERSION%#bwcTest ^|^| exit /b 1
+ ) | java -jar "C:\Program Files\infra\bin\runbld" --redirect-stderr -
diff --git a/.ci/jobs.t/elastic+elasticsearch+pull-request+part-1-windows.yml b/.ci/jobs.t/elastic+elasticsearch+pull-request+part-1-windows.yml
index dbb54e37fb23..f4ded4d1eeca 100644
--- a/.ci/jobs.t/elastic+elasticsearch+pull-request+part-1-windows.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+pull-request+part-1-windows.yml
@@ -33,6 +33,7 @@
properties-content: |
JAVA_HOME=$USERPROFILE\\.java\\$ES_BUILD_JAVA
RUNTIME_JAVA_HOME=$USERPROFILE\\.java\\$ES_RUNTIME_JAVA
+ JAVA11_HOME=$USERPROFILE\\.java\\java11
JAVA16_HOME=$USERPROFILE\\.java\\openjdk16
GRADLE_TASK=checkPart1
- batch: |
diff --git a/.ci/jobs.t/elastic+elasticsearch+pull-request+part-2-windows.yml b/.ci/jobs.t/elastic+elasticsearch+pull-request+part-2-windows.yml
index ab367188cb8e..53295df00627 100644
--- a/.ci/jobs.t/elastic+elasticsearch+pull-request+part-2-windows.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+pull-request+part-2-windows.yml
@@ -33,6 +33,7 @@
properties-content: |
JAVA_HOME=$USERPROFILE\\.java\\$ES_BUILD_JAVA
RUNTIME_JAVA_HOME=$USERPROFILE\\.java\\$ES_RUNTIME_JAVA
+ JAVA11_HOME=$USERPROFILE\\.java\\java11
JAVA16_HOME=$USERPROFILE\\.java\\openjdk16
GRADLE_TASK=checkPart2
- batch: |
diff --git a/.ci/jobs.t/elastic+elasticsearch+pull-request+part-3-windows.yml b/.ci/jobs.t/elastic+elasticsearch+pull-request+part-3-windows.yml
index a287c8c0bd9c..80e4bf7f47c0 100644
--- a/.ci/jobs.t/elastic+elasticsearch+pull-request+part-3-windows.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+pull-request+part-3-windows.yml
@@ -34,6 +34,7 @@
properties-content: |
JAVA_HOME=$USERPROFILE\\.java\\$ES_BUILD_JAVA
RUNTIME_JAVA_HOME=$USERPROFILE\\.java\\$ES_RUNTIME_JAVA
+ JAVA11_HOME=$USERPROFILE\\.java\\java11
JAVA16_HOME=$USERPROFILE\\.java\\openjdk16
GRADLE_TASK=checkPart3
- batch: |
diff --git a/.ci/jobs.t/elastic+elasticsearch+pull-request+release-tests.yml b/.ci/jobs.t/elastic+elasticsearch+pull-request+release-tests.yml
index 54242eee118b..125b0a00b6c8 100644
--- a/.ci/jobs.t/elastic+elasticsearch+pull-request+release-tests.yml
+++ b/.ci/jobs.t/elastic+elasticsearch+pull-request+release-tests.yml
@@ -45,13 +45,16 @@
mkdir -p ${BEATS_DIR}
curl --fail -o "${BEATS_DIR}/metricbeat-${ES_VERSION}-linux-x86_64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/metricbeat/metricbeat-${ES_VERSION}-SNAPSHOT-linux-x86_64.tar.gz
- curl --fail -o "${BEATS_DIR}/filebeat-${ES_VERSION}-linux-x86_64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/filebeat/filebeat-${ES_VERSION}-SNAPSHOT-linux-x86_64.tar.gz
+ curl --fail -o "${BEATS_DIR}/metricbeat-${ES_VERSION}-linux-arm64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/metricbeat/metricbeat-${ES_VERSION}-SNAPSHOT-linux-arm64.tar.gz
+ curl --fail -o "${BEATS_DIR}/filebeat-${ES_VERSION}-linux-x86_64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/metricbeat/metricbeat-${ES_VERSION}-SNAPSHOT-linux-x86_64.tar.gz
+ curl --fail -o "${BEATS_DIR}/filebeat-${ES_VERSION}-linux-arm64.tar.gz" https://artifacts-snapshot.elastic.co/beats/${ES_VERSION}-SNAPSHOT/downloads/beats/filebeat/filebeat-${ES_VERSION}-SNAPSHOT-linux-arm64.tar.gz
# Fetch ML artifacts
export ML_IVY_REPO=$(mktemp -d)
mkdir -p ${ML_IVY_REPO}/maven/org/elasticsearch/ml/ml-cpp/${ES_VERSION}
curl --fail -o "${ML_IVY_REPO}/maven/org/elasticsearch/ml/ml-cpp/${ES_VERSION}/ml-cpp-${ES_VERSION}-deps.zip" https://artifacts-snapshot.elastic.co/ml-cpp/${ES_VERSION}-SNAPSHOT/downloads/ml-cpp/ml-cpp-${ES_VERSION}-SNAPSHOT-deps.zip
curl --fail -o "${ML_IVY_REPO}/maven/org/elasticsearch/ml/ml-cpp/${ES_VERSION}/ml-cpp-${ES_VERSION}-nodeps.zip" https://artifacts-snapshot.elastic.co/ml-cpp/${ES_VERSION}-SNAPSHOT/downloads/ml-cpp/ml-cpp-${ES_VERSION}-SNAPSHOT-nodeps.zip
+ curl --fail -o "${ML_IVY_REPO}/maven/org/elasticsearch/ml/ml-cpp/${ES_VERSION}/ml-cpp-${ES_VERSION}.zip" https://artifacts-snapshot.elastic.co/ml-cpp/${ES_VERSION}-SNAPSHOT/downloads/ml-cpp/ml-cpp-${ES_VERSION}-SNAPSHOT.zip
$WORKSPACE/.ci/scripts/run-gradle.sh -Dbwc.checkout.align=true -Dbuild.snapshot=false -Dbuild.ml_cpp.repo=file://${ML_IVY_REPO} \
-Dtests.jvm.argline=-Dbuild.snapshot=false -Dlicense.key=${WORKSPACE}/x-pack/license-tools/src/test/resources/public.key -Dbuild.id=deadbeef build
diff --git a/.ci/matrix-runtime-javas.yml b/.ci/matrix-runtime-javas.yml
index a6b2d4a15d84..07582c4892d5 100644
--- a/.ci/matrix-runtime-javas.yml
+++ b/.ci/matrix-runtime-javas.yml
@@ -10,3 +10,4 @@ ES_RUNTIME_JAVA:
- openjdk17
- openjdk18
- openjdk19
+ - openjdk20
diff --git a/.ci/packer_cache.sh b/.ci/packer_cache.sh
index 5a7b3c792d7f..43d1c5a82b90 100755
--- a/.ci/packer_cache.sh
+++ b/.ci/packer_cache.sh
@@ -43,4 +43,4 @@ fi
## Gradle is able to resolve dependencies resolved with earlier gradle versions
## therefore we run main _AFTER_ we run 6.8 which uses an earlier gradle version
export JAVA_HOME="${HOME}"/.java/${ES_BUILD_JAVA}
-./gradlew --parallel clean -s resolveAllDependencies -Dorg.gradle.warning.mode=none
+./gradlew --parallel clean -s resolveAllDependencies -Dorg.gradle.warning.mode=none -Drecurse.bwc=true
diff --git a/.ci/snapshotBwcVersions b/.ci/snapshotBwcVersions
index dd700ed35e2c..c89f884223c0 100644
--- a/.ci/snapshotBwcVersions
+++ b/.ci/snapshotBwcVersions
@@ -1,5 +1,4 @@
BWC_VERSION:
- - "7.17.8"
- - "8.5.2"
- - "8.6.0"
+ - "7.17.10"
+ - "8.6.2"
- "8.7.0"
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 7a95e4eaef1b..6a3d07df917e 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -16,6 +16,6 @@ x-pack/plugin/core/src/main/resources/monitoring-logstash.json @elastic/infra-mo
x-pack/plugin/core/src/main/resources/monitoring-mb-ilm-policy.json @elastic/infra-monitoring-ui
x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringTemplateRegistry.java @elastic/infra-monitoring-ui
-# Elastic Agent
-x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet @elastic/elastic-agent-control-plane
-x-pack/plugin/core/src/main/resources/fleet-* @elastic/elastic-agent-control-plane
+# Fleet
+x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet @elastic/fleet
+x-pack/plugin/core/src/main/resources/fleet-* @elastic/fleet
diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml
index 0bae5de1d0f8..b434572cf6f3 100644
--- a/.github/ISSUE_TEMPLATE/bug.yml
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -4,22 +4,27 @@ labels: [">bug", "needs:triage"]
body:
- type: markdown
attributes:
- value: |
+ value: >
Github is reserved for bug reports and feature requests; it is
not the place for general questions. If you have a question or
an unconfirmed bug, please visit the [forums](https://discuss.elastic.co/c/elasticsearch).
- Please also check your OS is [supported](https://www.elastic.co/support/matrix#show_os).
- If it is not, the issue is likely to be closed.
+ Please also check your OS is [supported](https://www.elastic.co/support/matrix#show_os),
+ and that the version of Elasticsearch has not passed [end-of-life](https://www.elastic.co/support/eol).
+ If you are using an unsupported OS or an unsupported version then the issue is likely to be closed.
+
For security vulnerabilities please only send reports to security@elastic.co.
See https://www.elastic.co/community/security for more information.
+
Please fill in the following details to help us reproduce the bug:
- type: input
id: es_version
attributes:
label: Elasticsearch Version
- description: The version of Elasticsearch you are running, found with `bin/elasticsearch --version`
+ description: >-
+ The version of Elasticsearch you are running, found with `bin/elasticsearch --version`.
+ Ensure this version has not [passed end-of-life](https://www.elastic.co/support/eol).
validations:
required: true
- type: input
diff --git a/BUILDING.md b/BUILDING.md
index fa2258608144..692a7a559de2 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -78,7 +78,7 @@ For updated or newly added dependencies you need to add an entry to this verific
```
-In case of updating a dependency, ensure to remove the unused entry of the outdated dependency manually from the verifcation.xml file.
+In case of updating a dependency, ensure to remove the unused entry of the outdated dependency manually from the `verification-metadata.xml` file.
You can also automate the generation of this entry by running your build using the `--write-verification-metadata` commandline option:
```
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 61c31c7665d7..00af53743fd3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -870,6 +870,17 @@ benefits of this kind of change are very small, and in our experience it is not
worth investing the substantial effort needed to review them. This especially
includes changes suggested by tools.
+We normally immediately reject PRs which target platforms or system
+configurations that are not in the [official support
+matrix](https://www.elastic.co/support/matrix). We choose to support particular
+platforms with care because we must work to ensure that every Elasticsearch
+release works completely on every platform, and we must spend time
+investigating test failures and performance regressions there too. We cannot
+determine whether PRs which target unsupported platforms or configurations meet
+our quality standards, nor can we guarantee that the change they introduce will
+continue to work in future releases. We do not want Elasticsearch to suddenly
+stop working on a particular platform after an upgrade.
+
We sometimes reject contributions due to the low quality of the submission
since low-quality submissions tend to take unreasonable effort to review
properly. Quality is rather subjective so it is hard to describe exactly how to
diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/AllocationBenchmark.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/AllocationBenchmark.java
index 2a8bf1b91ce7..c69c357b1378 100644
--- a/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/AllocationBenchmark.java
+++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/AllocationBenchmark.java
@@ -131,7 +131,7 @@ public void setUp() throws Exception {
);
}
Metadata metadata = mb.build();
- RoutingTable.Builder rb = RoutingTable.builder();
+ RoutingTable.Builder rb = RoutingTable.builder(TestShardRoutingRoleStrategies.DEFAULT_ROLE_ONLY);
for (int i = 1; i <= numIndices; i++) {
rb.addAsNew(metadata.index("test_" + i));
}
diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/Allocators.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/Allocators.java
index 09080029ba25..f933957c7486 100644
--- a/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/Allocators.java
+++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/Allocators.java
@@ -81,7 +81,8 @@ public static AllocationService createAllocationService(Settings settings, Clust
NoopGatewayAllocator.INSTANCE,
new BalancedShardsAllocator(settings),
EmptyClusterInfoService.INSTANCE,
- EmptySnapshotsInfoService.INSTANCE
+ EmptySnapshotsInfoService.INSTANCE,
+ TestShardRoutingRoleStrategies.DEFAULT_ROLE_ONLY
);
}
diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/ShardsAvailabilityHealthIndicatorBenchmark.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/ShardsAvailabilityHealthIndicatorBenchmark.java
index 20e8106d93c0..deceab114f4f 100644
--- a/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/ShardsAvailabilityHealthIndicatorBenchmark.java
+++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/ShardsAvailabilityHealthIndicatorBenchmark.java
@@ -29,6 +29,7 @@
import org.elasticsearch.health.HealthIndicatorResult;
import org.elasticsearch.health.node.HealthInfo;
import org.elasticsearch.index.shard.ShardId;
+import org.elasticsearch.indices.SystemIndices;
import org.elasticsearch.tasks.TaskManager;
import org.elasticsearch.threadpool.ThreadPool;
import org.openjdk.jmh.annotations.Benchmark;
@@ -45,6 +46,7 @@
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -127,7 +129,7 @@ public void setUp() throws Exception {
.numberOfReplicas(numReplicas)
.build();
- final IndexRoutingTable.Builder indexRountingTableBuilder = new IndexRoutingTable.Builder(indexMetadata.getIndex());
+ final IndexRoutingTable.Builder indexRountingTableBuilder = IndexRoutingTable.builder(indexMetadata.getIndex());
for (int shardIdNumber = 0; shardIdNumber < numShards; shardIdNumber++) {
ShardId shardId = new ShardId(indexMetadata.getIndex(), shardIdNumber);
final IndexShardRoutingTable.Builder shardBuilder = new IndexShardRoutingTable.Builder(shardId);
@@ -135,7 +137,8 @@ public void setUp() throws Exception {
shardId,
true,
RecoverySource.ExistingStoreRecoverySource.INSTANCE,
- decidersNoUnassignedInfo
+ decidersNoUnassignedInfo,
+ ShardRouting.Role.DEFAULT
);
shardBuilder.addShard(shardRouting);
if (shardIdNumber < numReplicas) {
@@ -144,7 +147,8 @@ public void setUp() throws Exception {
shardId,
false,
RecoverySource.EmptyStoreRecoverySource.INSTANCE,
- decidersNoUnassignedInfo
+ decidersNoUnassignedInfo,
+ ShardRouting.Role.DEFAULT
)
);
}
@@ -171,7 +175,7 @@ public void setUp() throws Exception {
new TaskManager(Settings.EMPTY, threadPool, Collections.emptySet())
);
clusterService.getClusterApplierService().setInitialState(initialClusterState);
- indicatorService = new ShardsAvailabilityHealthIndicatorService(clusterService, allocationService);
+ indicatorService = new ShardsAvailabilityHealthIndicatorService(clusterService, allocationService, new SystemIndices(List.of()));
}
private int toInt(String v) {
diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/TestShardRoutingRoleStrategies.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/TestShardRoutingRoleStrategies.java
new file mode 100644
index 000000000000..2c6207285595
--- /dev/null
+++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/TestShardRoutingRoleStrategies.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.benchmark.routing.allocation;
+
+import org.elasticsearch.cluster.routing.ShardRouting;
+import org.elasticsearch.cluster.routing.ShardRoutingRoleStrategy;
+
+public class TestShardRoutingRoleStrategies {
+
+ /**
+ * A strategy which only returns the default role in all situations. This is deliberately not available to production code to avoid any
+ * possibility of using it instead of the strategy provided by the plugin (if so configured).
+ */
+ public static final ShardRoutingRoleStrategy DEFAULT_ROLE_ONLY = new ShardRoutingRoleStrategy() {
+ @Override
+ public ShardRouting.Role newReplicaRole() {
+ return ShardRouting.Role.DEFAULT;
+ }
+
+ @Override
+ public ShardRouting.Role newEmptyRole(int copyIndex) {
+ return ShardRouting.Role.DEFAULT;
+ }
+ };
+
+ private TestShardRoutingRoleStrategies() {
+ // no instances
+ }
+}
diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/script/ScriptScoreBenchmark.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/script/ScriptScoreBenchmark.java
index 47f1b4f41353..7e40acff82c8 100644
--- a/benchmarks/src/main/java/org/elasticsearch/benchmark/script/ScriptScoreBenchmark.java
+++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/script/ScriptScoreBenchmark.java
@@ -40,7 +40,7 @@
import org.elasticsearch.script.ScoreScript;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.search.lookup.SearchLookup;
-import org.elasticsearch.search.lookup.SourceLookup;
+import org.elasticsearch.search.lookup.SourceProvider;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
@@ -90,7 +90,7 @@ public class ScriptScoreBenchmark {
private final SearchLookup lookup = new SearchLookup(
fieldTypes::get,
(mft, lookup, fdo) -> mft.fielddataBuilder(FieldDataContext.noRuntimeFields("benchmark")).build(fieldDataCache, breakerService),
- new SourceLookup.ReaderSourceProvider()
+ SourceProvider.fromStoredFields()
);
@Param({ "expression", "metal", "painless_cast", "painless_def" })
diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/vector/DistanceFunctionBenchmark.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/vector/DistanceFunctionBenchmark.java
new file mode 100644
index 000000000000..1ee1d6217598
--- /dev/null
+++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/vector/DistanceFunctionBenchmark.java
@@ -0,0 +1,467 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.benchmark.vector;
+
+import org.apache.lucene.util.BytesRef;
+import org.elasticsearch.Version;
+import org.elasticsearch.script.field.vectors.BinaryDenseVector;
+import org.elasticsearch.script.field.vectors.ByteBinaryDenseVector;
+import org.elasticsearch.script.field.vectors.ByteKnnDenseVector;
+import org.elasticsearch.script.field.vectors.KnnDenseVector;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OperationsPerInvocation;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * Various benchmarks for the distance functions
+ * used by indexed and non-indexed vectors.
+ * Parameters include element, dims, function, and type.
+ * For individual local tests it may be useful to increase
+ * fork, measurement, and operations per invocation. (Note
+ * to also update the benchmark loop if operations per invocation
+ * is increased.)
+ */
+@Fork(1)
+@Warmup(iterations = 1)
+@Measurement(iterations = 2)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+@OperationsPerInvocation(25000)
+@State(Scope.Benchmark)
+public class DistanceFunctionBenchmark {
+
+ @Param({ "float", "byte" })
+ private String element;
+
+ @Param({ "96" })
+ private int dims;
+
+ @Param({ "dot", "cosine", "l1", "l2" })
+ private String function;
+
+ @Param({ "knn", "binary" })
+ private String type;
+
+ private abstract static class BenchmarkFunction {
+
+ final int dims;
+
+ private BenchmarkFunction(int dims) {
+ this.dims = dims;
+ }
+
+ abstract void execute(Consumer
+ * First, we check that the new jar signature contains all the same classes
+ * as the old jar signature. If not, we return an error.
+ *
+ * Second, we iterate over the signature for each class. If a signature from the old
+ * jar is absent in the new jar, we add it to our list of errors.
+ *
+ * Note that it is fine for the new jar to have additional elements, as this
+ * is backwards compatible.
+ */
+ public static void compareSignatures(Map> oldSignature, Map> newSignature) {
+ Set deletedClasses = new HashSet<>(oldSignature.keySet());
+ deletedClasses.removeAll(newSignature.keySet());
+ if (deletedClasses.size() > 0) {
+ throw new IllegalStateException("Classes from a previous version not found: " + deletedClasses);
+ }
+
+ Map> deletedMembersMap = new HashMap<>();
+ for (Map.Entry> entry : oldSignature.entrySet()) {
+ Set deletedMembers = new HashSet<>(entry.getValue());
+ deletedMembers.removeAll(newSignature.get(entry.getKey()));
+ if (deletedMembers.size() > 0) {
+ deletedMembersMap.put(entry.getKey(), Set.copyOf(deletedMembers));
+ }
+ }
+ if (deletedMembersMap.size() > 0) {
+ throw new IllegalStateException(
+ "Classes from a previous version have been modified, violating backwards compatibility: " + deletedMembersMap
+ );
+ }
+ }
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ResolveAllDependencies.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ResolveAllDependencies.java
index d86ec9001d41..0afa675c9dfc 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ResolveAllDependencies.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ResolveAllDependencies.java
@@ -21,7 +21,7 @@
import javax.inject.Inject;
import static org.elasticsearch.gradle.DistributionDownloadPlugin.DISTRO_EXTRACTED_CONFIG_PREFIX;
-import static org.elasticsearch.gradle.internal.rest.compat.YamlRestCompatTestPlugin.BWC_MINOR_CONFIG_NAME;
+import static org.elasticsearch.gradle.internal.test.rest.compat.compat.LegacyYamlRestCompatTestPlugin.BWC_MINOR_CONFIG_NAME;
public class ResolveAllDependencies extends DefaultTask {
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/BuildParams.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/BuildParams.java
index 33a859747681..c3feb367c76e 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/BuildParams.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/info/BuildParams.java
@@ -18,6 +18,7 @@
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.List;
+import java.util.Random;
import java.util.function.Consumer;
import static java.util.Objects.requireNonNull;
@@ -110,10 +111,18 @@ public static String getTestSeed() {
return value(testSeed);
}
+ public static Random getRandom() {
+ return new Random(Long.parseUnsignedLong(testSeed.split(":")[0], 16));
+ }
+
public static Boolean isCi() {
return value(isCi);
}
+ public static Boolean isGraalVmRuntime() {
+ return value(runtimeJavaDetails.toLowerCase().contains("graalvm"));
+ }
+
public static Integer getDefaultParallel() {
return value(defaultParallel);
}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/TestingConventionsPrecommitPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/TestingConventionsPrecommitPlugin.java
index 95d0ad2be4cc..6adf422133db 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/TestingConventionsPrecommitPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/TestingConventionsPrecommitPlugin.java
@@ -11,7 +11,8 @@
import org.elasticsearch.gradle.internal.conventions.precommit.PrecommitPlugin;
import org.elasticsearch.gradle.internal.test.InternalClusterTestPlugin;
import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin;
-import org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin;
+import org.elasticsearch.gradle.internal.test.rest.LegacyJavaRestTestPlugin;
+import org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin;
import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectProvider;
import org.gradle.api.Project;
@@ -43,8 +44,8 @@ public TaskProvider extends Task> createTask(Project project) {
});
});
- project.getPlugins().withType(InternalYamlRestTestPlugin.class, yamlRestTestPlugin -> {
- NamedDomainObjectProvider sourceSet = sourceSets.named(InternalYamlRestTestPlugin.SOURCE_SET_NAME);
+ project.getPlugins().withType(LegacyYamlRestTestPlugin.class, yamlRestTestPlugin -> {
+ NamedDomainObjectProvider sourceSet = sourceSets.named(LegacyYamlRestTestPlugin.SOURCE_SET_NAME);
setupTaskForSourceSet(project, sourceSet, t -> {
t.getSuffixes().convention(List.of("IT"));
t.getBaseClasses().convention(List.of("org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase"));
@@ -68,8 +69,17 @@ public TaskProvider extends Task> createTask(Project project) {
});
});
+ project.getPlugins().withType(LegacyJavaRestTestPlugin.class, javaRestTestPlugin -> {
+ NamedDomainObjectProvider sourceSet = sourceSets.named(LegacyJavaRestTestPlugin.SOURCE_SET_NAME);
+ setupTaskForSourceSet(project, sourceSet, t -> {
+ t.getSuffixes().convention(List.of("IT"));
+ t.getBaseClasses()
+ .convention(List.of("org.elasticsearch.test.ESIntegTestCase", "org.elasticsearch.test.rest.ESRestTestCase"));
+ });
+ });
+
project.getPlugins().withType(InternalJavaRestTestPlugin.class, javaRestTestPlugin -> {
- NamedDomainObjectProvider sourceSet = sourceSets.named(InternalJavaRestTestPlugin.SOURCE_SET_NAME);
+ NamedDomainObjectProvider sourceSet = sourceSets.named(LegacyJavaRestTestPlugin.SOURCE_SET_NAME);
setupTaskForSourceSet(project, sourceSet, t -> {
t.getSuffixes().convention(List.of("IT"));
t.getBaseClasses()
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/rest/compat/YamlRestCompatTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/rest/compat/YamlRestCompatTestPlugin.java
deleted file mode 100644
index bb245bec61b9..000000000000
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/rest/compat/YamlRestCompatTestPlugin.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.gradle.internal.rest.compat;
-
-import org.elasticsearch.gradle.Version;
-import org.elasticsearch.gradle.VersionProperties;
-import org.elasticsearch.gradle.internal.ElasticsearchJavaBasePlugin;
-import org.elasticsearch.gradle.internal.test.RestIntegTestTask;
-import org.elasticsearch.gradle.internal.test.RestTestBasePlugin;
-import org.elasticsearch.gradle.internal.test.rest.CopyRestApiTask;
-import org.elasticsearch.gradle.internal.test.rest.CopyRestTestsTask;
-import org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin;
-import org.elasticsearch.gradle.internal.test.rest.RestResourcesExtension;
-import org.elasticsearch.gradle.internal.test.rest.RestResourcesPlugin;
-import org.elasticsearch.gradle.internal.test.rest.RestTestUtil;
-import org.elasticsearch.gradle.testclusters.TestClustersPlugin;
-import org.elasticsearch.gradle.util.GradleUtils;
-import org.gradle.api.Plugin;
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.artifacts.Configuration;
-import org.gradle.api.artifacts.Dependency;
-import org.gradle.api.file.Directory;
-import org.gradle.api.file.ProjectLayout;
-import org.gradle.api.file.RelativePath;
-import org.gradle.api.internal.file.FileOperations;
-import org.gradle.api.plugins.ExtraPropertiesExtension;
-import org.gradle.api.plugins.JavaBasePlugin;
-import org.gradle.api.provider.Provider;
-import org.gradle.api.tasks.SourceSet;
-import org.gradle.api.tasks.SourceSetContainer;
-import org.gradle.api.tasks.Sync;
-import org.gradle.api.tasks.TaskProvider;
-
-import java.io.File;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.setupYamlRestTestDependenciesDefaults;
-
-/**
- * Apply this plugin to run the YAML based REST tests from a prior major version against this version's cluster.
- */
-public class YamlRestCompatTestPlugin implements Plugin {
- public static final String BWC_MINOR_CONFIG_NAME = "bwcMinor";
- private static final String REST_COMPAT_CHECK_TASK_NAME = "checkRestCompat";
- private static final String COMPATIBILITY_APIS_CONFIGURATION = "restCompatSpecs";
- private static final String COMPATIBILITY_TESTS_CONFIGURATION = "restCompatTests";
- private static final Path RELATIVE_API_PATH = Path.of("rest-api-spec/api");
- private static final Path RELATIVE_TEST_PATH = Path.of("rest-api-spec/test");
- private static final Path RELATIVE_REST_API_RESOURCES = Path.of("rest-api-spec/src/main/resources");
- private static final Path RELATIVE_REST_CORE = Path.of("rest-api-spec");
- private static final Path RELATIVE_REST_XPACK = Path.of("x-pack/plugin");
- private static final Path RELATIVE_REST_PROJECT_RESOURCES = Path.of("src/yamlRestTest/resources");
- private static final int COMPATIBLE_VERSION = Version.fromString(VersionProperties.getVersions().get("elasticsearch")).getMajor() - 1;
- private static final String SOURCE_SET_NAME = "yamlRestTestV" + COMPATIBLE_VERSION + "Compat";
- private ProjectLayout projectLayout;
- private FileOperations fileOperations;
-
- @Inject
- public YamlRestCompatTestPlugin(ProjectLayout projectLayout, FileOperations fileOperations) {
- this.projectLayout = projectLayout;
- this.fileOperations = fileOperations;
- }
-
- @Override
- public void apply(Project project) {
-
- final Path compatRestResourcesDir = Path.of("restResources").resolve("v" + COMPATIBLE_VERSION);
- final Path compatSpecsDir = compatRestResourcesDir.resolve("yamlSpecs");
- final Path compatTestsDir = compatRestResourcesDir.resolve("yamlTests");
-
- project.getPluginManager().apply(ElasticsearchJavaBasePlugin.class);
- project.getPluginManager().apply(TestClustersPlugin.class);
- project.getPluginManager().apply(RestTestBasePlugin.class);
- project.getPluginManager().apply(RestResourcesPlugin.class);
- project.getPluginManager().apply(InternalYamlRestTestPlugin.class);
-
- RestResourcesExtension extension = project.getExtensions().getByType(RestResourcesExtension.class);
-
- // create source set
- SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
- SourceSet yamlCompatTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
- SourceSet yamlTestSourceSet = sourceSets.getByName(InternalYamlRestTestPlugin.SOURCE_SET_NAME);
- GradleUtils.extendSourceSet(project, InternalYamlRestTestPlugin.SOURCE_SET_NAME, SOURCE_SET_NAME);
-
- // copy compatible rest specs
- Configuration bwcMinorConfig = project.getConfigurations().create(BWC_MINOR_CONFIG_NAME);
- Dependency bwcMinor = project.getDependencies()
- .project(Map.of("path", ":distribution:bwc:maintenance", "configuration", "checkout"));
- project.getDependencies().add(bwcMinorConfig.getName(), bwcMinor);
-
- String projectPath = project.getPath();
- ExtraPropertiesExtension extraProperties = project.getExtensions().getExtraProperties();
- Provider copyCompatYamlSpecTask = project.getTasks()
- .register("copyRestCompatApiTask", CopyRestApiTask.class, task -> {
- task.dependsOn(bwcMinorConfig);
- task.setConfig(bwcMinorConfig);
- task.setAdditionalConfig(bwcMinorConfig);
- task.getInclude().set(extension.getRestApi().getInclude());
- task.getOutputResourceDir().set(projectLayout.getBuildDirectory().dir(compatSpecsDir.toString()));
- task.setSourceResourceDir(
- yamlCompatTestSourceSet.getResources()
- .getSrcDirs()
- .stream()
- .filter(f -> f.isDirectory() && f.getName().equals("resources"))
- .findFirst()
- .orElse(null)
- );
- task.setSkipHasRestTestCheck(true);
- task.setConfigToFileTree(
- config -> fileOperations.fileTree(
- config.getSingleFile().toPath().resolve(RELATIVE_REST_API_RESOURCES).resolve(RELATIVE_API_PATH)
- )
- );
- task.setAdditionalConfigToFileTree(
- config -> fileOperations.fileTree(
- getCompatProjectPath(projectPath, config.getSingleFile().toPath()).resolve(RELATIVE_REST_PROJECT_RESOURCES)
- .resolve(RELATIVE_API_PATH)
- )
- );
- task.onlyIf(t -> isEnabled(extraProperties));
- });
-
- // copy compatible rest tests
- Provider copyCompatYamlTestTask = project.getTasks()
- .register("copyRestCompatTestTask", CopyRestTestsTask.class, task -> {
- task.dependsOn(bwcMinorConfig);
- task.setCoreConfig(bwcMinorConfig);
- task.setXpackConfig(bwcMinorConfig);
- task.setAdditionalConfig(bwcMinorConfig);
- task.getIncludeCore().set(extension.getRestTests().getIncludeCore());
- task.getIncludeXpack().set(extension.getRestTests().getIncludeXpack());
- task.getOutputResourceDir().set(projectLayout.getBuildDirectory().dir(compatTestsDir.resolve("original").toString()));
- task.setCoreConfigToFileTree(
- config -> fileOperations.fileTree(
- config.getSingleFile()
- .toPath()
- .resolve(RELATIVE_REST_CORE)
- .resolve(RELATIVE_REST_PROJECT_RESOURCES)
- .resolve(RELATIVE_TEST_PATH)
- )
- );
- task.setXpackConfigToFileTree(
- config -> fileOperations.fileTree(
- config.getSingleFile()
- .toPath()
- .resolve(RELATIVE_REST_XPACK)
- .resolve(RELATIVE_REST_PROJECT_RESOURCES)
- .resolve(RELATIVE_TEST_PATH)
- )
- );
- task.setAdditionalConfigToFileTree(
- config -> fileOperations.fileTree(
- getCompatProjectPath(projectPath, config.getSingleFile().toPath()).resolve(RELATIVE_REST_PROJECT_RESOURCES)
- .resolve(RELATIVE_TEST_PATH)
- )
- );
- task.dependsOn(copyCompatYamlSpecTask);
- task.onlyIf(t -> isEnabled(extraProperties));
- });
-
- // copy both local source set apis and compat apis to a single location to be exported as an artifact
- TaskProvider bundleRestCompatApis = project.getTasks().register("bundleRestCompatApis", Sync.class, task -> {
- task.setDestinationDir(projectLayout.getBuildDirectory().dir("bundledCompatApis").get().getAsFile());
- task.setIncludeEmptyDirs(false);
- task.from(copyCompatYamlSpecTask.flatMap(t -> t.getOutputResourceDir().map(d -> d.dir(RELATIVE_API_PATH.toString()))));
- task.from(yamlCompatTestSourceSet.getProcessResourcesTaskName(), s -> {
- s.include(RELATIVE_API_PATH + "/*");
- s.eachFile(
- details -> details.setRelativePath(
- new RelativePath(true, Arrays.stream(details.getRelativePath().getSegments()).skip(2).toArray(String[]::new))
- )
- );
- });
- });
-
- // transform the copied tests task
- TaskProvider transformCompatTestTask = project.getTasks()
- .register("yamlRestTestV" + COMPATIBLE_VERSION + "CompatTransform", RestCompatTestTransformTask.class, task -> {
- task.getSourceDirectory().set(copyCompatYamlTestTask.flatMap(CopyRestTestsTask::getOutputResourceDir));
- task.getOutputDirectory()
- .set(project.getLayout().getBuildDirectory().dir(compatTestsDir.resolve("transformed").toString()));
- task.onlyIf(t -> isEnabled(extraProperties));
- });
-
- // Register compat rest resources with source set
- yamlCompatTestSourceSet.getOutput().dir(copyCompatYamlSpecTask.map(CopyRestApiTask::getOutputResourceDir));
- yamlCompatTestSourceSet.getOutput().dir(transformCompatTestTask.map(RestCompatTestTransformTask::getOutputDirectory));
-
- // Register artifact for transformed compatibility apis and tests
- Configuration compatRestSpecs = project.getConfigurations().create(COMPATIBILITY_APIS_CONFIGURATION);
- Configuration compatRestTests = project.getConfigurations().create(COMPATIBILITY_TESTS_CONFIGURATION);
- project.getArtifacts().add(compatRestSpecs.getName(), bundleRestCompatApis.map(Sync::getDestinationDir));
- project.getArtifacts()
- .add(
- compatRestTests.getName(),
- transformCompatTestTask.flatMap(t -> t.getOutputDirectory().dir(RELATIVE_TEST_PATH.toString()))
- );
-
- // Grab the original rest resources locations so we can omit them from the compatibility testing classpath down below
- Provider originalYamlSpecsDir = project.getTasks()
- .withType(CopyRestApiTask.class)
- .named(RestResourcesPlugin.COPY_REST_API_SPECS_TASK)
- .flatMap(CopyRestApiTask::getOutputResourceDir);
- Provider originalYamlTestsDir = project.getTasks()
- .withType(CopyRestTestsTask.class)
- .named(RestResourcesPlugin.COPY_YAML_TESTS_TASK)
- .flatMap(CopyRestTestsTask::getOutputResourceDir);
-
- String testTaskName = "yamlRestTestV" + COMPATIBLE_VERSION + "CompatTest";
-
- // setup the test task
- Provider yamlRestCompatTestTask = RestTestUtil.registerTestTask(project, yamlCompatTestSourceSet, testTaskName);
- project.getTasks().withType(RestIntegTestTask.class).named(testTaskName).configure(testTask -> {
- testTask.systemProperty("tests.restCompat", true);
- // Use test runner and classpath from "normal" yaml source set
- testTask.setTestClassesDirs(
- yamlTestSourceSet.getOutput().getClassesDirs().plus(yamlCompatTestSourceSet.getOutput().getClassesDirs())
- );
- testTask.setClasspath(
- yamlCompatTestSourceSet.getRuntimeClasspath()
- // remove the "normal" api and tests
- .minus(project.files(yamlTestSourceSet.getOutput().getResourcesDir()))
- .minus(project.files(originalYamlSpecsDir))
- .minus(project.files(originalYamlTestsDir))
- );
-
- // run compatibility tests after "normal" tests
- testTask.mustRunAfter(project.getTasks().named(InternalYamlRestTestPlugin.SOURCE_SET_NAME));
- testTask.onlyIf(t -> isEnabled(extraProperties));
- });
-
- setupYamlRestTestDependenciesDefaults(project, yamlCompatTestSourceSet);
-
- // setup IDE
- GradleUtils.setupIdeForTestSourceSet(project, yamlCompatTestSourceSet);
-
- // add a lifecycle task to allow for a possible future additional rest compatibility without needing to change task names
- TaskProvider checkRestCompatTask = project.getTasks().register(REST_COMPAT_CHECK_TASK_NAME, (thisCheckTask) -> {
- thisCheckTask.setDescription("Runs all REST compatibility checks.");
- thisCheckTask.setGroup("verification");
- });
-
- // wire the lifecycle task into the main check task
- project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME).configure(check -> check.dependsOn(checkRestCompatTask));
-
- // wire the yamlRestCompatTest into the custom lifecycle task
- project.getTasks().named(REST_COMPAT_CHECK_TASK_NAME).configure(check -> check.dependsOn(yamlRestCompatTestTask));
-
- }
-
- private boolean isEnabled(ExtraPropertiesExtension extraProperties) {
- Object bwcEnabled = extraProperties.getProperties().get("bwc_tests_enabled");
- return bwcEnabled == null || (Boolean) bwcEnabled;
- }
-
- // TODO: implement custom extension that allows us move around of the projects between major versions and still find them
- private Path getCompatProjectPath(String projectPath, Path checkoutDir) {
- return checkoutDir.resolve(projectPath.replaceFirst(":", "").replace(":", File.separator));
- }
-}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/ErrorReportingTestListener.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/ErrorReportingTestListener.java
index d00301e96fab..6659218593f9 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/ErrorReportingTestListener.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/ErrorReportingTestListener.java
@@ -10,12 +10,12 @@
import org.gradle.api.internal.tasks.testing.logging.FullExceptionFormatter;
import org.gradle.api.internal.tasks.testing.logging.TestExceptionFormatter;
import org.gradle.api.logging.Logger;
+import org.gradle.api.tasks.testing.Test;
import org.gradle.api.tasks.testing.TestDescriptor;
import org.gradle.api.tasks.testing.TestListener;
import org.gradle.api.tasks.testing.TestOutputEvent;
import org.gradle.api.tasks.testing.TestOutputListener;
import org.gradle.api.tasks.testing.TestResult;
-import org.gradle.api.tasks.testing.logging.TestLogging;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
@@ -38,6 +38,7 @@
public class ErrorReportingTestListener implements TestOutputListener, TestListener {
private static final String REPRODUCE_WITH_PREFIX = "REPRODUCE WITH";
+ private final Test testTask;
private final TestExceptionFormatter formatter;
private final File outputDirectory;
private final Logger taskLogger;
@@ -45,9 +46,10 @@ public class ErrorReportingTestListener implements TestOutputListener, TestListe
private Map> reproductionLines = new ConcurrentHashMap<>();
private Set failedTests = new LinkedHashSet<>();
- public ErrorReportingTestListener(TestLogging testLogging, Logger taskLogger, File outputDirectory) {
- this.formatter = new FullExceptionFormatter(testLogging);
- this.taskLogger = taskLogger;
+ public ErrorReportingTestListener(Test testTask, File outputDirectory) {
+ this.testTask = testTask;
+ this.formatter = new FullExceptionFormatter(testTask.getTestLogging());
+ this.taskLogger = testTask.getLogger();
this.outputDirectory = outputDirectory;
}
@@ -80,34 +82,37 @@ public void afterSuite(final TestDescriptor suite, TestResult result) {
Descriptor descriptor = Descriptor.of(suite);
try {
- // if the test suite failed, report all captured output
- if (result.getResultType().equals(TestResult.ResultType.FAILURE)) {
- EventWriter eventWriter = eventWriters.get(descriptor);
-
- if (eventWriter != null) {
- // It's not explicit what the threading guarantees are for TestListener method execution so we'll
- // be explicitly safe here to avoid interleaving output from multiple test suites
- synchronized (this) {
- // make sure we've flushed everything to disk before reading
- eventWriter.flush();
-
- System.err.println("\n\nSuite: " + suite);
-
- try (BufferedReader reader = eventWriter.reader()) {
- PrintStream out = System.out;
- for (String message = reader.readLine(); message != null; message = reader.readLine()) {
- if (message.startsWith(" 1> ")) {
- out = System.out;
- } else if (message.startsWith(" 2> ")) {
- out = System.err;
+ if (isDumpOutputEnabled()) {
+ // if the test suite failed, report all captured output
+ if (result.getResultType().equals(TestResult.ResultType.FAILURE)) {
+ EventWriter eventWriter = eventWriters.get(descriptor);
+
+ if (eventWriter != null) {
+ // It's not explicit what the threading guarantees are for TestListener method execution so we'll
+ // be explicitly safe here to avoid interleaving output from multiple test suites
+ synchronized (this) {
+ // make sure we've flushed everything to disk before reading
+ eventWriter.flush();
+
+ System.err.println("\n\nSuite: " + suite);
+
+ try (BufferedReader reader = eventWriter.reader()) {
+ PrintStream out = System.out;
+ for (String message = reader.readLine(); message != null; message = reader.readLine()) {
+ if (message.startsWith(" 1> ")) {
+ out = System.out;
+ } else if (message.startsWith(" 2> ")) {
+ out = System.err;
+ }
+
+ out.println(message);
}
-
- out.println(message);
}
}
}
}
}
+
if (suite.getParent() == null) {
// per test task top level gradle test run suite finished
if (getFailedTests().size() > 0) {
@@ -250,4 +255,9 @@ public void close() throws IOException {
outputFile.delete();
}
}
+
+ private boolean isDumpOutputEnabled() {
+ Object errorReportingEnabled = testTask.getExtensions().getExtraProperties().get("dumpOutputOnFailure");
+ return errorReportingEnabled == null || (boolean) errorReportingEnabled;
+ }
}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/LegacyRestTestBasePlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/LegacyRestTestBasePlugin.java
new file mode 100644
index 000000000000..f27020511145
--- /dev/null
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/LegacyRestTestBasePlugin.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal.test;
+
+import org.elasticsearch.gradle.internal.ElasticsearchJavaBasePlugin;
+import org.elasticsearch.gradle.internal.ElasticsearchTestBasePlugin;
+import org.elasticsearch.gradle.internal.FixtureStop;
+import org.elasticsearch.gradle.internal.InternalTestClustersPlugin;
+import org.elasticsearch.gradle.internal.precommit.InternalPrecommitTasks;
+import org.elasticsearch.gradle.test.SystemPropertyCommandLineArgumentProvider;
+import org.elasticsearch.gradle.testclusters.ElasticsearchCluster;
+import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask;
+import org.elasticsearch.gradle.testclusters.TestClustersPlugin;
+import org.elasticsearch.gradle.util.GradleUtils;
+import org.gradle.api.NamedDomainObjectContainer;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.plugins.JavaBasePlugin;
+import org.gradle.api.provider.ProviderFactory;
+import org.gradle.api.tasks.Sync;
+import org.gradle.api.tasks.bundling.Zip;
+
+import javax.inject.Inject;
+
+import static org.elasticsearch.gradle.plugin.BasePluginBuildPlugin.BUNDLE_PLUGIN_TASK_NAME;
+import static org.elasticsearch.gradle.plugin.BasePluginBuildPlugin.EXPLODED_BUNDLE_PLUGIN_TASK_NAME;
+
+/**
+ * @deprecated use {@link RestTestBasePlugin} instead
+ */
+@Deprecated
+public class LegacyRestTestBasePlugin implements Plugin {
+ private static final String TESTS_REST_CLUSTER = "tests.rest.cluster";
+ private static final String TESTS_CLUSTER = "tests.cluster";
+ private static final String TESTS_CLUSTER_NAME = "tests.clustername";
+ private static final String TESTS_CLUSTER_READINESS = "tests.cluster.readiness";
+
+ private static final String TESTS_CLUSTER_REMOTE_ACCESS = "tests.cluster.remote_access";
+
+ private ProviderFactory providerFactory;
+
+ @Inject
+ public LegacyRestTestBasePlugin(ProviderFactory providerFactory) {
+ this.providerFactory = providerFactory;
+ }
+
+ @Override
+ public void apply(Project project) {
+ project.getPluginManager().apply(ElasticsearchJavaBasePlugin.class);
+ project.getPluginManager().apply(ElasticsearchTestBasePlugin.class);
+ project.getPluginManager().apply(InternalTestClustersPlugin.class);
+ InternalPrecommitTasks.create(project, false);
+ project.getTasks().withType(RestIntegTestTask.class).configureEach(restIntegTestTask -> {
+ @SuppressWarnings("unchecked")
+ NamedDomainObjectContainer testClusters = (NamedDomainObjectContainer) project
+ .getExtensions()
+ .getByName(TestClustersPlugin.EXTENSION_NAME);
+ ElasticsearchCluster cluster = testClusters.maybeCreate(restIntegTestTask.getName());
+ restIntegTestTask.useCluster(cluster);
+ restIntegTestTask.include("**/*IT.class");
+ restIntegTestTask.systemProperty("tests.rest.load_packaged", Boolean.FALSE.toString());
+ if (systemProperty(TESTS_REST_CLUSTER) == null) {
+ if (systemProperty(TESTS_CLUSTER) != null || systemProperty(TESTS_CLUSTER_NAME) != null) {
+ throw new IllegalArgumentException(
+ String.format("%s, %s, and %s must all be null or non-null", TESTS_REST_CLUSTER, TESTS_CLUSTER, TESTS_CLUSTER_NAME)
+ );
+ }
+ SystemPropertyCommandLineArgumentProvider runnerNonInputProperties =
+ (SystemPropertyCommandLineArgumentProvider) restIntegTestTask.getExtensions().getByName("nonInputProperties");
+ runnerNonInputProperties.systemProperty(TESTS_REST_CLUSTER, () -> String.join(",", cluster.getAllHttpSocketURI()));
+ runnerNonInputProperties.systemProperty(TESTS_CLUSTER, () -> String.join(",", cluster.getAllTransportPortURI()));
+ runnerNonInputProperties.systemProperty(TESTS_CLUSTER_NAME, cluster::getName);
+ runnerNonInputProperties.systemProperty(TESTS_CLUSTER_READINESS, () -> String.join(",", cluster.getAllReadinessPortURI()));
+ runnerNonInputProperties.systemProperty(
+ TESTS_CLUSTER_REMOTE_ACCESS,
+ () -> String.join(",", cluster.getAllRemoteAccessPortURI())
+ );
+ } else {
+ if (systemProperty(TESTS_CLUSTER) == null || systemProperty(TESTS_CLUSTER_NAME) == null) {
+ throw new IllegalArgumentException(
+ String.format("%s, %s, and %s must all be null or non-null", TESTS_REST_CLUSTER, TESTS_CLUSTER, TESTS_CLUSTER_NAME)
+ );
+ }
+ }
+ });
+
+ project.getTasks()
+ .named(JavaBasePlugin.CHECK_TASK_NAME)
+ .configure(check -> check.dependsOn(project.getTasks().withType(RestIntegTestTask.class)));
+ project.getTasks()
+ .withType(StandaloneRestIntegTestTask.class)
+ .configureEach(t -> t.finalizedBy(project.getTasks().withType(FixtureStop.class)));
+
+ project.getTasks().withType(StandaloneRestIntegTestTask.class).configureEach(t -> {
+ t.setMaxParallelForks(1);
+ // if this a module or plugin, it may have an associated zip file with it's contents, add that to the test cluster
+ project.getPluginManager().withPlugin("elasticsearch.esplugin", plugin -> {
+ if (GradleUtils.isModuleProject(project.getPath())) {
+ var bundle = project.getTasks().withType(Sync.class).named(EXPLODED_BUNDLE_PLUGIN_TASK_NAME);
+ t.getClusters().forEach(c -> c.module(bundle));
+ } else {
+ var bundle = project.getTasks().withType(Zip.class).named(BUNDLE_PLUGIN_TASK_NAME);
+ t.getClusters().forEach(c -> c.plugin(bundle));
+ }
+ });
+ });
+ }
+
+ private String systemProperty(String propName) {
+ return providerFactory.systemProperty(propName).getOrNull();
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/RestTestBasePlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/RestTestBasePlugin.java
deleted file mode 100644
index fc27bfa43798..000000000000
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/RestTestBasePlugin.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.gradle.internal.test;
-
-import org.elasticsearch.gradle.internal.ElasticsearchJavaBasePlugin;
-import org.elasticsearch.gradle.internal.ElasticsearchTestBasePlugin;
-import org.elasticsearch.gradle.internal.FixtureStop;
-import org.elasticsearch.gradle.internal.InternalTestClustersPlugin;
-import org.elasticsearch.gradle.internal.precommit.InternalPrecommitTasks;
-import org.elasticsearch.gradle.test.SystemPropertyCommandLineArgumentProvider;
-import org.elasticsearch.gradle.testclusters.ElasticsearchCluster;
-import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask;
-import org.elasticsearch.gradle.testclusters.TestClustersPlugin;
-import org.elasticsearch.gradle.util.GradleUtils;
-import org.gradle.api.NamedDomainObjectContainer;
-import org.gradle.api.Plugin;
-import org.gradle.api.Project;
-import org.gradle.api.plugins.JavaBasePlugin;
-import org.gradle.api.provider.ProviderFactory;
-import org.gradle.api.tasks.Sync;
-import org.gradle.api.tasks.bundling.Zip;
-
-import javax.inject.Inject;
-
-import static org.elasticsearch.gradle.plugin.BasePluginBuildPlugin.BUNDLE_PLUGIN_TASK_NAME;
-import static org.elasticsearch.gradle.plugin.BasePluginBuildPlugin.EXPLODED_BUNDLE_PLUGIN_TASK_NAME;
-
-public class RestTestBasePlugin implements Plugin {
- private static final String TESTS_REST_CLUSTER = "tests.rest.cluster";
- private static final String TESTS_CLUSTER = "tests.cluster";
- private static final String TESTS_CLUSTER_NAME = "tests.clustername";
- private static final String TESTS_CLUSTER_READINESS = "tests.cluster.readiness";
-
- private ProviderFactory providerFactory;
-
- @Inject
- public RestTestBasePlugin(ProviderFactory providerFactory) {
- this.providerFactory = providerFactory;
- }
-
- @Override
- public void apply(Project project) {
- project.getPluginManager().apply(ElasticsearchJavaBasePlugin.class);
- project.getPluginManager().apply(ElasticsearchTestBasePlugin.class);
- project.getPluginManager().apply(InternalTestClustersPlugin.class);
- InternalPrecommitTasks.create(project, false);
- project.getTasks().withType(RestIntegTestTask.class).configureEach(restIntegTestTask -> {
- @SuppressWarnings("unchecked")
- NamedDomainObjectContainer testClusters = (NamedDomainObjectContainer) project
- .getExtensions()
- .getByName(TestClustersPlugin.EXTENSION_NAME);
- ElasticsearchCluster cluster = testClusters.maybeCreate(restIntegTestTask.getName());
- restIntegTestTask.useCluster(cluster);
- restIntegTestTask.include("**/*IT.class");
- restIntegTestTask.systemProperty("tests.rest.load_packaged", Boolean.FALSE.toString());
- if (systemProperty(TESTS_REST_CLUSTER) == null) {
- if (systemProperty(TESTS_CLUSTER) != null || systemProperty(TESTS_CLUSTER_NAME) != null) {
- throw new IllegalArgumentException(
- String.format("%s, %s, and %s must all be null or non-null", TESTS_REST_CLUSTER, TESTS_CLUSTER, TESTS_CLUSTER_NAME)
- );
- }
- SystemPropertyCommandLineArgumentProvider runnerNonInputProperties =
- (SystemPropertyCommandLineArgumentProvider) restIntegTestTask.getExtensions().getByName("nonInputProperties");
- runnerNonInputProperties.systemProperty(TESTS_REST_CLUSTER, () -> String.join(",", cluster.getAllHttpSocketURI()));
- runnerNonInputProperties.systemProperty(TESTS_CLUSTER, () -> String.join(",", cluster.getAllTransportPortURI()));
- runnerNonInputProperties.systemProperty(TESTS_CLUSTER_NAME, cluster::getName);
- runnerNonInputProperties.systemProperty(TESTS_CLUSTER_READINESS, () -> String.join(",", cluster.getAllReadinessPortURI()));
- } else {
- if (systemProperty(TESTS_CLUSTER) == null || systemProperty(TESTS_CLUSTER_NAME) == null) {
- throw new IllegalArgumentException(
- String.format("%s, %s, and %s must all be null or non-null", TESTS_REST_CLUSTER, TESTS_CLUSTER, TESTS_CLUSTER_NAME)
- );
- }
- }
- });
-
- project.getTasks()
- .named(JavaBasePlugin.CHECK_TASK_NAME)
- .configure(check -> check.dependsOn(project.getTasks().withType(RestIntegTestTask.class)));
- project.getTasks()
- .withType(StandaloneRestIntegTestTask.class)
- .configureEach(t -> t.finalizedBy(project.getTasks().withType(FixtureStop.class)));
-
- project.getTasks().withType(StandaloneRestIntegTestTask.class).configureEach(t ->
- // if this a module or plugin, it may have an associated zip file with it's contents, add that to the test cluster
- project.getPluginManager().withPlugin("elasticsearch.esplugin", plugin -> {
- if (GradleUtils.isModuleProject(project.getPath())) {
- var bundle = project.getTasks().withType(Sync.class).named(EXPLODED_BUNDLE_PLUGIN_TASK_NAME);
- t.getClusters().forEach(c -> c.module(bundle));
- } else {
- var bundle = project.getTasks().withType(Zip.class).named(BUNDLE_PLUGIN_TASK_NAME);
- t.getClusters().forEach(c -> c.plugin(bundle));
- }
- }));
- }
-
- private String systemProperty(String propName) {
- return providerFactory.systemProperty(propName).getOrNull();
- }
-}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/StandaloneRestTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/StandaloneRestTestPlugin.java
index 9ffaf396e7fb..163df6cc40e1 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/StandaloneRestTestPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/StandaloneRestTestPlugin.java
@@ -11,8 +11,8 @@
import org.elasticsearch.gradle.internal.ExportElasticsearchBuildResourcesTask;
import org.elasticsearch.gradle.internal.info.GlobalBuildInfoPlugin;
import org.elasticsearch.gradle.internal.precommit.InternalPrecommitTasks;
-import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin;
-import org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin;
+import org.elasticsearch.gradle.internal.test.rest.LegacyJavaRestTestPlugin;
+import org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin;
import org.elasticsearch.gradle.internal.test.rest.RestTestUtil;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Plugin;
@@ -32,8 +32,8 @@
* and run REST tests. Use BuildPlugin if you want to build main code as well
* as tests.
*
- * @deprecated use {@link InternalClusterTestPlugin}, {@link InternalJavaRestTestPlugin} or
- * {@link InternalYamlRestTestPlugin} instead.
+ * @deprecated use {@link InternalClusterTestPlugin}, {@link LegacyJavaRestTestPlugin} or
+ * {@link LegacyYamlRestTestPlugin} instead.
*/
@Deprecated
public class StandaloneRestTestPlugin implements Plugin {
@@ -46,7 +46,7 @@ public void apply(final Project project) {
}
project.getRootProject().getPluginManager().apply(GlobalBuildInfoPlugin.class);
- project.getPluginManager().apply(RestTestBasePlugin.class);
+ project.getPluginManager().apply(LegacyRestTestBasePlugin.class);
project.getTasks().register("buildResources", ExportElasticsearchBuildResourcesTask.class);
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/TestWithSslPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/TestWithSslPlugin.java
index 9eb2efc77835..524f3dfedf95 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/TestWithSslPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/TestWithSslPlugin.java
@@ -14,7 +14,7 @@
import org.elasticsearch.gradle.internal.precommit.FilePermissionsPrecommitPlugin;
import org.elasticsearch.gradle.internal.precommit.ForbiddenPatternsPrecommitPlugin;
import org.elasticsearch.gradle.internal.precommit.ForbiddenPatternsTask;
-import org.elasticsearch.gradle.internal.test.rest.InternalJavaRestTestPlugin;
+import org.elasticsearch.gradle.internal.test.rest.LegacyJavaRestTestPlugin;
import org.elasticsearch.gradle.testclusters.ElasticsearchCluster;
import org.elasticsearch.gradle.testclusters.TestClustersAware;
import org.elasticsearch.gradle.testclusters.TestClustersPlugin;
@@ -62,8 +62,8 @@ public void apply(Project project) {
.withType(RestIntegTestTask.class)
.configureEach(runner -> runner.systemProperty("tests.ssl.enabled", "true"));
});
- project.getPlugins().withType(InternalJavaRestTestPlugin.class).configureEach(restTestPlugin -> {
- SourceSet testSourceSet = Util.getJavaSourceSets(project).getByName(InternalJavaRestTestPlugin.SOURCE_SET_NAME);
+ project.getPlugins().withType(LegacyJavaRestTestPlugin.class).configureEach(restTestPlugin -> {
+ SourceSet testSourceSet = Util.getJavaSourceSets(project).getByName(LegacyJavaRestTestPlugin.SOURCE_SET_NAME);
testSourceSet.getResources().srcDir(new File(keyStoreDir, "test/ssl"));
project.getTasks().named(testSourceSet.getProcessResourcesTaskName()).configure(t -> t.dependsOn(exportKeyStore));
project.getTasks().withType(TestClustersAware.class).configureEach(clusterAware -> clusterAware.dependsOn(exportKeyStore));
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/InternalJavaRestTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/InternalJavaRestTestPlugin.java
index 9dda731f7211..d18505ca4b11 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/InternalJavaRestTestPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/InternalJavaRestTestPlugin.java
@@ -8,7 +8,7 @@
package org.elasticsearch.gradle.internal.test.rest;
-import org.elasticsearch.gradle.internal.test.RestTestBasePlugin;
+import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask;
import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
@@ -33,8 +33,11 @@ public void apply(Project project) {
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet javaTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
+ project.getDependencies().add(javaTestSourceSet.getImplementationConfigurationName(), project.project(":test:test-clusters"));
+
// setup the javaRestTest task
- registerTestTask(project, javaTestSourceSet);
+ // we use a StandloneRestIntegTestTask here so that the conventions of RestTestBasePlugin don't create a test cluster
+ registerTestTask(project, javaTestSourceSet, SOURCE_SET_NAME, StandaloneRestIntegTestTask.class);
// setup dependencies
setupJavaRestTestDependenciesDefaults(project, javaTestSourceSet);
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/InternalYamlRestTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/InternalYamlRestTestPlugin.java
index dacf119994f4..b0fd142705a0 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/InternalYamlRestTestPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/InternalYamlRestTestPlugin.java
@@ -8,7 +8,7 @@
package org.elasticsearch.gradle.internal.test.rest;
-import org.elasticsearch.gradle.internal.test.RestTestBasePlugin;
+import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask;
import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
@@ -34,10 +34,10 @@ public void apply(Project project) {
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet yamlTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
- registerTestTask(project, yamlTestSourceSet);
+ registerTestTask(project, yamlTestSourceSet, SOURCE_SET_NAME, StandaloneRestIntegTestTask.class);
// setup the dependencies
- setupYamlRestTestDependenciesDefaults(project, yamlTestSourceSet);
+ setupYamlRestTestDependenciesDefaults(project, yamlTestSourceSet, true);
// setup the copy for the rest resources
project.getTasks().withType(CopyRestApiTask.class).configureEach(copyRestApiTask -> {
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/LegacyJavaRestTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/LegacyJavaRestTestPlugin.java
new file mode 100644
index 000000000000..a1b17c110b34
--- /dev/null
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/LegacyJavaRestTestPlugin.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal.test.rest;
+
+import org.elasticsearch.gradle.internal.test.LegacyRestTestBasePlugin;
+import org.elasticsearch.gradle.util.GradleUtils;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.SourceSetContainer;
+
+import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.registerTestTask;
+import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.setupJavaRestTestDependenciesDefaults;
+
+/**
+ * Apply this plugin to run the Java based REST tests.
+ *
+ * @deprecated use {@link InternalJavaRestTestPlugin}
+ */
+@Deprecated
+public class LegacyJavaRestTestPlugin implements Plugin {
+
+ public static final String SOURCE_SET_NAME = "javaRestTest";
+
+ @Override
+ public void apply(Project project) {
+ project.getPluginManager().apply(LegacyRestTestBasePlugin.class);
+
+ // create source set
+ SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
+ SourceSet javaTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
+
+ // setup the javaRestTest task
+ registerTestTask(project, javaTestSourceSet);
+
+ // setup dependencies
+ setupJavaRestTestDependenciesDefaults(project, javaTestSourceSet);
+
+ // setup IDE
+ GradleUtils.setupIdeForTestSourceSet(project, javaTestSourceSet);
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/LegacyYamlRestTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/LegacyYamlRestTestPlugin.java
new file mode 100644
index 000000000000..4977c0924efb
--- /dev/null
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/LegacyYamlRestTestPlugin.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal.test.rest;
+
+import org.elasticsearch.gradle.internal.test.LegacyRestTestBasePlugin;
+import org.elasticsearch.gradle.util.GradleUtils;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.SourceSetContainer;
+
+import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.registerTestTask;
+import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.setupYamlRestTestDependenciesDefaults;
+
+/**
+ * Apply this plugin to run the YAML based REST tests.
+ *
+ * @deprecated use {@link InternalYamlRestTestPlugin}
+ */
+@Deprecated
+public class LegacyYamlRestTestPlugin implements Plugin {
+
+ public static final String SOURCE_SET_NAME = "yamlRestTest";
+
+ @Override
+ public void apply(Project project) {
+ project.getPluginManager().apply(LegacyRestTestBasePlugin.class);
+ project.getPluginManager().apply(RestResourcesPlugin.class);
+
+ // create source set
+ SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
+ SourceSet yamlTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
+
+ registerTestTask(project, yamlTestSourceSet);
+
+ // setup the dependencies
+ setupYamlRestTestDependenciesDefaults(project, yamlTestSourceSet);
+
+ // setup the copy for the rest resources
+ project.getTasks().withType(CopyRestApiTask.class).configureEach(copyRestApiTask -> {
+ copyRestApiTask.setSourceResourceDir(
+ yamlTestSourceSet.getResources()
+ .getSrcDirs()
+ .stream()
+ .filter(f -> f.isDirectory() && f.getName().equals("resources"))
+ .findFirst()
+ .orElse(null)
+ );
+ });
+
+ // Register rest resources with source set
+ yamlTestSourceSet.getOutput()
+ .dir(
+ project.getTasks()
+ .withType(CopyRestApiTask.class)
+ .named(RestResourcesPlugin.COPY_REST_API_SPECS_TASK)
+ .flatMap(CopyRestApiTask::getOutputResourceDir)
+ );
+
+ yamlTestSourceSet.getOutput()
+ .dir(
+ project.getTasks()
+ .withType(CopyRestTestsTask.class)
+ .named(RestResourcesPlugin.COPY_YAML_TESTS_TASK)
+ .flatMap(CopyRestTestsTask::getOutputResourceDir)
+ );
+
+ GradleUtils.setupIdeForTestSourceSet(project, yamlTestSourceSet);
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestResourcesExtension.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestResourcesExtension.java
index 8b08c23ac287..a107cfc51226 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestResourcesExtension.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestResourcesExtension.java
@@ -27,11 +27,11 @@ public RestResourcesExtension(ObjectFactory objects) {
restTests = new XpackRestResourcesSpec(objects);
}
- void restApi(Action super RestResourcesSpec> spec) {
+ public void restApi(Action super RestResourcesSpec> spec) {
spec.execute(restApi);
}
- void restTests(Action super XpackRestResourcesSpec> spec) {
+ public void restTests(Action super XpackRestResourcesSpec> spec) {
spec.execute(restTests);
}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestResourcesPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestResourcesPlugin.java
index e99ef646cdff..309480d9f600 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestResourcesPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestResourcesPlugin.java
@@ -11,6 +11,7 @@
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.attributes.Usage;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
@@ -76,6 +77,9 @@ public class RestResourcesPlugin implements Plugin {
public static final String COPY_YAML_TESTS_TASK = "copyYamlTestsTask";
public static final String COPY_REST_API_SPECS_TASK = "copyRestApiSpecsTask";
+ public static final String YAML_TESTS_USAGE = "yaml-tests";
+ public static final String YAML_XPACK_TESTS_USAGE = "yaml-xpack-tests";
+ public static final String YAML_SPEC_USAGE = "yaml-spec";
private static final String EXTENSION_NAME = "restResources";
@Override
@@ -86,8 +90,14 @@ public void apply(Project project) {
SourceSet defaultSourceSet = sourceSets.maybeCreate(TEST_SOURCE_SET_NAME);
// tests
- Configuration testConfig = project.getConfigurations().create("restTestConfig");
- Configuration xpackTestConfig = project.getConfigurations().create("restXpackTestConfig");
+ Configuration testConfig = project.getConfigurations().create("restTestConfig", config -> {
+ config.setCanBeConsumed(false);
+ config.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, YAML_TESTS_USAGE));
+ });
+ Configuration xpackTestConfig = project.getConfigurations().create("restXpackTestConfig", config -> {
+ config.setCanBeConsumed(false);
+ config.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, YAML_XPACK_TESTS_USAGE));
+ });
// core
// we guard this reference to :rest-api-spec with a find to make testing easier
var restApiSpecProjectAvailable = project.findProject(":rest-api-spec") != null;
@@ -104,8 +114,17 @@ public void apply(Project project) {
.project(Map.of("path", ":x-pack:plugin", "configuration", "restXpackTests"));
project.getDependencies().add(xpackTestConfig.getName(), restXPackTestdependency);
}
- project.getConfigurations().create("restTests");
- project.getConfigurations().create("restXpackTests");
+ project.getConfigurations()
+ .create(
+ "restTests",
+ config -> config.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, YAML_TESTS_USAGE))
+ );
+ project.getConfigurations()
+ .create(
+ "restXpackTests",
+ config -> config.getAttributes()
+ .attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, YAML_XPACK_TESTS_USAGE))
+ );
Provider copyRestYamlTestTask = project.getTasks()
.register(COPY_YAML_TESTS_TASK, CopyRestTestsTask.class, task -> {
@@ -121,13 +140,24 @@ public void apply(Project project) {
});
// api
- Configuration specConfig = project.getConfigurations().create("restSpec"); // name chosen for passivity
+ Configuration specConfig = project.getConfigurations()
+ .create(
+ "restSpec", // name chosen for passivity
+ config -> {
+ config.setCanBeConsumed(false);
+ config.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, YAML_SPEC_USAGE));
+ }
+ );
if (restApiSpecProjectAvailable) {
Dependency restSpecDependency = project.getDependencies()
.project(Map.of("path", ":rest-api-spec", "configuration", "restSpecs"));
project.getDependencies().add(specConfig.getName(), restSpecDependency);
}
- project.getConfigurations().create("restSpecs");
+ project.getConfigurations()
+ .create(
+ "restSpecs",
+ config -> config.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, YAML_SPEC_USAGE))
+ );
Provider copyRestYamlApiTask = project.getTasks()
.register(COPY_REST_API_SPECS_TASK, CopyRestApiTask.class, task -> {
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java
new file mode 100644
index 000000000000..1a7b5bc3ee2a
--- /dev/null
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal.test.rest;
+
+import groovy.lang.Closure;
+
+import org.elasticsearch.gradle.Architecture;
+import org.elasticsearch.gradle.DistributionDownloadPlugin;
+import org.elasticsearch.gradle.ElasticsearchDistribution;
+import org.elasticsearch.gradle.ElasticsearchDistributionType;
+import org.elasticsearch.gradle.Version;
+import org.elasticsearch.gradle.VersionProperties;
+import org.elasticsearch.gradle.distribution.ElasticsearchDistributionTypes;
+import org.elasticsearch.gradle.internal.ElasticsearchJavaPlugin;
+import org.elasticsearch.gradle.internal.InternalDistributionDownloadPlugin;
+import org.elasticsearch.gradle.internal.info.BuildParams;
+import org.elasticsearch.gradle.plugin.BasePluginBuildPlugin;
+import org.elasticsearch.gradle.plugin.PluginBuildPlugin;
+import org.elasticsearch.gradle.plugin.PluginPropertiesExtension;
+import org.elasticsearch.gradle.test.SystemPropertyCommandLineArgumentProvider;
+import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask;
+import org.elasticsearch.gradle.transform.UnzipTransform;
+import org.elasticsearch.gradle.util.GradleUtils;
+import org.gradle.api.Action;
+import org.gradle.api.NamedDomainObjectContainer;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.ProjectDependency;
+import org.gradle.api.artifacts.type.ArtifactTypeDefinition;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.plugins.JavaBasePlugin;
+import org.gradle.api.provider.ProviderFactory;
+import org.gradle.api.tasks.ClasspathNormalizer;
+import org.gradle.api.tasks.PathSensitivity;
+import org.gradle.api.tasks.util.PatternFilterable;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+/**
+ * Base plugin used for wiring up build tasks to REST testing tasks using new JUnit rule-based test clusters framework.
+ */
+public class RestTestBasePlugin implements Plugin {
+
+ private static final String TESTS_RUNTIME_JAVA_SYSPROP = "tests.runtime.java";
+ private static final String DEFAULT_DISTRIBUTION_SYSPROP = "tests.default.distribution";
+ private static final String INTEG_TEST_DISTRIBUTION_SYSPROP = "tests.integ-test.distribution";
+ private static final String BWC_SNAPSHOT_DISTRIBUTION_SYSPROP_PREFIX = "tests.snapshot.distribution.";
+ private static final String BWC_RELEASED_DISTRIBUTION_SYSPROP_PREFIX = "tests.release.distribution.";
+ private static final String TESTS_CLUSTER_MODULES_PATH_SYSPROP = "tests.cluster.modules.path";
+ private static final String TESTS_CLUSTER_PLUGINS_PATH_SYSPROP = "tests.cluster.plugins.path";
+ private static final String DEFAULT_REST_INTEG_TEST_DISTRO = "default_distro";
+ private static final String INTEG_TEST_REST_INTEG_TEST_DISTRO = "integ_test_distro";
+ private static final String MODULES_CONFIGURATION = "clusterModules";
+ private static final String PLUGINS_CONFIGURATION = "clusterPlugins";
+ private static final String EXTRACTED_PLUGINS_CONFIGURATION = "extractedPlugins";
+
+ private final ProviderFactory providerFactory;
+
+ @Inject
+ public RestTestBasePlugin(ProviderFactory providerFactory) {
+ this.providerFactory = providerFactory;
+ }
+
+ @Override
+ public void apply(Project project) {
+ project.getPluginManager().apply(ElasticsearchJavaPlugin.class);
+ project.getPluginManager().apply(InternalDistributionDownloadPlugin.class);
+
+ // Register integ-test and default distributions
+ ElasticsearchDistribution defaultDistro = createDistribution(
+ project,
+ DEFAULT_REST_INTEG_TEST_DISTRO,
+ VersionProperties.getElasticsearch()
+ );
+ ElasticsearchDistribution integTestDistro = createDistribution(
+ project,
+ INTEG_TEST_REST_INTEG_TEST_DISTRO,
+ VersionProperties.getElasticsearch(),
+ ElasticsearchDistributionTypes.INTEG_TEST_ZIP
+ );
+
+ // Create configures for module and plugin dependencies
+ Configuration modulesConfiguration = createPluginConfiguration(project, MODULES_CONFIGURATION, true, false);
+ Configuration pluginsConfiguration = createPluginConfiguration(project, PLUGINS_CONFIGURATION, false, false);
+ Configuration extractedPluginsConfiguration = createPluginConfiguration(project, EXTRACTED_PLUGINS_CONFIGURATION, true, true);
+ extractedPluginsConfiguration.extendsFrom(pluginsConfiguration);
+ configureArtifactTransforms(project);
+
+ // For plugin and module projects, register the current project plugin bundle as a dependency
+ project.getPluginManager().withPlugin("elasticsearch.esplugin", plugin -> {
+ if (GradleUtils.isModuleProject(project.getPath())) {
+ project.getDependencies().add(MODULES_CONFIGURATION, getExplodedBundleDependency(project, project.getPath()));
+ } else {
+ project.getDependencies().add(PLUGINS_CONFIGURATION, getBundleZipTaskDependency(project, project.getPath()));
+ }
+
+ });
+
+ project.getTasks().withType(StandaloneRestIntegTestTask.class).configureEach(task -> {
+ SystemPropertyCommandLineArgumentProvider nonInputSystemProperties = task.getExtensions()
+ .getByType(SystemPropertyCommandLineArgumentProvider.class);
+
+ task.dependsOn(integTestDistro, modulesConfiguration);
+ registerDistributionInputs(task, integTestDistro);
+
+ // Enable parallel execution for these tests since each test gets its own cluster
+ task.setMaxParallelForks(task.getProject().getGradle().getStartParameter().getMaxWorkerCount() / 2);
+
+ // Disable test failure reporting since this stuff is now captured in build scans
+ task.getExtensions().getExtraProperties().set("dumpOutputOnFailure", false);
+
+ // Disable the security manager and syscall filter since the test framework needs to fork processes
+ task.systemProperty("tests.security.manager", "false");
+ task.systemProperty("tests.system_call_filter", "false");
+
+ // Register plugins and modules as task inputs and pass paths as system properties to tests
+ nonInputSystemProperties.systemProperty(TESTS_CLUSTER_MODULES_PATH_SYSPROP, modulesConfiguration::getAsPath);
+ registerConfigurationInputs(task, modulesConfiguration);
+ nonInputSystemProperties.systemProperty(TESTS_CLUSTER_PLUGINS_PATH_SYSPROP, pluginsConfiguration::getAsPath);
+ registerConfigurationInputs(task, extractedPluginsConfiguration);
+
+ // Wire up integ-test distribution by default for all test tasks
+ nonInputSystemProperties.systemProperty(
+ INTEG_TEST_DISTRIBUTION_SYSPROP,
+ () -> integTestDistro.getExtracted().getSingleFile().getPath()
+ );
+ nonInputSystemProperties.systemProperty(TESTS_RUNTIME_JAVA_SYSPROP, BuildParams.getRuntimeJavaHome());
+
+ // Add `usesDefaultDistribution()` extension method to test tasks to indicate they require the default distro
+ task.getExtensions().getExtraProperties().set("usesDefaultDistribution", new Closure(task) {
+ @Override
+ public Void call(Object... args) {
+ task.dependsOn(defaultDistro);
+ registerDistributionInputs(task, defaultDistro);
+
+ nonInputSystemProperties.systemProperty(
+ DEFAULT_DISTRIBUTION_SYSPROP,
+ providerFactory.provider(() -> defaultDistro.getExtracted().getSingleFile().getPath())
+ );
+ return null;
+ }
+ });
+
+ // Add `usesBwcDistribution(version)` extension method to test tasks to indicate they require a BWC distribution
+ task.getExtensions().getExtraProperties().set("usesBwcDistribution", new Closure(task) {
+ @Override
+ public Void call(Object... args) {
+ if (args.length != 1 && args[0] instanceof Version == false) {
+ throw new IllegalArgumentException("Expected exactly one argument of type org.elasticsearch.gradle.Version");
+ }
+
+ Version version = (Version) args[0];
+ boolean isReleased = BuildParams.getBwcVersions().unreleasedInfo(version) == null;
+ String versionString = version.toString();
+ ElasticsearchDistribution bwcDistro = createDistribution(project, "bwc_" + versionString, versionString);
+
+ task.dependsOn(bwcDistro);
+ registerDistributionInputs(task, bwcDistro);
+
+ nonInputSystemProperties.systemProperty(
+ (isReleased ? BWC_RELEASED_DISTRIBUTION_SYSPROP_PREFIX : BWC_SNAPSHOT_DISTRIBUTION_SYSPROP_PREFIX) + versionString,
+ providerFactory.provider(() -> bwcDistro.getExtracted().getSingleFile().getPath())
+ );
+
+ if (version.before(BuildParams.getBwcVersions().getMinimumWireCompatibleVersion())) {
+ // If we are upgrade testing older versions we also need to upgrade to 7.last
+ this.call(BuildParams.getBwcVersions().getMinimumWireCompatibleVersion());
+ }
+ return null;
+ }
+ });
+ });
+
+ project.getTasks()
+ .named(JavaBasePlugin.CHECK_TASK_NAME)
+ .configure(check -> check.dependsOn(project.getTasks().withType(StandaloneRestIntegTestTask.class)));
+ }
+
+ private ElasticsearchDistribution createDistribution(Project project, String name, String version) {
+ return createDistribution(project, name, version, null);
+ }
+
+ private ElasticsearchDistribution createDistribution(Project project, String name, String version, ElasticsearchDistributionType type) {
+ NamedDomainObjectContainer distributions = DistributionDownloadPlugin.getContainer(project);
+ ElasticsearchDistribution maybeDistro = distributions.findByName(name);
+ if (maybeDistro == null) {
+ return distributions.create(name, distro -> {
+ distro.setVersion(version);
+ distro.setArchitecture(Architecture.current());
+ if (type != null) {
+ distro.setType(type);
+ }
+ });
+ } else {
+ return maybeDistro;
+ }
+ }
+
+ private FileTree getDistributionFiles(ElasticsearchDistribution distribution, Action patternFilter) {
+ return distribution.getExtracted().getAsFileTree().matching(patternFilter);
+ }
+
+ private void registerConfigurationInputs(Task task, Configuration configuration) {
+ task.getInputs()
+ .files(providerFactory.provider(() -> configuration.getAsFileTree().filter(f -> f.getName().endsWith(".jar") == false)))
+ .withPropertyName(configuration.getName() + "-files")
+ .withPathSensitivity(PathSensitivity.RELATIVE);
+
+ task.getInputs()
+ .files(providerFactory.provider(() -> configuration.getAsFileTree().filter(f -> f.getName().endsWith(".jar"))))
+ .withPropertyName(configuration.getName() + "-classpath")
+ .withNormalizer(ClasspathNormalizer.class);
+ }
+
+ private void registerDistributionInputs(Task task, ElasticsearchDistribution distribution) {
+ task.getInputs()
+ .files(providerFactory.provider(() -> getDistributionFiles(distribution, filter -> filter.exclude("**/*.jar"))))
+ .withPropertyName(distribution.getName() + "-files")
+ .withPathSensitivity(PathSensitivity.RELATIVE);
+
+ task.getInputs()
+ .files(providerFactory.provider(() -> getDistributionFiles(distribution, filter -> filter.include("**/*.jar"))))
+ .withPropertyName(distribution.getName() + "-classpath")
+ .withNormalizer(ClasspathNormalizer.class);
+ }
+
+ private Optional findModulePath(Project project, String pluginName) {
+ return project.getRootProject()
+ .getAllprojects()
+ .stream()
+ .filter(p -> GradleUtils.isModuleProject(p.getPath()))
+ .filter(p -> p.getPlugins().hasPlugin(PluginBuildPlugin.class))
+ .filter(p -> p.getExtensions().getByType(PluginPropertiesExtension.class).getName().equals(pluginName))
+ .findFirst()
+ .map(Project::getPath);
+ }
+
+ private Configuration createPluginConfiguration(Project project, String name, boolean useExploded, boolean isExtended) {
+ return project.getConfigurations().create(name, c -> {
+ if (useExploded) {
+ c.attributes(a -> a.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE));
+ } else {
+ c.attributes(a -> a.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.ZIP_TYPE));
+ }
+ if (isExtended == false) {
+ c.withDependencies(dependencies -> {
+ // Add dependencies of any modules
+ Collection additionalDependencies = new LinkedHashSet<>();
+ for (Iterator iterator = dependencies.iterator(); iterator.hasNext();) {
+ Dependency dependency = iterator.next();
+ if (dependency instanceof ProjectDependency projectDependency) {
+ Project dependencyProject = projectDependency.getDependencyProject();
+ List extendedPlugins = dependencyProject.getExtensions()
+ .getByType(PluginPropertiesExtension.class)
+ .getExtendedPlugins();
+
+ // Replace project dependency with explicit dependency on exploded configuration to workaround variant bug
+ if (projectDependency.getTargetConfiguration() == null) {
+ iterator.remove();
+ additionalDependencies.add(
+ useExploded
+ ? getExplodedBundleDependency(project, dependencyProject.getPath())
+ : getBundleZipTaskDependency(project, dependencyProject.getPath())
+ );
+ }
+
+ for (String extendedPlugin : extendedPlugins) {
+ findModulePath(project, extendedPlugin).ifPresent(
+ modulePath -> additionalDependencies.add(
+ useExploded
+ ? getExplodedBundleDependency(project, modulePath)
+ : getBundleZipTaskDependency(project, modulePath)
+ )
+ );
+ }
+ }
+ }
+
+ dependencies.addAll(additionalDependencies);
+ });
+ }
+ });
+ }
+
+ private Dependency getExplodedBundleDependency(Project project, String projectPath) {
+ return project.getDependencies()
+ .project(Map.of("path", projectPath, "configuration", BasePluginBuildPlugin.EXPLODED_BUNDLE_CONFIG));
+ }
+
+ private Dependency getBundleZipTaskDependency(Project project, String projectPath) {
+ Project dependencyProject = project.findProject(projectPath);
+ return project.getDependencies()
+ .create(project.files(dependencyProject.getTasks().named(BasePluginBuildPlugin.BUNDLE_PLUGIN_TASK_NAME)));
+ }
+
+ private void configureArtifactTransforms(Project project) {
+ project.getDependencies().registerTransform(UnzipTransform.class, transformSpec -> {
+ transformSpec.getFrom().attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.ZIP_TYPE);
+ transformSpec.getTo().attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE);
+ transformSpec.getParameters().setAsFiletreeOutput(false);
+ });
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestUtil.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestUtil.java
index 922157333d80..99c25b9e2570 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestUtil.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestUtil.java
@@ -15,6 +15,7 @@
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskProvider;
+import org.gradle.api.tasks.testing.Test;
/**
* Utility class to configure the necessary tasks and dependencies.
@@ -34,8 +35,17 @@ public static Provider registerTestTask(Project project, Sour
* Creates a {@link RestIntegTestTask} task with a custom name for the provided source set
*/
public static TaskProvider registerTestTask(Project project, SourceSet sourceSet, String taskName) {
+ return registerTestTask(project, sourceSet, taskName, RestIntegTestTask.class);
+ }
+
+ /**
+ * Creates a {@link T} task with a custom name for the provided source set
+ *
+ * @param test task type
+ */
+ public static TaskProvider registerTestTask(Project project, SourceSet sourceSet, String taskName, Class clazz) {
// lazily create the test task
- return project.getTasks().register(taskName, RestIntegTestTask.class, testTask -> {
+ return project.getTasks().register(taskName, clazz, testTask -> {
testTask.setGroup(JavaBasePlugin.VERIFICATION_GROUP);
testTask.setDescription("Runs the REST tests against an external cluster");
project.getPlugins().withType(JavaPlugin.class, t -> testTask.mustRunAfter(project.getTasks().named("test")));
@@ -49,10 +59,20 @@ public static TaskProvider registerTestTask(Project project,
* Setup the dependencies needed for the YAML REST tests.
*/
public static void setupYamlRestTestDependenciesDefaults(Project project, SourceSet sourceSet) {
+ setupYamlRestTestDependenciesDefaults(project, sourceSet, false);
+ }
+
+ /**
+ * Setup the dependencies needed for the YAML REST tests.
+ */
+ public static void setupYamlRestTestDependenciesDefaults(Project project, SourceSet sourceSet, boolean useNewTestClusters) {
Project yamlTestRunnerProject = project.findProject(":test:yaml-rest-runner");
// we shield the project dependency to make integration tests easier
if (yamlTestRunnerProject != null) {
project.getDependencies().add(sourceSet.getImplementationConfigurationName(), yamlTestRunnerProject);
+ if (useNewTestClusters) {
+ project.getDependencies().add(sourceSet.getImplementationConfigurationName(), project.project(":test:test-clusters"));
+ }
}
}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/AbstractYamlRestCompatTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/AbstractYamlRestCompatTestPlugin.java
new file mode 100644
index 000000000000..273a0a379318
--- /dev/null
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/AbstractYamlRestCompatTestPlugin.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal.test.rest.compat.compat;
+
+import org.elasticsearch.gradle.Version;
+import org.elasticsearch.gradle.VersionProperties;
+import org.elasticsearch.gradle.internal.ElasticsearchJavaBasePlugin;
+import org.elasticsearch.gradle.internal.test.LegacyRestTestBasePlugin;
+import org.elasticsearch.gradle.internal.test.rest.CopyRestApiTask;
+import org.elasticsearch.gradle.internal.test.rest.CopyRestTestsTask;
+import org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin;
+import org.elasticsearch.gradle.internal.test.rest.RestResourcesExtension;
+import org.elasticsearch.gradle.internal.test.rest.RestResourcesPlugin;
+import org.elasticsearch.gradle.testclusters.TestClustersPlugin;
+import org.elasticsearch.gradle.util.GradleUtils;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.file.Directory;
+import org.gradle.api.file.ProjectLayout;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.FileOperations;
+import org.gradle.api.plugins.ExtraPropertiesExtension;
+import org.gradle.api.plugins.JavaBasePlugin;
+import org.gradle.api.provider.Provider;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.SourceSetContainer;
+import org.gradle.api.tasks.Sync;
+import org.gradle.api.tasks.TaskProvider;
+import org.gradle.api.tasks.testing.Test;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import static org.elasticsearch.gradle.internal.test.rest.RestTestUtil.setupYamlRestTestDependenciesDefaults;
+
+/**
+ * Apply this plugin to run the YAML based REST tests from a prior major version against this version's cluster.
+ */
+public abstract class AbstractYamlRestCompatTestPlugin implements Plugin {
+ public static final String BWC_MINOR_CONFIG_NAME = "bwcMinor";
+ private static final String REST_COMPAT_CHECK_TASK_NAME = "checkRestCompat";
+ private static final String COMPATIBILITY_APIS_CONFIGURATION = "restCompatSpecs";
+ private static final String COMPATIBILITY_TESTS_CONFIGURATION = "restCompatTests";
+ private static final Path RELATIVE_API_PATH = Path.of("rest-api-spec/api");
+ private static final Path RELATIVE_TEST_PATH = Path.of("rest-api-spec/test");
+ private static final Path RELATIVE_REST_API_RESOURCES = Path.of("rest-api-spec/src/main/resources");
+ private static final Path RELATIVE_REST_CORE = Path.of("rest-api-spec");
+ private static final Path RELATIVE_REST_XPACK = Path.of("x-pack/plugin");
+ private static final Path RELATIVE_REST_PROJECT_RESOURCES = Path.of("src/yamlRestTest/resources");
+ private static final int COMPATIBLE_VERSION = Version.fromString(VersionProperties.getVersions().get("elasticsearch")).getMajor() - 1;
+ private static final String SOURCE_SET_NAME = "yamlRestTestV" + COMPATIBLE_VERSION + "Compat";
+ private ProjectLayout projectLayout;
+ private FileOperations fileOperations;
+
+ @Inject
+ public AbstractYamlRestCompatTestPlugin(ProjectLayout projectLayout, FileOperations fileOperations) {
+ this.projectLayout = projectLayout;
+ this.fileOperations = fileOperations;
+ }
+
+ @Override
+ public void apply(Project project) {
+
+ final Path compatRestResourcesDir = Path.of("restResources").resolve("v" + COMPATIBLE_VERSION);
+ final Path compatSpecsDir = compatRestResourcesDir.resolve("yamlSpecs");
+ final Path compatTestsDir = compatRestResourcesDir.resolve("yamlTests");
+
+ project.getPluginManager().apply(ElasticsearchJavaBasePlugin.class);
+ project.getPluginManager().apply(TestClustersPlugin.class);
+ project.getPluginManager().apply(LegacyRestTestBasePlugin.class);
+ project.getPluginManager().apply(RestResourcesPlugin.class);
+ project.getPluginManager().apply(getBasePlugin());
+
+ RestResourcesExtension extension = project.getExtensions().getByType(RestResourcesExtension.class);
+
+ // create source set
+ SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
+ SourceSet yamlCompatTestSourceSet = sourceSets.create(SOURCE_SET_NAME);
+ SourceSet yamlTestSourceSet = sourceSets.getByName(LegacyYamlRestTestPlugin.SOURCE_SET_NAME);
+ GradleUtils.extendSourceSet(project, LegacyYamlRestTestPlugin.SOURCE_SET_NAME, SOURCE_SET_NAME);
+
+ // copy compatible rest specs
+ Configuration bwcMinorConfig = project.getConfigurations().create(BWC_MINOR_CONFIG_NAME);
+ Dependency bwcMinor = project.getDependencies()
+ .project(Map.of("path", ":distribution:bwc:maintenance", "configuration", "checkout"));
+ project.getDependencies().add(bwcMinorConfig.getName(), bwcMinor);
+
+ String projectPath = project.getPath();
+ ExtraPropertiesExtension extraProperties = project.getExtensions().getExtraProperties();
+ Provider copyCompatYamlSpecTask = project.getTasks()
+ .register("copyRestCompatApiTask", CopyRestApiTask.class, task -> {
+ task.dependsOn(bwcMinorConfig);
+ task.setConfig(bwcMinorConfig);
+ task.setAdditionalConfig(bwcMinorConfig);
+ task.getInclude().set(extension.getRestApi().getInclude());
+ task.getOutputResourceDir().set(projectLayout.getBuildDirectory().dir(compatSpecsDir.toString()));
+ task.setSourceResourceDir(
+ yamlCompatTestSourceSet.getResources()
+ .getSrcDirs()
+ .stream()
+ .filter(f -> f.isDirectory() && f.getName().equals("resources"))
+ .findFirst()
+ .orElse(null)
+ );
+ task.setSkipHasRestTestCheck(true);
+ task.setConfigToFileTree(
+ config -> fileOperations.fileTree(
+ config.getSingleFile().toPath().resolve(RELATIVE_REST_API_RESOURCES).resolve(RELATIVE_API_PATH)
+ )
+ );
+ task.setAdditionalConfigToFileTree(
+ config -> fileOperations.fileTree(
+ getCompatProjectPath(projectPath, config.getSingleFile().toPath()).resolve(RELATIVE_REST_PROJECT_RESOURCES)
+ .resolve(RELATIVE_API_PATH)
+ )
+ );
+ task.onlyIf(t -> isEnabled(extraProperties));
+ });
+
+ // copy compatible rest tests
+ Provider copyCompatYamlTestTask = project.getTasks()
+ .register("copyRestCompatTestTask", CopyRestTestsTask.class, task -> {
+ task.dependsOn(bwcMinorConfig);
+ task.setCoreConfig(bwcMinorConfig);
+ task.setXpackConfig(bwcMinorConfig);
+ task.setAdditionalConfig(bwcMinorConfig);
+ task.getIncludeCore().set(extension.getRestTests().getIncludeCore());
+ task.getIncludeXpack().set(extension.getRestTests().getIncludeXpack());
+ task.getOutputResourceDir().set(projectLayout.getBuildDirectory().dir(compatTestsDir.resolve("original").toString()));
+ task.setCoreConfigToFileTree(
+ config -> fileOperations.fileTree(
+ config.getSingleFile()
+ .toPath()
+ .resolve(RELATIVE_REST_CORE)
+ .resolve(RELATIVE_REST_PROJECT_RESOURCES)
+ .resolve(RELATIVE_TEST_PATH)
+ )
+ );
+ task.setXpackConfigToFileTree(
+ config -> fileOperations.fileTree(
+ config.getSingleFile()
+ .toPath()
+ .resolve(RELATIVE_REST_XPACK)
+ .resolve(RELATIVE_REST_PROJECT_RESOURCES)
+ .resolve(RELATIVE_TEST_PATH)
+ )
+ );
+ task.setAdditionalConfigToFileTree(
+ config -> fileOperations.fileTree(
+ getCompatProjectPath(projectPath, config.getSingleFile().toPath()).resolve(RELATIVE_REST_PROJECT_RESOURCES)
+ .resolve(RELATIVE_TEST_PATH)
+ )
+ );
+ task.dependsOn(copyCompatYamlSpecTask);
+ task.onlyIf(t -> isEnabled(extraProperties));
+ });
+
+ // copy both local source set apis and compat apis to a single location to be exported as an artifact
+ TaskProvider bundleRestCompatApis = project.getTasks().register("bundleRestCompatApis", Sync.class, task -> {
+ task.setDestinationDir(projectLayout.getBuildDirectory().dir("bundledCompatApis").get().getAsFile());
+ task.setIncludeEmptyDirs(false);
+ task.from(copyCompatYamlSpecTask.flatMap(t -> t.getOutputResourceDir().map(d -> d.dir(RELATIVE_API_PATH.toString()))));
+ task.from(yamlCompatTestSourceSet.getProcessResourcesTaskName(), s -> {
+ s.include(RELATIVE_API_PATH + "/*");
+ s.eachFile(
+ details -> details.setRelativePath(
+ new RelativePath(true, Arrays.stream(details.getRelativePath().getSegments()).skip(2).toArray(String[]::new))
+ )
+ );
+ });
+ });
+
+ // transform the copied tests task
+ TaskProvider transformCompatTestTask = project.getTasks()
+ .register("yamlRestTestV" + COMPATIBLE_VERSION + "CompatTransform", RestCompatTestTransformTask.class, task -> {
+ task.getSourceDirectory().set(copyCompatYamlTestTask.flatMap(CopyRestTestsTask::getOutputResourceDir));
+ task.getOutputDirectory()
+ .set(project.getLayout().getBuildDirectory().dir(compatTestsDir.resolve("transformed").toString()));
+ task.onlyIf(t -> isEnabled(extraProperties));
+ });
+
+ // Register compat rest resources with source set
+ yamlCompatTestSourceSet.getOutput().dir(copyCompatYamlSpecTask.map(CopyRestApiTask::getOutputResourceDir));
+ yamlCompatTestSourceSet.getOutput().dir(transformCompatTestTask.map(RestCompatTestTransformTask::getOutputDirectory));
+
+ // Register artifact for transformed compatibility apis and tests
+ Configuration compatRestSpecs = project.getConfigurations().create(COMPATIBILITY_APIS_CONFIGURATION);
+ Configuration compatRestTests = project.getConfigurations().create(COMPATIBILITY_TESTS_CONFIGURATION);
+ project.getArtifacts().add(compatRestSpecs.getName(), bundleRestCompatApis.map(Sync::getDestinationDir));
+ project.getArtifacts()
+ .add(
+ compatRestTests.getName(),
+ transformCompatTestTask.flatMap(t -> t.getOutputDirectory().dir(RELATIVE_TEST_PATH.toString()))
+ );
+
+ // Grab the original rest resources locations so we can omit them from the compatibility testing classpath down below
+ Provider originalYamlSpecsDir = project.getTasks()
+ .withType(CopyRestApiTask.class)
+ .named(RestResourcesPlugin.COPY_REST_API_SPECS_TASK)
+ .flatMap(CopyRestApiTask::getOutputResourceDir);
+ Provider originalYamlTestsDir = project.getTasks()
+ .withType(CopyRestTestsTask.class)
+ .named(RestResourcesPlugin.COPY_YAML_TESTS_TASK)
+ .flatMap(CopyRestTestsTask::getOutputResourceDir);
+
+ // setup the test task
+ TaskProvider extends Test> yamlRestCompatTestTask = registerTestTask(project, yamlCompatTestSourceSet);
+ yamlRestCompatTestTask.configure(testTask -> {
+ testTask.systemProperty("tests.restCompat", true);
+ // Use test runner and classpath from "normal" yaml source set
+ testTask.setTestClassesDirs(
+ yamlTestSourceSet.getOutput().getClassesDirs().plus(yamlCompatTestSourceSet.getOutput().getClassesDirs())
+ );
+ testTask.setClasspath(
+ yamlCompatTestSourceSet.getRuntimeClasspath()
+ // remove the "normal" api and tests
+ .minus(project.files(yamlTestSourceSet.getOutput().getResourcesDir()))
+ .minus(project.files(originalYamlSpecsDir))
+ .minus(project.files(originalYamlTestsDir))
+ );
+
+ // run compatibility tests after "normal" tests
+ testTask.mustRunAfter(project.getTasks().named(LegacyYamlRestTestPlugin.SOURCE_SET_NAME));
+ testTask.onlyIf(t -> isEnabled(extraProperties));
+ });
+
+ setupYamlRestTestDependenciesDefaults(project, yamlCompatTestSourceSet, true);
+
+ // setup IDE
+ GradleUtils.setupIdeForTestSourceSet(project, yamlCompatTestSourceSet);
+
+ // add a lifecycle task to allow for a possible future additional rest compatibility without needing to change task names
+ TaskProvider checkRestCompatTask = project.getTasks().register(REST_COMPAT_CHECK_TASK_NAME, (thisCheckTask) -> {
+ thisCheckTask.setDescription("Runs all REST compatibility checks.");
+ thisCheckTask.setGroup("verification");
+ });
+
+ // wire the lifecycle task into the main check task
+ project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME).configure(check -> check.dependsOn(checkRestCompatTask));
+
+ // wire the yamlRestCompatTest into the custom lifecycle task
+ project.getTasks().named(REST_COMPAT_CHECK_TASK_NAME).configure(check -> check.dependsOn(yamlRestCompatTestTask));
+
+ }
+
+ public abstract TaskProvider extends Test> registerTestTask(Project project, SourceSet sourceSet);
+
+ public abstract Class extends Plugin> getBasePlugin();
+
+ private boolean isEnabled(ExtraPropertiesExtension extraProperties) {
+ Object bwcEnabled = extraProperties.getProperties().get("bwc_tests_enabled");
+ return bwcEnabled == null || (Boolean) bwcEnabled;
+ }
+
+ // TODO: implement custom extension that allows us move around of the projects between major versions and still find them
+ private Path getCompatProjectPath(String projectPath, Path checkoutDir) {
+ return checkoutDir.resolve(projectPath.replaceFirst(":", "").replace(":", File.separator));
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/LegacyYamlRestCompatTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/LegacyYamlRestCompatTestPlugin.java
new file mode 100644
index 000000000000..e84c84cc426a
--- /dev/null
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/LegacyYamlRestCompatTestPlugin.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal.test.rest.compat.compat;
+
+import org.elasticsearch.gradle.internal.test.rest.LegacyYamlRestTestPlugin;
+import org.elasticsearch.gradle.internal.test.rest.RestTestUtil;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.file.ProjectLayout;
+import org.gradle.api.internal.file.FileOperations;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.TaskProvider;
+import org.gradle.api.tasks.testing.Test;
+
+import javax.inject.Inject;
+
+/**
+ * Apply this plugin to run the YAML based REST tests from a prior major version against this version's cluster.
+ *
+ * @deprecated use {@link YamlRestCompatTestPlugin}
+ */
+@Deprecated
+public class LegacyYamlRestCompatTestPlugin extends AbstractYamlRestCompatTestPlugin {
+ @Inject
+ public LegacyYamlRestCompatTestPlugin(ProjectLayout projectLayout, FileOperations fileOperations) {
+ super(projectLayout, fileOperations);
+ }
+
+ @Override
+ public TaskProvider extends Test> registerTestTask(Project project, SourceSet sourceSet) {
+ return RestTestUtil.registerTestTask(project, sourceSet, sourceSet.getTaskName(null, "test"));
+ }
+
+ @Override
+ public Class extends Plugin> getBasePlugin() {
+ return LegacyYamlRestTestPlugin.class;
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/rest/compat/RestCompatTestTransformTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/RestCompatTestTransformTask.java
similarity index 99%
rename from build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/rest/compat/RestCompatTestTransformTask.java
rename to build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/RestCompatTestTransformTask.java
index bfb53c23b5f1..eee1c4c21eb0 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/rest/compat/RestCompatTestTransformTask.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/RestCompatTestTransformTask.java
@@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
-package org.elasticsearch.gradle.internal.rest.compat;
+package org.elasticsearch.gradle.internal.test.rest.compat.compat;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/YamlRestCompatTestPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/YamlRestCompatTestPlugin.java
new file mode 100644
index 000000000000..79588ca722ff
--- /dev/null
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/compat/compat/YamlRestCompatTestPlugin.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal.test.rest.compat.compat;
+
+import org.elasticsearch.gradle.internal.test.rest.InternalYamlRestTestPlugin;
+import org.elasticsearch.gradle.internal.test.rest.RestTestUtil;
+import org.elasticsearch.gradle.testclusters.StandaloneRestIntegTestTask;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.file.ProjectLayout;
+import org.gradle.api.internal.file.FileOperations;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.TaskProvider;
+import org.gradle.api.tasks.testing.Test;
+
+import javax.inject.Inject;
+
+/**
+ * Apply this plugin to run the YAML based REST tests from a prior major version against this version's cluster.
+ */
+public class YamlRestCompatTestPlugin extends AbstractYamlRestCompatTestPlugin {
+ @Inject
+ public YamlRestCompatTestPlugin(ProjectLayout projectLayout, FileOperations fileOperations) {
+ super(projectLayout, fileOperations);
+ }
+
+ @Override
+ public TaskProvider extends Test> registerTestTask(Project project, SourceSet sourceSet) {
+ return RestTestUtil.registerTestTask(project, sourceSet, sourceSet.getTaskName(null, "test"), StandaloneRestIntegTestTask.class);
+ }
+
+ @Override
+ public Class extends Plugin> getBasePlugin() {
+ return InternalYamlRestTestPlugin.class;
+ }
+}
diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/testfixtures/TestFixturesPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/testfixtures/TestFixturesPlugin.java
index 384774190207..3d59cf337e87 100644
--- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/testfixtures/TestFixturesPlugin.java
+++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/testfixtures/TestFixturesPlugin.java
@@ -117,6 +117,7 @@ public void execute(Task task) {
maybeSkipTask(dockerSupport, buildFixture);
ComposeExtension composeExtension = project.getExtensions().getByType(ComposeExtension.class);
+ composeExtension.setProjectName(project.getName());
composeExtension.getUseComposeFiles().addAll(Collections.singletonList(DOCKER_COMPOSE_YML));
composeExtension.getRemoveContainers().set(true);
composeExtension.getCaptureContainersOutput()
diff --git a/build-tools-internal/src/main/resources/forbidden/es-server-signatures.txt b/build-tools-internal/src/main/resources/forbidden/es-server-signatures.txt
index 729907f9e42a..64f89d6c57ed 100644
--- a/build-tools-internal/src/main/resources/forbidden/es-server-signatures.txt
+++ b/build-tools-internal/src/main/resources/forbidden/es-server-signatures.txt
@@ -139,7 +139,9 @@ org.apache.logging.log4j.LogManager#getLogger()
# This is permitted in test code, where we have a Checkstyle rule to guard
# against unsafe uses. This leniency does not extend to server code.
-java.lang.String#formatted(java.lang.Object[]) @ Uses default locale - use String#format(Locale, String, Object...) instead
+@defaultMessage Uses default locale - use org.elasticsearch.common.Strings#format(String, Object...) instead
+java.lang.String#formatted(java.lang.Object[])
+java.lang.String#format(java.lang.String,java.lang.Object[])
@defaultMessage Unbatched cluster state tasks are a source of performance and stability bugs. Implement the update logic in a executor which is reused across tasks instead.
org.elasticsearch.cluster.service.MasterService#submitUnbatchedStateUpdateTask(java.lang.String, org.elasticsearch.cluster.ClusterStateUpdateTask)
diff --git a/build-tools-internal/src/main/resources/templates/breaking-changes.asciidoc b/build-tools-internal/src/main/resources/templates/breaking-changes.asciidoc
index a16c7e393ee9..d181c60f6463 100644
--- a/build-tools-internal/src/main/resources/templates/breaking-changes.asciidoc
+++ b/build-tools-internal/src/main/resources/templates/breaking-changes.asciidoc
@@ -7,7 +7,7 @@
This section discusses the changes that you need to be aware of when migrating
your application to {es} ${majorDotMinor}.
-See also <> and <>.
+See also {ref-bare}/${majorDotMinor}/release-highlights.html[What's new in ${majorDotMinor}] and <>.
<% if (isElasticsearchSnapshot) { %>
coming::[${majorDotMinorDotRevision}]
<% } %>
diff --git a/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateMigrationFile.asciidoc b/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateMigrationFile.asciidoc
index d8be43130260..1c835da9994a 100644
--- a/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateMigrationFile.asciidoc
+++ b/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateMigrationFile.asciidoc
@@ -7,7 +7,7 @@
This section discusses the changes that you need to be aware of when migrating
your application to {es} 8.4.
-See also <> and <>.
+See also {ref-bare}/8.4/release-highlights.html[What's new in 8.4] and <>.
coming::[8.4.0]
diff --git a/build-tools-internal/version.properties b/build-tools-internal/version.properties
index 32617c9623a9..0444d4152ce1 100644
--- a/build-tools-internal/version.properties
+++ b/build-tools-internal/version.properties
@@ -1,32 +1,30 @@
elasticsearch = 8.7.0
-lucene = 9.4.1
+lucene = 9.5.0
bundled_jdk_vendor = openjdk
-bundled_jdk = 19.0.1+10@afdd2e245b014143b62ccb916125e3ce
+bundled_jdk = 19.0.2+7@fdb695a9d9064ad6b064dc6df578380c
# optional dependencies
spatial4j = 0.7
jts = 1.15.0
-jackson = 2.14.0
+jackson = 2.14.2
snakeyaml = 1.33
icu4j = 68.2
supercsv = 2.4.0
log4j = 2.19.0
slf4j = 1.6.2
ecsLogging = 1.2.0
-
jna = 5.10.0
+netty = 4.1.86.Final
+commons_lang3 = 3.9
+google_oauth_client = 1.34.1
-netty = 4.1.84.Final
-
-commons_lang3 = 3.9
-
+antlr4 = 4.11.1
# when updating this version, you need to ensure compatibility with:
# - modules/ingest-attachment (transitive dependency, check the upstream POM)
# - distribution/tools/plugin-cli
# - x-pack/plugin/security
bouncycastle=1.64
-
# used by security and idp (need to be in sync due to cross-dependency in testing)
opensaml = 4.0.1
@@ -36,6 +34,7 @@ httpcore = 4.4.13
httpasyncclient = 4.1.5
commonslogging = 1.2
commonscodec = 1.15
+protobuf = 3.21.9
# test dependencies
randomizedrunner = 2.8.0
diff --git a/build-tools/src/integTest/groovy/org/elasticsearch/gradle/plugin/StablePluginBuildPluginFuncTest.groovy b/build-tools/src/integTest/groovy/org/elasticsearch/gradle/plugin/StablePluginBuildPluginFuncTest.groovy
index fc706497008a..9b0a44ad9710 100644
--- a/build-tools/src/integTest/groovy/org/elasticsearch/gradle/plugin/StablePluginBuildPluginFuncTest.groovy
+++ b/build-tools/src/integTest/groovy/org/elasticsearch/gradle/plugin/StablePluginBuildPluginFuncTest.groovy
@@ -19,15 +19,11 @@ import java.nio.file.Files
import java.nio.file.Path
import java.util.stream.Collectors
+import static org.elasticsearch.gradle.fixtures.TestClasspathUtils.setupNamedComponentScanner
+
class StablePluginBuildPluginFuncTest extends AbstractGradleFuncTest {
def setup() {
- // underlaying TestClusterPlugin and StandaloneRestIntegTestTask are not cc compatible
- configurationCacheCompatible = false
- }
-
- def "can build stable plugin properties"() {
- given:
buildFile << """plugins {
id 'elasticsearch.stable-esplugin'
}
@@ -38,8 +34,27 @@ class StablePluginBuildPluginFuncTest extends AbstractGradleFuncTest {
name = 'myplugin'
description = 'test plugin'
}
+ repositories {
+ maven {
+ name = "local-test"
+ url = file("local-repo")
+ metadataSources {
+ artifact()
+ }
+ }
+ }
"""
+ // underlaying TestClusterPlugin and StandaloneRestIntegTestTask are not cc compatible
+ configurationCacheCompatible = false
+
+ def version = VersionProperties.elasticsearch
+ setupNamedComponentScanner(dir("local-repo/org/elasticsearch/elasticsearch-plugin-scanner/${version}/"), version)
+
+ }
+
+ def "can build stable plugin properties"() {
+ given:
when:
def result = gradleRunner(":pluginProperties").build()
def props = getPluginProperties()
@@ -62,32 +77,22 @@ class StablePluginBuildPluginFuncTest extends AbstractGradleFuncTest {
}
def "can scan and create named components file"() {
+ //THIS IS RUNNING A MOCK CONFIGURED IN setup()
given:
File jarFolder = new File(testProjectDir.root, "jars")
jarFolder.mkdirs()
- buildFile << """plugins {
- id 'elasticsearch.stable-esplugin'
- }
-
- version = '1.2.3'
-
- esplugin {
- name = 'myplugin'
- description = 'test plugin'
- }
-
+ buildFile << """
dependencies {
implementation files('${normalized(StableApiJarMocks.createPluginApiJar(jarFolder.toPath()).toAbsolutePath().toString())}')
implementation files('${normalized(StableApiJarMocks.createExtensibleApiJar(jarFolder.toPath()).toAbsolutePath().toString())}')
}
-
"""
file("src/main/java/org/acme/A.java") << """
package org.acme;
- import org.elasticsearch.plugin.api.NamedComponent;
+ import org.elasticsearch.plugin.NamedComponent;
import org.elasticsearch.plugin.scanner.test_classes.ExtensibleClass;
@NamedComponent( "componentA")
@@ -95,18 +100,16 @@ class StablePluginBuildPluginFuncTest extends AbstractGradleFuncTest {
}
"""
-
when:
- def result = gradleRunner(":assemble").build()
- Path namedComponents = file("build/generated-named-components/named_components.json").toPath();
- def map = new JsonSlurper().parse(namedComponents.toFile())
+ def result = gradleRunner(":assemble", "-i").build()
+
then:
result.task(":assemble").outcome == TaskOutcome.SUCCESS
-
- map == ["org.elasticsearch.plugin.scanner.test_classes.ExtensibleClass" : (["componentA" : "org.acme.A"]) ]
+ //we expect that a Fake namedcomponent scanner used in this test will be passed a filename to be created
+ File namedComponents = file("build/generated-named-components/named_components.json")
+ namedComponents.exists() == true
}
-
Map getPluginProperties() {
Path propsFile = file("build/generated-descriptor/stable-plugin-descriptor.properties").toPath();
Properties rawProps = new Properties()
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/NamedComponentScannerMock.java b/build-tools/src/main/java/org/elasticsearch/gradle/NamedComponentScannerMock.java
new file mode 100644
index 000000000000..cfd3ab566b33
--- /dev/null
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/NamedComponentScannerMock.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class NamedComponentScannerMock {
+ public static void main(String[] args) throws IOException {
+ // expect a file name to passed in as a parameter
+ // creating a file so that we can assert about this in a test
+ Path path = Path.of(args[0]);
+ Files.createDirectories(path.getParent());
+ Files.createFile(path);
+ }
+}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/GenerateNamedComponentsTask.java b/build-tools/src/main/java/org/elasticsearch/gradle/plugin/GenerateNamedComponentsTask.java
index 9a44a5214899..7945bce426cc 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/GenerateNamedComponentsTask.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/plugin/GenerateNamedComponentsTask.java
@@ -8,55 +8,60 @@
package org.elasticsearch.gradle.plugin;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.elasticsearch.gradle.plugin.scanner.ClassReaders;
-import org.elasticsearch.gradle.plugin.scanner.NamedComponentScanner;
+import org.elasticsearch.gradle.LoggedExec;
import org.gradle.api.DefaultTask;
-import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.ProjectLayout;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
-import org.gradle.api.model.ObjectFactory;
import org.gradle.api.tasks.CompileClasspath;
+import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile;
+import org.gradle.api.tasks.PathSensitive;
+import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.TaskAction;
-import org.gradle.workers.WorkAction;
-import org.gradle.workers.WorkParameters;
+import org.gradle.process.ExecOperations;
+import org.gradle.process.ExecResult;
import org.gradle.workers.WorkerExecutor;
-import org.objectweb.asm.ClassReader;
import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
import javax.inject.Inject;
public abstract class GenerateNamedComponentsTask extends DefaultTask {
private static final Logger LOGGER = Logging.getLogger(GenerateNamedComponentsTask.class);
+ private static final String NAMED_COMPONENTS_DIR = "generated-named-components/";
private static final String NAMED_COMPONENTS_FILE = "named_components.json";
+ private static final String NAMED_COMPONENTS_PATH = NAMED_COMPONENTS_DIR + NAMED_COMPONENTS_FILE;
private final WorkerExecutor workerExecutor;
+ private FileCollection pluginScannerClasspath;
private FileCollection classpath;
+ private ExecOperations execOperations;
+ private ProjectLayout projectLayout;
@Inject
- public GenerateNamedComponentsTask(WorkerExecutor workerExecutor, ObjectFactory objectFactory, ProjectLayout projectLayout) {
+ public GenerateNamedComponentsTask(WorkerExecutor workerExecutor, ExecOperations execOperations, ProjectLayout projectLayout) {
this.workerExecutor = workerExecutor;
- getOutputFile().convention(projectLayout.getBuildDirectory().file("generated-named-components/" + NAMED_COMPONENTS_FILE));
+ this.execOperations = execOperations;
+ this.projectLayout = projectLayout;
+
+ getOutputFile().convention(projectLayout.getBuildDirectory().file(NAMED_COMPONENTS_PATH));
}
@TaskAction
public void scanPluginClasses() {
- workerExecutor.noIsolation().submit(GenerateNamedComponentsAction.class, params -> {
- params.getClasspath().from(classpath);
- params.getOutputFile().set(getOutputFile());
+ File outputFile = projectLayout.getBuildDirectory().file(NAMED_COMPONENTS_PATH).get().getAsFile();
+
+ ExecResult execResult = LoggedExec.javaexec(execOperations, spec -> {
+ spec.classpath(pluginScannerClasspath.plus(getClasspath()).getAsPath());
+ spec.getMainClass().set("org.elasticsearch.plugin.scanner.NamedComponentScanner");
+ spec.args(outputFile);
+ spec.setErrorOutput(System.err);
+ spec.setStandardOutput(System.out);
});
+ execResult.assertNormalExitValue();
}
@OutputFile
@@ -71,37 +76,13 @@ public void setClasspath(FileCollection classpath) {
this.classpath = classpath;
}
- public abstract static class GenerateNamedComponentsAction implements WorkAction {
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @Override
- public void execute() {
- Set classpathFiles = getParameters().getClasspath().getFiles();
-
- List classReaders = ClassReaders.ofPaths(classpathFiles.stream().map(File::toPath)).collect(Collectors.toList());
-
- NamedComponentScanner namedComponentScanner = new NamedComponentScanner();
- Map> namedComponentsMap = namedComponentScanner.scanForNamedClasses(classReaders);
- writeToFile(namedComponentsMap);
- }
-
- private void writeToFile(Map> namedComponentsMap) {
- try {
- String json = OBJECT_MAPPER.writeValueAsString(namedComponentsMap);
- File file = getParameters().getOutputFile().getAsFile().get();
- Path of = Path.of(file.getAbsolutePath());
- Files.writeString(of, json);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
+ public void setPluginScannerClasspath(FileCollection pluginScannerClasspath) {
+ this.pluginScannerClasspath = pluginScannerClasspath;
}
- interface Parameters extends WorkParameters {
-
- ConfigurableFileCollection getClasspath();
-
- RegularFileProperty getOutputFile();
+ @InputFiles
+ @PathSensitive(PathSensitivity.RELATIVE)
+ public FileCollection getPluginScannerClasspath() {
+ return pluginScannerClasspath;
}
}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/StablePluginBuildPlugin.java b/build-tools/src/main/java/org/elasticsearch/gradle/plugin/StablePluginBuildPlugin.java
index 80f65ea26fa8..ef2d1631d560 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/StablePluginBuildPlugin.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/plugin/StablePluginBuildPlugin.java
@@ -8,9 +8,12 @@
package org.elasticsearch.gradle.plugin;
+import org.elasticsearch.gradle.VersionProperties;
import org.elasticsearch.gradle.util.GradleUtils;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.dsl.DependencyHandler;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFile;
import org.gradle.api.plugins.JavaPlugin;
@@ -33,12 +36,21 @@ public void apply(Project project) {
});
final var pluginNamedComponents = project.getTasks().register("pluginNamedComponents", GenerateNamedComponentsTask.class, t -> {
+
SourceSet mainSourceSet = GradleUtils.getJavaSourceSets(project).findByName(SourceSet.MAIN_SOURCE_SET_NAME);
FileCollection dependencyJars = project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME);
FileCollection compiledPluginClasses = mainSourceSet.getOutput().getClassesDirs();
FileCollection classPath = dependencyJars.plus(compiledPluginClasses);
t.setClasspath(classPath);
});
+ Configuration pluginScannerConfig = project.getConfigurations().create("pluginScannerConfig");
+ DependencyHandler dependencyHandler = project.getDependencies();
+ pluginScannerConfig.defaultDependencies(
+ deps -> deps.add(
+ dependencyHandler.create("org.elasticsearch:elasticsearch-plugin-scanner:" + VersionProperties.getElasticsearch())
+ )
+ );
+ pluginNamedComponents.configure(t -> { t.setPluginScannerClasspath(pluginScannerConfig); });
final var pluginExtension = project.getExtensions().getByType(PluginPropertiesExtension.class);
pluginExtension.getBundleSpec().from(pluginNamedComponents);
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/scanner/ClassReaders.java b/build-tools/src/main/java/org/elasticsearch/gradle/plugin/scanner/ClassReaders.java
deleted file mode 100644
index 40cc66c0a485..000000000000
--- a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/scanner/ClassReaders.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.gradle.plugin.scanner;
-
-import org.objectweb.asm.ClassReader;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.jar.JarFile;
-import java.util.stream.Stream;
-import java.util.zip.ZipFile;
-
-/**
- * A utility class containing methods to create streams of ASM's ClassReader
- *
- * @see ClassReader
- */
-public class ClassReaders {
- private static final String MODULE_INFO = "module-info.class";
-
- /**
- * This method must be used within a try-with-resources statement or similar
- * control structure.
- */
- public static Stream ofDirWithJars(String path) {
- if (path == null) {
- return Stream.empty();
- }
- Path dir = Paths.get(path);
- try {
- return ofPaths(Files.list(dir));
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- /**
- * This method must be used within a try-with-resources statement or similar
- * control structure.
- */
- public static Stream ofPaths(Stream list) {
- return list.filter(Files::exists).flatMap(p -> {
- if (p.toString().endsWith(".jar")) {
- return classesInJar(p);
- } else {
- return classesInPath(p);
- }
- });
- }
-
- private static Stream classesInJar(Path jar) {
- try {
- JarFile jf = new JarFile(jar.toFile(), true, ZipFile.OPEN_READ, Runtime.version());
-
- Stream classReaderStream = jf.versionedStream()
- .filter(e -> e.getName().endsWith(".class") && e.getName().equals(MODULE_INFO) == false)
- .map(e -> {
- try (InputStream is = jf.getInputStream(e)) {
- byte[] classBytes = is.readAllBytes();
- return new ClassReader(classBytes);
- } catch (IOException ex) {
- throw new UncheckedIOException(ex);
- }
- });
- return classReaderStream;
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private static Stream classesInPath(Path root) {
- try {
- Stream stream = Files.walk(root);
- return stream.filter(p -> p.toString().endsWith(".class"))
- .filter(p -> p.toString().endsWith("module-info.class") == false)
- .map(p -> {
- try (InputStream is = Files.newInputStream(p)) {
- byte[] classBytes = is.readAllBytes();
- return new ClassReader(classBytes);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- });
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/scanner/NamedComponentScanner.java b/build-tools/src/main/java/org/elasticsearch/gradle/plugin/scanner/NamedComponentScanner.java
deleted file mode 100644
index 86843c8f20ee..000000000000
--- a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/scanner/NamedComponentScanner.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.gradle.plugin.scanner;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.Opcodes;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-public class NamedComponentScanner {
-
- // returns a Map - extensible interface -> map{ namedName -> className }
- public Map> scanForNamedClasses(Collection classReaderStream) {
- // TODO I don't have access to stable-plugin-api here so I have to hardcode class descriptors
- ClassScanner extensibleClassScanner = new ClassScanner("Lorg/elasticsearch/plugin/api/Extensible;", (classname, map) -> {
- map.put(classname, classname);
- return null;
- });
- extensibleClassScanner.visit(classReaderStream.stream());
-
- ClassScanner namedComponentsScanner = new ClassScanner(
- "Lorg/elasticsearch/plugin/api/NamedComponent;"/*NamedComponent.class*/,
- (classname, map) -> new AnnotationVisitor(Opcodes.ASM9) {
- @Override
- public void visit(String key, Object value) {
- assert key.equals("value");
- assert value instanceof String;
- map.put(value.toString(), classname);
- }
- }
- );
-
- namedComponentsScanner.visit(classReaderStream.stream());
-
- Map> componentInfo = new HashMap<>();
- for (var e : namedComponentsScanner.getFoundClasses().entrySet()) {
- String name = e.getKey();
- String classnameWithSlashes = e.getValue();
- String extensibleClassnameWithSlashes = extensibleClassScanner.getFoundClasses().get(classnameWithSlashes);
- if (extensibleClassnameWithSlashes == null) {
- throw new RuntimeException(
- "Named component " + name + "(" + pathToClassName(classnameWithSlashes) + ") does not extend from an extensible class"
- );
- }
- var named = componentInfo.computeIfAbsent(pathToClassName(extensibleClassnameWithSlashes), k -> new HashMap<>());
- named.put(name, pathToClassName(classnameWithSlashes));
- }
- return componentInfo;
- }
-
- private String pathToClassName(String classWithSlashes) {
- return classWithSlashes.replace('/', '.');
- }
-}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java
index 0317b74bf0d3..f6705bdb62fa 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java
@@ -491,6 +491,13 @@ public List getAllReadinessPortURI() {
return nodes.stream().flatMap(each -> each.getAllReadinessPortURI().stream()).collect(Collectors.toList());
}
+ @Override
+ @Internal
+ public List getAllRemoteAccessPortURI() {
+ waitForAllConditions();
+ return nodes.stream().flatMap(each -> each.getAllRemoteAccessPortURI().stream()).collect(Collectors.toList());
+ }
+
public void waitForAllConditions() {
writeUnicastHostsFiles();
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java
index 85433e5a0772..fcb1af73e854 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java
@@ -164,6 +164,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
private final Path transportPortFile;
private final Path httpPortsFile;
private final Path readinessPortsFile;
+ private final Path remoteAccessPortsFile;
private final Path esOutputFile;
private final Path esInputFile;
private final Path tmpDir;
@@ -215,6 +216,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
transportPortFile = confPathLogs.resolve("transport.ports");
httpPortsFile = confPathLogs.resolve("http.ports");
readinessPortsFile = confPathLogs.resolve("readiness.ports");
+ remoteAccessPortsFile = confPathLogs.resolve("remote_cluster.ports");
esOutputFile = confPathLogs.resolve("es.out");
esInputFile = workingDir.resolve("es.in");
tmpDir = workingDir.resolve("tmp");
@@ -999,6 +1001,13 @@ public List getAllReadinessPortURI() {
return getReadinessPortInternal();
}
+ @Override
+ @Internal
+ public List getAllRemoteAccessPortURI() {
+ waitForAllConditions();
+ return getRemoteAccessPortInternal();
+ }
+
@Internal
public File getServerLog() {
return confPathLogs.resolve(defaultConfig.get("cluster.name") + "_server.json").toFile();
@@ -1022,6 +1031,9 @@ public synchronized void stop(boolean tailLogs) {
if (Files.exists(readinessPortsFile)) {
Files.delete(readinessPortsFile);
}
+ if (Files.exists(remoteAccessPortsFile)) {
+ Files.delete(remoteAccessPortsFile);
+ }
} catch (IOException e) {
throw new UncheckedIOException(e);
}
@@ -1047,6 +1059,9 @@ public synchronized void stop(boolean tailLogs) {
if (Files.exists(readinessPortsFile)) {
Files.delete(readinessPortsFile);
}
+ if (Files.exists(remoteAccessPortsFile)) {
+ Files.delete(remoteAccessPortsFile);
+ }
} catch (IOException e) {
throw new UncheckedIOException(e);
}
@@ -1519,6 +1534,14 @@ private List getReadinessPortInternal() {
}
}
+ private List getRemoteAccessPortInternal() {
+ try {
+ return readPortsFile(remoteAccessPortsFile);
+ } catch (IOException e) {
+ return new ArrayList<>();
+ }
+ }
+
private List readPortsFile(Path file) throws IOException {
try (Stream lines = Files.lines(file, StandardCharsets.UTF_8)) {
return lines.map(String::trim).collect(Collectors.toList());
@@ -1673,20 +1696,17 @@ public boolean isHttpSslEnabled() {
}
void configureHttpWait(WaitForHttpResource wait) {
- if (settings.containsKey("xpack.security.http.ssl.certificate_authorities")) {
- wait.setCertificateAuthorities(
- getConfigDir().resolve(settings.get("xpack.security.http.ssl.certificate_authorities").toString()).toFile()
- );
- }
if (settings.containsKey("xpack.security.http.ssl.certificate")) {
- wait.setCertificateAuthorities(getConfigDir().resolve(settings.get("xpack.security.http.ssl.certificate").toString()).toFile());
- }
- if (settings.containsKey("xpack.security.http.ssl.keystore.path")
- && settings.containsKey("xpack.security.http.ssl.certificate_authorities") == false) { // Can not set both trust stores and CA
- wait.setTrustStoreFile(getConfigDir().resolve(settings.get("xpack.security.http.ssl.keystore.path").toString()).toFile());
- }
- if (keystoreSettings.containsKey("xpack.security.http.ssl.keystore.secure_password")) {
- wait.setTrustStorePassword(keystoreSettings.get("xpack.security.http.ssl.keystore.secure_password").toString());
+ wait.setServerCertificate(getConfigDir().resolve(settings.get("xpack.security.http.ssl.certificate").toString()).toFile());
+ } else {
+ if (settings.containsKey("xpack.security.http.ssl.keystore.path")) {
+ wait.setServerKeystoreFile(
+ getConfigDir().resolve(settings.get("xpack.security.http.ssl.keystore.path").toString()).toFile()
+ );
+ }
+ if (keystoreSettings.containsKey("xpack.security.http.ssl.keystore.secure_password")) {
+ wait.setServerKeystorePassword(keystoreSettings.get("xpack.security.http.ssl.keystore.secure_password").toString());
+ }
}
}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/SslTrustResolver.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/SslTrustResolver.java
new file mode 100644
index 000000000000..4c2cbf4defb7
--- /dev/null
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/SslTrustResolver.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.testclusters;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+class SslTrustResolver {
+ private Set certificateAuthorities;
+ private File trustStoreFile;
+ private String trustStorePassword;
+ private File serverCertificate;
+ private File serverKeyStoreFile;
+ private String serverKeyStorePassword;
+
+ public void setCertificateAuthorities(File... certificateAuthorities) {
+ this.certificateAuthorities = new HashSet<>(Arrays.asList(certificateAuthorities));
+ }
+
+ public void setTrustStoreFile(File trustStoreFile) {
+ this.trustStoreFile = trustStoreFile;
+ }
+
+ public void setTrustStorePassword(String trustStorePassword) {
+ this.trustStorePassword = trustStorePassword;
+ }
+
+ public void setServerCertificate(File serverCertificate) {
+ this.serverCertificate = serverCertificate;
+ }
+
+ public void setServerKeystoreFile(File keyStoreFile) {
+ this.serverKeyStoreFile = keyStoreFile;
+ }
+
+ public void setServerKeystorePassword(String keyStorePassword) {
+ this.serverKeyStorePassword = keyStorePassword;
+ }
+
+ public SSLContext getSslContext() throws GeneralSecurityException, IOException {
+ final TrustManager[] trustManagers = buildTrustManagers();
+ if (trustManagers != null) {
+ return createSslContext(trustManagers);
+ } else {
+ return null;
+ }
+ }
+
+ TrustManager[] buildTrustManagers() throws GeneralSecurityException, IOException {
+ var configurationCount = Stream.of(
+ this.certificateAuthorities,
+ this.trustStoreFile,
+ this.serverCertificate,
+ this.serverKeyStoreFile
+ ).filter(Objects::nonNull).count();
+ if (configurationCount == 0) {
+ return null;
+ } else if (configurationCount > 1) {
+ throw new IllegalStateException(
+ String.format(
+ Locale.ROOT,
+ "Cannot specify more than one trust method (CA=%s, trustStore=%s, serverCert=%s, serverKeyStore=%s)",
+ certificateAuthorities,
+ trustStoreFile,
+ serverCertificate,
+ serverKeyStoreFile
+ )
+ );
+ }
+ if (this.certificateAuthorities != null) {
+ return getTrustManagers(buildTrustStoreFromCA(certificateAuthorities));
+ } else if (this.trustStoreFile != null) {
+ return getTrustManagers(readKeyStoreFromFile(trustStoreFile, trustStorePassword));
+ } else if (this.serverCertificate != null) {
+ return buildTrustManagerFromLeafCertificates(head(readCertificates(serverCertificate)));
+ } else if (this.serverKeyStoreFile != null) {
+ return buildTrustManagerFromLeafCertificates(readCertificatesFromKeystore(serverKeyStoreFile, serverKeyStorePassword));
+ } else {
+ // Cannot get here unless the code gets out of sync with the 'configurationCount == 0' check above
+ throw new IllegalStateException("Expected to configure trust, but all configuration values are null");
+ }
+ }
+
+ private SSLContext createSslContext(TrustManager[] trustManagers) throws GeneralSecurityException {
+ SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
+ sslContext.init(new KeyManager[0], trustManagers, new SecureRandom());
+ return sslContext;
+ }
+
+ private TrustManager[] getTrustManagers(KeyStore trustStore) throws GeneralSecurityException {
+ checkForTrustEntry(trustStore);
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ tmf.init(trustStore);
+ return tmf.getTrustManagers();
+ }
+
+ private void checkForTrustEntry(KeyStore trustStore) throws KeyStoreException {
+ Enumeration enumeration = trustStore.aliases();
+ while (enumeration.hasMoreElements()) {
+ if (trustStore.isCertificateEntry(enumeration.nextElement())) {
+ // found trusted cert entry
+ return;
+ }
+ }
+ throw new IllegalStateException("Trust-store does not contain any trusted certificate entries");
+ }
+
+ private static KeyStore buildTrustStoreFromCA(Set files) throws GeneralSecurityException, IOException {
+ final KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
+ store.load(null, null);
+ int counter = 0;
+ for (File ca : files) {
+ for (Certificate certificate : readCertificates(ca)) {
+ store.setCertificateEntry("cert-" + counter, certificate);
+ counter++;
+ }
+ }
+ return store;
+ }
+
+ private static TrustManager[] buildTrustManagerFromLeafCertificates(Collection extends Certificate> certificates) {
+ final Set trusted = certificates.stream()
+ .filter(X509Certificate.class::isInstance)
+ .map(X509Certificate.class::cast)
+ .collect(Collectors.toUnmodifiableSet());
+
+ var trustManager = new X509TrustManager() {
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ final X509Certificate leaf = chain[0];
+ if (trusted.contains(leaf) == false) {
+ throw new CertificateException("Untrusted leaf certificate: " + leaf.getSubjectX500Principal());
+ }
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ // This doesn't apply when trusting leaf certs, and is only really needed for server trust managers anyways
+ return new X509Certificate[0];
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ throw new CertificateException("This trust manager is for client use only and cannot trust other clients");
+ }
+
+ };
+ return new TrustManager[] { trustManager };
+ }
+
+ private static Collection readCertificatesFromKeystore(File file, String password) throws GeneralSecurityException,
+ IOException {
+ var keyStore = readKeyStoreFromFile(file, password);
+ final Set certificates = new HashSet<>(keyStore.size());
+ var enumeration = keyStore.aliases();
+ while (enumeration.hasMoreElements()) {
+ var alias = enumeration.nextElement();
+ if (keyStore.isKeyEntry(alias)) {
+ certificates.add(keyStore.getCertificate(alias));
+ }
+ }
+ return certificates;
+ }
+
+ private static KeyStore readKeyStoreFromFile(File file, String password) throws GeneralSecurityException, IOException {
+ KeyStore keyStore = KeyStore.getInstance(file.getName().endsWith(".jks") ? "JKS" : "PKCS12");
+ try (InputStream input = new FileInputStream(file)) {
+ keyStore.load(input, password == null ? null : password.toCharArray());
+ }
+ return keyStore;
+ }
+
+ private static Collection extends Certificate> readCertificates(File pemFile) throws GeneralSecurityException, IOException {
+ final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ try (InputStream input = new FileInputStream(pemFile)) {
+ return certFactory.generateCertificates(input);
+ }
+ }
+
+ private Collection extends Certificate> head(Collection extends Certificate> certificates) {
+ if (certificates.isEmpty()) {
+ return certificates;
+ } else {
+ return List.of(certificates.iterator().next());
+ }
+ }
+}
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/StandaloneRestIntegTestTask.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/StandaloneRestIntegTestTask.java
index 11ad0a29f5b8..3754f57dc378 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/StandaloneRestIntegTestTask.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/StandaloneRestIntegTestTask.java
@@ -9,8 +9,11 @@
import org.elasticsearch.gradle.FileSystemOperationsAware;
import org.elasticsearch.gradle.util.GradleUtils;
+import org.gradle.api.Task;
import org.gradle.api.provider.Provider;
import org.gradle.api.services.internal.BuildServiceRegistryInternal;
+import org.gradle.api.specs.NotSpec;
+import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.CacheableTask;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
@@ -40,6 +43,11 @@ public class StandaloneRestIntegTestTask extends Test implements TestClustersAwa
private boolean debugServer = false;
public StandaloneRestIntegTestTask() {
+ Spec taskSpec = t -> getProject().getTasks()
+ .withType(StandaloneRestIntegTestTask.class)
+ .stream()
+ .filter(task -> task != this)
+ .anyMatch(task -> Collections.disjoint(task.getClusters(), getClusters()) == false);
this.getOutputs()
.doNotCacheIf(
"Caching disabled for this task since it uses a cluster shared by other tasks",
@@ -49,13 +57,9 @@ public StandaloneRestIntegTestTask() {
* avoid any undesired behavior we simply disable the cache if we detect that this task uses a cluster shared between
* multiple tasks.
*/
- t -> getProject().getTasks()
- .withType(StandaloneRestIntegTestTask.class)
- .stream()
- .filter(task -> task != this)
- .anyMatch(task -> Collections.disjoint(task.getClusters(), getClusters()) == false)
+ taskSpec
);
-
+ this.getOutputs().upToDateWhen(new NotSpec(taskSpec));
this.getOutputs()
.doNotCacheIf(
"Caching disabled for this task since it is configured to preserve data directory",
@@ -67,11 +71,7 @@ public StandaloneRestIntegTestTask() {
@Option(option = "debug-server-jvm", description = "Enable debugging configuration, to allow attaching a debugger to elasticsearch.")
public void setDebugServer(boolean enabled) {
this.debugServer = enabled;
- }
-
- @Override
- public int getMaxParallelForks() {
- return 1;
+ systemProperty("tests.cluster.debug.enabled", Boolean.toString(enabled));
}
@Nested
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/TestClusterConfiguration.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/TestClusterConfiguration.java
index e6f0fd9965b6..b6ead59296eb 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/TestClusterConfiguration.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/TestClusterConfiguration.java
@@ -121,6 +121,8 @@ public interface TestClusterConfiguration {
List getAllReadinessPortURI();
+ List getAllRemoteAccessPortURI();
+
void stop(boolean tailLogs);
void setNameCustomization(Function nameSupplier);
diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/WaitForHttpResource.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/WaitForHttpResource.java
index 03368e74cdb7..550dd0fdcf8f 100644
--- a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/WaitForHttpResource.java
+++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/WaitForHttpResource.java
@@ -12,31 +12,20 @@
import org.gradle.api.logging.Logging;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.SecureRandom;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateFactory;
-import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
-import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManagerFactory;
/**
* A utility to wait for a specific HTTP resource to be available, optionally with customized TLS trusted CAs.
@@ -47,11 +36,10 @@ public class WaitForHttpResource {
private static final Logger logger = Logging.getLogger(WaitForHttpResource.class);
+ private final SslTrustResolver trustResolver;
+ private final URL url;
+
private Set validResponseCodes = Collections.singleton(200);
- private URL url;
- private Set certificateAuthorities;
- private File trustStoreFile;
- private String trustStorePassword;
private String username;
private String password;
@@ -61,6 +49,7 @@ public WaitForHttpResource(String protocol, String host, int numberOfNodes) thro
public WaitForHttpResource(URL url) {
this.url = url;
+ this.trustResolver = new SslTrustResolver();
}
public void setValidResponseCodes(int... validResponseCodes) {
@@ -71,15 +60,27 @@ public void setValidResponseCodes(int... validResponseCodes) {
}
public void setCertificateAuthorities(File... certificateAuthorities) {
- this.certificateAuthorities = new HashSet<>(Arrays.asList(certificateAuthorities));
+ trustResolver.setCertificateAuthorities(certificateAuthorities);
}
public void setTrustStoreFile(File trustStoreFile) {
- this.trustStoreFile = trustStoreFile;
+ trustResolver.setTrustStoreFile(trustStoreFile);
}
public void setTrustStorePassword(String trustStorePassword) {
- this.trustStorePassword = trustStorePassword;
+ trustResolver.setTrustStorePassword(trustStorePassword);
+ }
+
+ public void setServerCertificate(File serverCertificate) {
+ trustResolver.setServerCertificate(serverCertificate);
+ }
+
+ public void setServerKeystoreFile(File keyStoreFile) {
+ trustResolver.setServerKeystoreFile(keyStoreFile);
+ }
+
+ public void setServerKeystorePassword(String keyStorePassword) {
+ trustResolver.setServerKeystorePassword(keyStorePassword);
}
public void setUsername(String username) {
@@ -94,13 +95,7 @@ public boolean wait(int durationInMs) throws GeneralSecurityException, Interrupt
final long waitUntil = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(durationInMs);
final long sleep = Long.max(durationInMs / 10, 100);
- final SSLContext ssl;
- final KeyStore trustStore = buildTrustStore();
- if (trustStore != null) {
- ssl = createSslContext(trustStore);
- } else {
- ssl = null;
- }
+ final SSLContext ssl = trustResolver.getSslContext();
IOException failure = null;
while (true) {
try {
@@ -159,61 +154,4 @@ private void configureBasicAuth(HttpURLConnection connection) {
);
}
}
-
- KeyStore buildTrustStore() throws GeneralSecurityException, IOException {
- if (this.certificateAuthorities != null) {
- if (trustStoreFile != null) {
- throw new IllegalStateException("Cannot specify both truststore and CAs");
- }
- return buildTrustStoreFromCA();
- } else if (trustStoreFile != null) {
- return buildTrustStoreFromFile();
- } else {
- return null;
- }
- }
-
- private KeyStore buildTrustStoreFromFile() throws GeneralSecurityException, IOException {
- KeyStore keyStore = KeyStore.getInstance(trustStoreFile.getName().endsWith(".jks") ? "JKS" : "PKCS12");
- try (InputStream input = new FileInputStream(trustStoreFile)) {
- keyStore.load(input, trustStorePassword == null ? null : trustStorePassword.toCharArray());
- }
- return keyStore;
- }
-
- private KeyStore buildTrustStoreFromCA() throws GeneralSecurityException, IOException {
- final KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
- store.load(null, null);
- final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
- int counter = 0;
- for (File ca : certificateAuthorities) {
- try (InputStream input = new FileInputStream(ca)) {
- for (Certificate certificate : certFactory.generateCertificates(input)) {
- store.setCertificateEntry("cert-" + counter, certificate);
- counter++;
- }
- }
- }
- return store;
- }
-
- private SSLContext createSslContext(KeyStore trustStore) throws GeneralSecurityException {
- checkForTrustEntry(trustStore);
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- tmf.init(trustStore);
- SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
- sslContext.init(new KeyManager[0], tmf.getTrustManagers(), new SecureRandom());
- return sslContext;
- }
-
- private void checkForTrustEntry(KeyStore trustStore) throws KeyStoreException {
- Enumeration enumeration = trustStore.aliases();
- while (enumeration.hasMoreElements()) {
- if (trustStore.isCertificateEntry(enumeration.nextElement())) {
- // found trusted cert entry
- return;
- }
- }
- throw new IllegalStateException("Trust-store does not contain any trusted certificate entries");
- }
}
diff --git a/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/AnnotatedHierarchyVisitorSpec.groovy b/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/AnnotatedHierarchyVisitorSpec.groovy
deleted file mode 100644
index 732fa1c5e0ac..000000000000
--- a/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/AnnotatedHierarchyVisitorSpec.groovy
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1 you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.gradle.plugin.scanner
-
-import spock.lang.Specification
-
-import org.elasticsearch.plugin.api.NamedComponent
-import org.elasticsearch.plugin.scanner.test_classes.ExtensibleClass
-import org.elasticsearch.plugin.scanner.test_classes.ExtensibleInterface
-import org.elasticsearch.plugin.scanner.test_classes.ImplementingExtensible
-import org.elasticsearch.plugin.scanner.test_classes.SubClass
-import org.elasticsearch.plugin.api.Extensible
-import org.objectweb.asm.ClassReader
-import org.objectweb.asm.Type
-
-import java.nio.file.Files
-import java.nio.file.Path
-import java.nio.file.Paths
-
-class AnnotatedHierarchyVisitorSpec extends Specification {
- Set foundClasses
- AnnotatedHierarchyVisitor visitor
-
- def setup() {
- foundClasses = new HashSet<>()
- visitor =
- new AnnotatedHierarchyVisitor(
- Type.getDescriptor(Extensible.class), (className) -> {
- foundClasses.add(className)
- return null
- }
- )
- }
-
- def "empty result when no classes annotated"() {
- when:
- performScan(visitor, NamedComponent.class)
-
- then:
- foundClasses.empty
- }
-
- def "single class found when only one is annotated"() {
- when:
- performScan(visitor, ExtensibleClass.class)
-
- then:
- foundClasses == [classNameToPath(ExtensibleClass.class)] as Set
- }
-
- def "class extending an extensible is also found"() {
- when:
- performScan(visitor, ExtensibleClass.class, SubClass.class)
-
- then:
- foundClasses == [classNameToPath(ExtensibleClass.class)] as Set
- visitor.getClassHierarchy() == [(classNameToPath(ExtensibleClass.class)) : [classNameToPath(SubClass.class)] as Set]
- }
-
- def "interface extending an extensible is also found"() {
- when:
- performScan(visitor, ImplementingExtensible.class, ExtensibleInterface.class)
-
- then:
- foundClasses == [classNameToPath(ExtensibleInterface.class)] as Set
- visitor.getClassHierarchy() ==
- [(classNameToPath(ExtensibleInterface.class)) : [classNameToPath(ImplementingExtensible.class)] as Set]
- }
-
- private String classNameToPath(Class> clazz) {
- return clazz.getCanonicalName().replace(".", "/")
- }
-
- private void performScan(AnnotatedHierarchyVisitor classVisitor, Class>... classes) throws IOException, URISyntaxException {
- for (Class> clazz : classes) {
- String className = classNameToPath(clazz) + ".class"
- def stream = this.getClass().getClassLoader().getResourceAsStream(className)
- try (InputStream fileInputStream = stream) {
- ClassReader cr = new ClassReader(fileInputStream)
- cr.accept(classVisitor, 0)
- }
- }
- }
-
-}
diff --git a/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/ClassReadersSpec.groovy b/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/ClassReadersSpec.groovy
deleted file mode 100644
index bc448efd2d75..000000000000
--- a/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/ClassReadersSpec.groovy
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.gradle.plugin.scanner
-
-import spock.lang.Specification
-
-import org.elasticsearch.gradle.internal.test.InMemoryJavaCompiler;
-
-import org.elasticsearch.gradle.internal.test.JarUtils
-import org.hamcrest.Matchers
-import org.junit.Rule
-import org.junit.rules.TemporaryFolder
-import org.objectweb.asm.ClassReader
-
-import java.nio.file.Files
-import java.nio.file.Path
-import java.util.stream.Collectors
-import java.util.stream.Stream
-
-import static org.hamcrest.MatcherAssert.assertThat
-
-class ClassReadersSpec extends Specification {
- @Rule
- TemporaryFolder testProjectDir = new TemporaryFolder()
-
- private Path tmpDir() throws IOException {
- return testProjectDir.root.toPath();
- }
-
- def "module-info is not returned as a class from jar"() {
- when:
- final Path tmp = tmpDir();
- final Path dirWithJar = tmp.resolve("jars-dir");
- Files.createDirectories(dirWithJar);
- Path jar = dirWithJar.resolve("api.jar");
- JarUtils.createJarWithEntries(
- jar, Map.of(
- "module-info.class", InMemoryJavaCompiler.compile(
- "module-info", """
- module p {}
- """)
- )
- )
-
-
- then:
- try (Stream classReaderStream = ClassReaders.ofPaths(Stream.of(jar))) {
-
- assertThat(classReaderStream.collect(Collectors.toList()), Matchers.empty());
- }
- }
-
-
- def "two classes are returned in a stream from jar"() {
- when:
- final Path tmp = tmpDir();
- final Path dirWithJar = tmp.resolve("jars-dir");
- Files.createDirectories(dirWithJar);
- Path jar = dirWithJar.resolve("api.jar");
- JarUtils.createJarWithEntries(
- jar, Map.of(
- "p/A.class", InMemoryJavaCompiler.compile(
- "p.A", """
- package p;
- public class A {}
- """),
- "p/B.class", InMemoryJavaCompiler.compile(
- "p.B", """
- package p;
- public class B {}
- """)
- )
- );
-
-
- then:
- try (Stream classReaderStream = ClassReaders.ofPaths(Stream.of(jar))) {
- List collect = classReaderStream.map(cr -> cr.getClassName()).collect(Collectors.toList());
- assertThat(collect, Matchers.containsInAnyOrder("p/A", "p/B"));
- }
- }
-
-
- def "on a classpath jars and individual classes are returned"() {
- when:
- final Path tmp = tmpDir();
- final Path dirWithJar = tmp.resolve("jars-dir");
- Files.createDirectories(dirWithJar);
-
- Path jar = dirWithJar.resolve("a_b.jar");
- JarUtils.createJarWithEntries(
- jar, Map.of(
- "p/A.class", InMemoryJavaCompiler.compile(
- "p.A", """
- package p;
- public class A {}
- """),
- "p/B.class", InMemoryJavaCompiler.compile(
- "p.B", """
- package p;
- public class B {}
- """)
- )
- );
-
- Path jar2 = dirWithJar.resolve("c_d.jar");
- JarUtils.createJarWithEntries(
- jar2, Map.of(
- "p/C.class", InMemoryJavaCompiler.compile(
- "p.C", """
- package p;
- public class C {}
- """),
- "p/D.class", InMemoryJavaCompiler.compile(
- "p.D", """
- package p;
- public class D {}
- """)
- )
- );
-
- InMemoryJavaCompiler.compile(
- "p.E", """
- package p;
- public class E {}
- """
- );
- Files.write(
- tmp.resolve("E.class"), InMemoryJavaCompiler.compile(
- "p.E", """
- package p;
- public class E {}
- """)
- );
-
-
- then:
- try (Stream classReaderStream = ClassReaders.ofPaths(Stream.of(tmp, jar, jar2))) {
-
- List collect = classReaderStream.map(cr -> cr.getClassName()).collect(Collectors.toList());
- assertThat(collect, Matchers.containsInAnyOrder("p/A", "p/B", "p/C", "p/D", "p/E"));
- }
- }
-
- def "classes from multiple jars in a dir are returned"() {
- when:
- final Path tmp = tmpDir();
- final Path dirWithJar = tmp.resolve("jars-dir");
- Files.createDirectories(dirWithJar);
-
-
- Path jar = dirWithJar.resolve("a_b.jar");
- JarUtils.createJarWithEntries(
- jar, Map.of(
- "p/A.class", InMemoryJavaCompiler.compile(
- "p.A", """
- package p;
- public class A {}
- """),
- "p/B.class", InMemoryJavaCompiler.compile(
- "p.B", """
- package p;
- public class B {}
- """)
- )
- );
-
- Path jar2 = dirWithJar.resolve("c_d.jar");
- JarUtils.createJarWithEntries(
- jar2, Map.of(
- "p/C.class", InMemoryJavaCompiler.compile(
- "p.C", """
- package p;
- public class C {}
- """),
- "p/D.class", InMemoryJavaCompiler.compile(
- "p.D", """
- package p;
- public class D {}
- """)
- )
- );
-
- then:
- try (Stream classReaderStream = ClassReaders.ofDirWithJars(dirWithJar.toString())) {
- List collect = classReaderStream.map(cr -> cr.getClassName()).collect(Collectors.toList());
- assertThat(collect, Matchers.containsInAnyOrder("p/A", "p/B", "p/C", "p/D"));
- }
- }
-}
diff --git a/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/ClassScannerSpec.groovy b/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/ClassScannerSpec.groovy
deleted file mode 100644
index d03ae28576ae..000000000000
--- a/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/ClassScannerSpec.groovy
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.gradle.plugin.scanner
-
-import spock.lang.Specification
-
-import org.elasticsearch.plugin.api.Extensible
-import org.hamcrest.Matchers
-import org.objectweb.asm.ClassReader
-import org.objectweb.asm.Type
-
-import java.nio.file.Paths
-import java.util.stream.Collectors
-import java.util.stream.Stream
-
-import static org.hamcrest.MatcherAssert.assertThat
-
-class ClassScannerSpec extends Specification {
- static final System.Logger logger = System.getLogger(ClassScannerSpec.class.getName())
- def "class and interface hierarchy is scanned"() {
- given:
- def reader = new ClassScanner(
- Type.getDescriptor(Extensible.class), (classname, map) -> {
- map.put(classname, classname)
- return null
- }
- )
- Stream classReaderStream = ofClassPath()
- logger.log(System.Logger.Level.INFO, "classReaderStream size "+ofClassPath().collect(Collectors.toList()).size())
-
- when:
- reader.visit(classReaderStream);
- Map extensibleClasses = reader.getFoundClasses()
-
- then:
- assertThat(
- extensibleClasses,
- Matchers.allOf(
- Matchers.hasEntry(
- "org/elasticsearch/plugin/scanner/test_classes/ExtensibleClass",
- "org/elasticsearch/plugin/scanner/test_classes/ExtensibleClass"
- ),
- Matchers.hasEntry(
- "org/elasticsearch/plugin/scanner/test_classes/ImplementingExtensible",
- "org/elasticsearch/plugin/scanner/test_classes/ExtensibleInterface"
- ),
- Matchers.hasEntry(
- "org/elasticsearch/plugin/scanner/test_classes/SubClass",
- "org/elasticsearch/plugin/scanner/test_classes/ExtensibleClass"
- )
- )
- );
- }
-
- static Stream ofClassPath() throws IOException {
- String classpath = System.getProperty("java.class.path");
- logger.log(System.Logger.Level.INFO, "classpath "+classpath);
- return ofClassPath(classpath);
- }
-
- static Stream ofClassPath(String classpath) {
- if (classpath != null && classpath.equals("") == false) {// todo when do we set cp to "" ?
- def classpathSeparator = System.getProperty("path.separator")
- logger.log(System.Logger.Level.INFO, "classpathSeparator "+classpathSeparator);
-
- String[] pathelements = classpath.split(classpathSeparator);
- return ClassReaders.ofPaths(Arrays.stream(pathelements).map(Paths::get));
- }
- return Stream.empty();
- }
-
-}
diff --git a/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/NamedComponentScannerSpec.groovy b/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/NamedComponentScannerSpec.groovy
deleted file mode 100644
index fc48ae6a0ad6..000000000000
--- a/build-tools/src/test/groovy/org/elasticsearch/gradle/plugin/scanner/NamedComponentScannerSpec.groovy
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.plugin.scanner
-
-import net.bytebuddy.ByteBuddy
-import net.bytebuddy.dynamic.DynamicType
-import spock.lang.Specification
-
-import org.elasticsearch.gradle.internal.test.InMemoryJavaCompiler
-import org.elasticsearch.gradle.internal.test.JarUtils
-import org.elasticsearch.gradle.internal.test.StableApiJarMocks
-import org.elasticsearch.gradle.plugin.scanner.ClassReaders
-import org.elasticsearch.gradle.plugin.scanner.NamedComponentScanner
-import org.elasticsearch.plugin.scanner.test_classes.ExtensibleClass
-import org.elasticsearch.plugin.scanner.test_classes.ExtensibleInterface
-import org.elasticsearch.plugin.scanner.test_classes.TestNamedComponent
-import org.elasticsearch.plugin.api.Extensible
-import org.elasticsearch.plugin.api.NamedComponent
-import org.junit.Rule
-import org.junit.rules.TemporaryFolder
-import org.objectweb.asm.ClassReader
-
-import java.nio.file.Files
-import java.nio.file.Path
-import java.nio.file.Paths
-import java.util.stream.Collectors
-
-import static org.hamcrest.MatcherAssert.assertThat
-import static org.hamcrest.Matchers.equalTo
-
-class NamedComponentScannerSpec extends Specification {
- @Rule
- TemporaryFolder testProjectDir = new TemporaryFolder()
-
- private Path tmpDir() throws IOException {
- return testProjectDir.root.toPath();
- }
-
- NamedComponentScanner namedComponentScanner = new NamedComponentScanner();
-
- def "named component is found when single class provided"() {
- when:
- Map> namedComponents = namedComponentScanner.scanForNamedClasses(
- classReaderStream(TestNamedComponent.class, ExtensibleInterface.class)
- )
-
- then:
- assertThat(
- namedComponents,
- equalTo(
- Map.of(
- ExtensibleInterface.class.getCanonicalName(),
- Map.of("test_named_component", TestNamedComponent.class.getCanonicalName())
- )
- )
- )
-
- }
-
- def "named components are found when single jar provided"() {
- given:
- final Path tmp = tmpDir();
- final Path dirWithJar = tmp.resolve("jars-dir");
- Files.createDirectories(dirWithJar);
- Path jar = dirWithJar.resolve("plugin.jar");
- JarUtils.createJarWithEntries(
- jar, Map.of(
- "p/A.class", InMemoryJavaCompiler.compile(
- "p.A", """
- package p;
- import org.elasticsearch.plugin.api.*;
- import org.elasticsearch.plugin.scanner.test_classes.*;
- @NamedComponent("a_component")
- public class A extends ExtensibleClass {}
- """
- ), "p/B.class", InMemoryJavaCompiler.compile(
- "p.B", """
- package p;
- import org.elasticsearch.plugin.api.*;
- import org.elasticsearch.plugin.scanner.test_classes.*;
- @NamedComponent("b_component")
- public class B implements ExtensibleInterface{}
- """
- )
- )
- );
- StableApiJarMocks.createPluginApiJar(dirWithJar);
- StableApiJarMocks.createExtensibleApiJar(dirWithJar);//for instance analysis api
-
-
- Collection classReaderStream = ClassReaders.ofDirWithJars(dirWithJar.toString()).collect(Collectors.toList())
-
- when:
- Map> namedComponents = namedComponentScanner.scanForNamedClasses(classReaderStream);
-
- then:
- assertThat(
- namedComponents,
- equalTo(
- Map.of(
- ExtensibleClass.class.getCanonicalName(),
- Map.of("a_component", "p.A"),
- ExtensibleInterface.class.getCanonicalName(),
- Map.of("b_component", "p.B")
- )
- )
- );
- }
-
- def "named components can extend common super class"() {
- given:
- Map sources = Map.of(
- "p.CustomExtensibleInterface",
- """
- package p;
- import org.elasticsearch.plugin.api.*;
- import org.elasticsearch.plugin.scanner.test_classes.*;
- public interface CustomExtensibleInterface extends ExtensibleInterface {}
- """,
- // note that this class implements a custom interface
- "p.CustomExtensibleClass",
- """
- package p;
- import org.elasticsearch.plugin.api.*;
- import org.elasticsearch.plugin.scanner.test_classes.*;
- public class CustomExtensibleClass implements CustomExtensibleInterface {}
- """,
- "p.A",
- """
- package p;
- import org.elasticsearch.plugin.api.*;
- import org.elasticsearch.plugin.scanner.test_classes.*;
- @NamedComponent("a_component")
- public class A extends CustomExtensibleClass {}
- """,
- "p.B",
- """
- package p;
- import org.elasticsearch.plugin.api.*;
- import org.elasticsearch.plugin.scanner.test_classes.*;
- @NamedComponent("b_component")
- public class B implements CustomExtensibleInterface{}
- """
- );
- var classToBytes = InMemoryJavaCompiler.compile(sources);
-
- Map jarEntries = new HashMap<>();
- jarEntries.put("p/CustomExtensibleInterface.class", classToBytes.get("p.CustomExtensibleInterface"));
- jarEntries.put("p/CustomExtensibleClass.class", classToBytes.get("p.CustomExtensibleClass"));
- jarEntries.put("p/A.class", classToBytes.get("p.A"));
- jarEntries.put("p/B.class", classToBytes.get("p.B"));
-
- final Path tmp = tmpDir();
- final Path dirWithJar = tmp.resolve("jars-dir");
- Files.createDirectories(dirWithJar);
- Path jar = dirWithJar.resolve("plugin.jar");
- JarUtils.createJarWithEntries(jar, jarEntries);
-
- StableApiJarMocks.createPluginApiJar(dirWithJar)
- StableApiJarMocks.createExtensibleApiJar(dirWithJar);//for instance analysis api
-
- Collection classReaderStream = ClassReaders.ofDirWithJars(dirWithJar.toString()).collect(Collectors.toList())
-
- when:
- Map> namedComponents = namedComponentScanner.scanForNamedClasses(classReaderStream);
-
- then:
- assertThat(
- namedComponents,
- equalTo(
- Map.of(
- ExtensibleInterface.class.getCanonicalName(),
- Map.of(
- "a_component", "p.A",
- "b_component", "p.B"
- )
- )
- )
- );
- }
-
-
-
- private Collection classReaderStream(Class>... classes) {
- try {
- return Arrays.stream(classes).map(
- clazz -> {
- String className = classNameToPath(clazz) + ".class";
- def stream = this.getClass().getClassLoader().getResourceAsStream(className)
- try (InputStream is = stream) {
- byte[] classBytes = is.readAllBytes();
- ClassReader classReader = new ClassReader(classBytes);
- return classReader;
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
- ).collect(Collectors.toList())
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- }
-
- private String classNameToPath(Class> clazz) {
- return clazz.getCanonicalName().replace(".", "/");
- }
-
-
-}
diff --git a/build-tools/src/test/groovy/org/elasticsearch/gradle/testclusters/SslTrustResolverSpec.groovy b/build-tools/src/test/groovy/org/elasticsearch/gradle/testclusters/SslTrustResolverSpec.groovy
new file mode 100644
index 000000000000..f1a87cd9ff26
--- /dev/null
+++ b/build-tools/src/test/groovy/org/elasticsearch/gradle/testclusters/SslTrustResolverSpec.groovy
@@ -0,0 +1,117 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.testclusters
+
+import spock.lang.Specification
+
+import java.nio.file.Paths
+import java.security.cert.Certificate
+import java.security.cert.CertificateException
+import java.security.cert.CertificateFactory
+import javax.net.ssl.TrustManager
+import javax.net.ssl.X509TrustManager
+
+class SslTrustResolverSpec extends Specification {
+
+ def "build trust manager from trust store file"() {
+ given:
+ SslTrustResolver resolver = new SslTrustResolver()
+ URL ca = getClass().getResource("/ca.p12")
+
+ when:
+ resolver.setTrustStoreFile(Paths.get(ca.toURI()).toFile())
+ resolver.setTrustStorePassword("password")
+ final TrustManager[] trustManagers = resolver.buildTrustManagers()
+
+ then:
+ trustManagers.length == 1
+ trustManagers[0] instanceof X509TrustManager
+ def issuers = ((X509TrustManager) trustManagers[0]).getAcceptedIssuers()
+ issuers.length == 1
+ issuers[0].subjectX500Principal.toString() == 'CN=Elastic Certificate Tool Autogenerated CA'
+ }
+
+ def "build trust manager from certificate authorities file"() {
+ given:
+ SslTrustResolver resolver = new SslTrustResolver()
+ URL ca = getClass().getResource("/ca.pem")
+
+ when:
+ resolver.setCertificateAuthorities(Paths.get(ca.toURI()).toFile())
+ final TrustManager[] trustManagers = resolver.buildTrustManagers()
+
+ then:
+ trustManagers.length == 1
+ trustManagers[0] instanceof X509TrustManager
+ def issuers = ((X509TrustManager) trustManagers[0]).getAcceptedIssuers()
+ issuers.length == 1
+ issuers[0].subjectX500Principal.toString() == 'CN=Elastic Certificate Tool Autogenerated CA'
+ }
+
+ def "build trust manager from keystore file"() {
+ given:
+ SslTrustResolver resolver = new SslTrustResolver()
+ URL ks = getClass().getResource("/server.p12")
+ Certificate[] serverChain = readCertificates("/server.chain")
+ Certificate[] issuingChain = readCertificates("/issuing.pem")
+ Certificate[] altChain = readCertificates("/ca.pem")
+
+ when:
+ resolver.setServerKeystoreFile(Paths.get(ks.toURI()).toFile())
+ resolver.setServerKeystorePassword("password")
+ final TrustManager[] trustManagers = resolver.buildTrustManagers()
+
+ then:
+ trustManagers.length == 1
+ trustManagers[0] instanceof X509TrustManager
+
+ def trustManager = (X509TrustManager) trustManagers[0]
+ isTrusted(trustManager, serverChain) == true;
+ isTrusted(trustManager, issuingChain) == false;
+ isTrusted(trustManager, altChain) == false;
+ }
+
+ def "build trust manager from server certificate file"() {
+ given:
+ SslTrustResolver resolver = new SslTrustResolver()
+ URL chain = getClass().getResource("/server.chain")
+ Certificate[] serverChain = readCertificates("/server.chain")
+ Certificate[] issuingChain = readCertificates("/issuing.pem")
+ Certificate[] altChain = readCertificates("/ca.pem")
+
+ when:
+ resolver.setServerCertificate(Paths.get(chain.toURI()).toFile())
+ final TrustManager[] trustManagers = resolver.buildTrustManagers()
+
+ then:
+ trustManagers.length == 1
+ trustManagers[0] instanceof X509TrustManager
+
+ def trustManager = (X509TrustManager) trustManagers[0]
+ isTrusted(trustManager, serverChain) == true;
+ isTrusted(trustManager, issuingChain) == false;
+ isTrusted(trustManager, altChain) == false;
+ }
+
+ private Certificate[] readCertificates(String resourceName) {
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509")
+ return getClass().getResource(resourceName).withInputStream { stream ->
+ certificateFactory.generateCertificates(stream)
+ }
+ }
+
+ private boolean isTrusted(X509TrustManager trustManager, Certificate[] certificateChain) {
+ try {
+ trustManager.checkServerTrusted(((java.security.cert.X509Certificate[]) certificateChain), "RSA");
+ return true;
+ } catch(CertificateException ignore) {
+ return false;
+ }
+ }
+}
diff --git a/build-tools/src/test/groovy/org/elasticsearch/gradle/testclusters/WaitForHttpResourceSpec.groovy b/build-tools/src/test/groovy/org/elasticsearch/gradle/testclusters/WaitForHttpResourceSpec.groovy
deleted file mode 100644
index ffa8b569e3e9..000000000000
--- a/build-tools/src/test/groovy/org/elasticsearch/gradle/testclusters/WaitForHttpResourceSpec.groovy
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.gradle.testclusters
-
-import spock.lang.Specification
-
-import java.nio.file.Paths
-import java.security.KeyStore
-import java.security.cert.Certificate
-import java.security.cert.X509Certificate
-
-class WaitForHttpResourceSpec extends Specification {
-
- def "build trust store from trust store file"() {
- given:
- WaitForHttpResource http = new WaitForHttpResource(new URL("https://localhost/"))
- URL ca = getClass().getResource("/ca.p12")
-
- when:
- http.setTrustStoreFile(Paths.get(ca.toURI()).toFile())
- http.setTrustStorePassword("password")
- final KeyStore store = http.buildTrustStore()
- final Certificate certificate = store.getCertificate("ca")
-
- then:
- certificate != null
- certificate instanceof X509Certificate
- certificate.subjectX500Principal.toString() == 'CN=Elastic Certificate Tool Autogenerated CA'
- }
-
- def "build trust store from certificate authorities file"() {
- given:
- WaitForHttpResource http = new WaitForHttpResource(new URL("https://localhost/"))
- URL ca = getClass().getResource("/ca.pem")
-
- when:
- http.setCertificateAuthorities(Paths.get(ca.toURI()).toFile())
- KeyStore store = http.buildTrustStore()
- Certificate certificate = store.getCertificate("cert-0")
-
- then:
- certificate != null
- certificate instanceof X509Certificate
- certificate.subjectX500Principal.toString() == "CN=Elastic Certificate Tool Autogenerated CA"
- }
-}
diff --git a/build-tools/src/test/resources/issuing.p12 b/build-tools/src/test/resources/issuing.p12
new file mode 100644
index 000000000000..85118080aacd
Binary files /dev/null and b/build-tools/src/test/resources/issuing.p12 differ
diff --git a/build-tools/src/test/resources/issuing.pem b/build-tools/src/test/resources/issuing.pem
new file mode 100644
index 000000000000..49d1f9d95052
--- /dev/null
+++ b/build-tools/src/test/resources/issuing.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIICBjCCAW+gAwIBAgIUY8ypR5RTcCCoHom3Mvq3Cl4MWggwDQYJKoZIhvcNAQEL
+BQAwFTETMBEGA1UEAxMKSXNzdWluZyBDQTAeFw0yMzAxMDQwNjE3MDlaFw0zNjA5
+MTIwNjE3MDlaMBUxEzARBgNVBAMTCklzc3VpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEB
+BQADgY0AMIGJAoGBAKta2elMeFOjCoMaaT3XiQh4bcs8FfG2x96puWu8vy184qBp
+26JDizlpJROx8WmE1hZEoexlagltYZ9bQrNyxrXDFbFw6Ccg+0o8RZmLzJE+v5Th
+vE2ezzGcDDlb+gvFKTmdTiunI1G6y+5qe03YTtJniT5wOSUMOahRf2qc4p/DAgMB
+AAGjUzBRMB0GA1UdDgQWBBSC0hVfH3oNVV5ZPM0fxfMCfVTK0DAfBgNVHSMEGDAW
+gBSC0hVfH3oNVV5ZPM0fxfMCfVTK0DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4GBAFKZ7KV9XP5Q5baRk3wgvpejBEpLf438icvpxU++WU8neX1vc9qK
+ZNbivyaVG1JthobV9A/lS9pNSlJtGvTjpp8Aq2uM0V2LDaLeNQ/sMrKWpsvYZkKU
+kIkbrBgUHm/zHfuhRhS3X1siKa7muH+T3bH//Vc3x6lO8nfX1iz6XHcy
+-----END CERTIFICATE-----
diff --git a/build-tools/src/test/resources/server.chain b/build-tools/src/test/resources/server.chain
new file mode 100644
index 000000000000..07da615d580a
--- /dev/null
+++ b/build-tools/src/test/resources/server.chain
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIICDjCCAXegAwIBAgIVAO17tpEpOGKg8EH4BIKpYMlPkwtLMA0GCSqGSIb3DQEB
+CwUAMBUxEzARBgNVBAMTCklzc3VpbmcgQ0EwHhcNMjMwMTA0MDYxOTMyWhcNMzYw
+OTEyMDYxOTMyWjARMQ8wDQYDVQQDEwZzZXJ2ZXIwgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBAMQkTJQP3ust+YERFxqjm6Ck+w4ql9Dc7L87mkdJhY7kVrv8hVb5
+UB+UjNYpO/hBKKE3sAqenuni/XfNRHbmVq+c3xNgJxkr9JGOzIf76TBDEORlVe99
+uViqQb+WwGcO+qY7NN5WcNKd8W779Y6CENPlMiyRzdEmgf4AnwmxOTs7AgMBAAGj
+XjBcMB0GA1UdDgQWBBRj8cuUKTNtKJvhy7mMganBGg5RCjAfBgNVHSMEGDAWgBSC
+0hVfH3oNVV5ZPM0fxfMCfVTK0DAPBgNVHREECDAGhwR/AAABMAkGA1UdEwQCMAAw
+DQYJKoZIhvcNAQELBQADgYEASox5Lk7otOz85+G0qQOJyortpOTyxZgJJ5RI3RO5
+7d59vMabbktdj+750fL50G07oeACip6kyglQqAE+I6UPQDepTpvoEv3OxDvilehX
+HCq2f0rKFnFB8ueT9Qx6tzAz1Luz764KU4AzP4rBcJicMZW1cmGsXD3/TDDEE+qJ
+YEY=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICBjCCAW+gAwIBAgIUY8ypR5RTcCCoHom3Mvq3Cl4MWggwDQYJKoZIhvcNAQEL
+BQAwFTETMBEGA1UEAxMKSXNzdWluZyBDQTAeFw0yMzAxMDQwNjE3MDlaFw0zNjA5
+MTIwNjE3MDlaMBUxEzARBgNVBAMTCklzc3VpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEB
+BQADgY0AMIGJAoGBAKta2elMeFOjCoMaaT3XiQh4bcs8FfG2x96puWu8vy184qBp
+26JDizlpJROx8WmE1hZEoexlagltYZ9bQrNyxrXDFbFw6Ccg+0o8RZmLzJE+v5Th
+vE2ezzGcDDlb+gvFKTmdTiunI1G6y+5qe03YTtJniT5wOSUMOahRf2qc4p/DAgMB
+AAGjUzBRMB0GA1UdDgQWBBSC0hVfH3oNVV5ZPM0fxfMCfVTK0DAfBgNVHSMEGDAW
+gBSC0hVfH3oNVV5ZPM0fxfMCfVTK0DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4GBAFKZ7KV9XP5Q5baRk3wgvpejBEpLf438icvpxU++WU8neX1vc9qK
+ZNbivyaVG1JthobV9A/lS9pNSlJtGvTjpp8Aq2uM0V2LDaLeNQ/sMrKWpsvYZkKU
+kIkbrBgUHm/zHfuhRhS3X1siKa7muH+T3bH//Vc3x6lO8nfX1iz6XHcy
+-----END CERTIFICATE-----
diff --git a/build-tools/src/test/resources/server.p12 b/build-tools/src/test/resources/server.p12
new file mode 100644
index 000000000000..95674e0fe78e
Binary files /dev/null and b/build-tools/src/test/resources/server.p12 differ
diff --git a/build-tools/src/testFixtures/groovy/org/elasticsearch/gradle/fixtures/TestClasspathUtils.groovy b/build-tools/src/testFixtures/groovy/org/elasticsearch/gradle/fixtures/TestClasspathUtils.groovy
index 94e012c95021..e41ace83b75b 100644
--- a/build-tools/src/testFixtures/groovy/org/elasticsearch/gradle/fixtures/TestClasspathUtils.groovy
+++ b/build-tools/src/testFixtures/groovy/org/elasticsearch/gradle/fixtures/TestClasspathUtils.groovy
@@ -16,17 +16,40 @@ import net.bytebuddy.dynamic.DynamicType
import net.bytebuddy.implementation.ExceptionMethod
import net.bytebuddy.implementation.FixedValue
import net.bytebuddy.implementation.Implementation
+import net.bytebuddy.implementation.MethodDelegation
+
+import org.elasticsearch.gradle.NamedComponentScannerMock
import static org.junit.Assert.fail
class TestClasspathUtils {
+ // we cannot access real NamedComponentScanner in libs:plugin-api-scanner so we create a fake class
+ static void setupNamedComponentScanner(File projectRoot, String version) {
+ def value = MethodDelegation.to(NamedComponentScannerMock.class)
+
+ DynamicType.Unloaded> dynamicType = new ByteBuddy().subclass(Object.class)
+ .name("org.elasticsearch.plugin.scanner.NamedComponentScanner")
+ .defineMethod("main", void.class, Visibility.PUBLIC, Ownership.STATIC)
+ .withParameters(String[].class)
+ .intercept(value)
+ .make()
+ .include(new ByteBuddy().redefine(NamedComponentScannerMock.class).make())
+
+ try {
+ dynamicType.toJar(targetFile(projectRoot, "elasticsearch-plugin-scanner", version))
+ } catch (IOException e) {
+ e.printStackTrace()
+ fail("Cannot setup jdk jar hell classpath")
+ }
+ }
+
static void setupJarHellJar(File projectRoot) {
- generateJdkJarHellCheck(projectRoot, "org.elasticsearch.jdk.JarHell", "current", FixedValue.value(TypeDescription.VOID))
+ generateJarWithClass(projectRoot, "org.elasticsearch.jdk.JarHell","elasticsearch-core", "current", FixedValue.value(TypeDescription.VOID))
}
static void setupJarHellJar(File projectRoot, String version) {
- generateJdkJarHellCheck(projectRoot, "org.elasticsearch.jdk.JarHell", version, FixedValue.value(TypeDescription.VOID))
+ generateJarWithClass(projectRoot, "org.elasticsearch.jdk.JarHell", "elasticsearch-core", version, FixedValue.value(TypeDescription.VOID))
}
static void setupJarJdkClasspath(File projectRoot) {
@@ -39,26 +62,28 @@ class TestClasspathUtils {
}
private static void generateJdkJarHellCheck(File targetDir, String className, Implementation mainImplementation) {
- generateJdkJarHellCheck(targetDir, className, "current", mainImplementation)
+ generateJarWithClass(targetDir, className, "elasticsearch-core", "current", mainImplementation)
}
- private static void generateJdkJarHellCheck(File targetDir, String className, String version, Implementation mainImplementation) {
+
+ private static void generateJarWithClass(File targetDir, String className, String artifactName, String version, Implementation mainImplementation) {
DynamicType.Unloaded> dynamicType = new ByteBuddy().subclass(Object.class)
.name(className)
.defineMethod("main", void.class, Visibility.PUBLIC, Ownership.STATIC)
.withParameters(String[].class)
.intercept(mainImplementation)
.make()
+
try {
- dynamicType.toJar(targetFile(targetDir, version))
+ dynamicType.toJar(targetFile(targetDir, artifactName, version))
} catch (IOException e) {
e.printStackTrace()
fail("Cannot setup jdk jar hell classpath")
}
}
- private static File targetFile(File projectRoot, String version) {
- File targetFile = new File(projectRoot, "elasticsearch-core-${version}.jar")
+ private static File targetFile(File projectRoot, String artifactName, String version) {
+ File targetFile = new File(projectRoot, "${artifactName}-${version}.jar")
println "targetFile = $targetFile"
targetFile.getParentFile().mkdirs()
diff --git a/build-tools/src/testFixtures/java/org/elasticsearch/gradle/internal/test/StableApiJarMocks.java b/build-tools/src/testFixtures/java/org/elasticsearch/gradle/internal/test/StableApiJarMocks.java
index d5d45807f062..a625fef61903 100644
--- a/build-tools/src/testFixtures/java/org/elasticsearch/gradle/internal/test/StableApiJarMocks.java
+++ b/build-tools/src/testFixtures/java/org/elasticsearch/gradle/internal/test/StableApiJarMocks.java
@@ -11,8 +11,8 @@
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
-import org.elasticsearch.plugin.api.Extensible;
-import org.elasticsearch.plugin.api.NamedComponent;
+import org.elasticsearch.plugin.Extensible;
+import org.elasticsearch.plugin.NamedComponent;
import org.elasticsearch.plugin.scanner.test_classes.ExtensibleClass;
import org.elasticsearch.plugin.scanner.test_classes.ExtensibleInterface;
diff --git a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/Extensible.java b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/Extensible.java
new file mode 100644
index 000000000000..34984b90d3c7
--- /dev/null
+++ b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/Extensible.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+package org.elasticsearch.plugin;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value = { TYPE })
+public @interface Extensible {
+}
diff --git a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/NamedComponent.java b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/NamedComponent.java
new file mode 100644
index 000000000000..53b195313ecc
--- /dev/null
+++ b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/NamedComponent.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.plugin;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE })
+public @interface NamedComponent {
+ /**
+ * The name used for registration and lookup
+ * @return a name
+ */
+ String value();
+}
diff --git a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/api/Extensible.java b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/api/Extensible.java
deleted file mode 100644
index 1a1f10f11c3e..000000000000
--- a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/api/Extensible.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-package org.elasticsearch.plugin.api;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.TYPE;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(value = { TYPE })
-public @interface Extensible {
-}
diff --git a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/api/NamedComponent.java b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/api/NamedComponent.java
deleted file mode 100644
index 65a1a0d46abd..000000000000
--- a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/api/NamedComponent.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.plugin.api;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.TYPE })
-public @interface NamedComponent {
- /**
- * The name used for registration and lookup
- * @return a name
- */
- String value();
-}
diff --git a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/ExtensibleClass.java b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/ExtensibleClass.java
index b76f6dd93f9d..50ea17993d7c 100644
--- a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/ExtensibleClass.java
+++ b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/ExtensibleClass.java
@@ -8,7 +8,7 @@
package org.elasticsearch.plugin.scanner.test_classes;
-import org.elasticsearch.plugin.api.Extensible;
+import org.elasticsearch.plugin.Extensible;
@Extensible
public class ExtensibleClass {}
diff --git a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/ExtensibleInterface.java b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/ExtensibleInterface.java
index c630bf216883..784136bf6f5a 100644
--- a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/ExtensibleInterface.java
+++ b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/ExtensibleInterface.java
@@ -8,7 +8,7 @@
package org.elasticsearch.plugin.scanner.test_classes;
-import org.elasticsearch.plugin.api.Extensible;
+import org.elasticsearch.plugin.Extensible;
@Extensible
public interface ExtensibleInterface {}
diff --git a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/TestNamedComponent.java b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/TestNamedComponent.java
index a98e6b08a797..9a6b9b648e3a 100644
--- a/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/TestNamedComponent.java
+++ b/build-tools/src/testFixtures/java/org/elasticsearch/plugin/scanner/test_classes/TestNamedComponent.java
@@ -8,7 +8,9 @@
package org.elasticsearch.plugin.scanner.test_classes;
-@org.elasticsearch.plugin.api.NamedComponent("test_named_component")
+import org.elasticsearch.plugin.NamedComponent;
+
+@NamedComponent("test_named_component")
public class TestNamedComponent implements ExtensibleInterface {
}
diff --git a/client/rest-high-level/build.gradle b/client/rest-high-level/build.gradle
index be2be6f0461e..500870fb593c 100644
--- a/client/rest-high-level/build.gradle
+++ b/client/rest-high-level/build.gradle
@@ -25,7 +25,6 @@ restResources {
dependencies {
api project(':modules:mapper-extras')
api project(':modules:parent-join')
- api project(':modules:aggs-matrix-stats')
api project(':modules:rank-eval')
api project(':modules:lang-mustache')
api project(':modules:aggregations')
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/GetAliasesResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/GetAliasesResponse.java
deleted file mode 100644
index c5a1d97b7edf..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/GetAliasesResponse.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client;
-
-import org.elasticsearch.ElasticsearchException;
-import org.elasticsearch.cluster.metadata.AliasMetadata;
-import org.elasticsearch.common.xcontent.StatusToXContentObject;
-import org.elasticsearch.rest.RestStatus;
-import org.elasticsearch.xcontent.ToXContent;
-import org.elasticsearch.xcontent.XContentBuilder;
-import org.elasticsearch.xcontent.XContentParser;
-import org.elasticsearch.xcontent.XContentParser.Token;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
-
-/**
- * Response obtained from the get aliases API.
- * The format is pretty horrible as it holds aliases, but at the same time errors can come back through the status and error fields.
- * Such errors are mostly 404 - NOT FOUND for aliases that were specified but not found. In such case the client won't throw exception
- * so it allows to retrieve the returned aliases, while at the same time checking if errors were returned.
- * There's also the case where an exception is returned, like for instance an {@link org.elasticsearch.index.IndexNotFoundException}.
- * We would usually throw such exception, but we configure the client to not throw for 404 to support the case above, hence we also not
- * throw in case an index is not found, although it is a hard error that doesn't come back with aliases.
- */
-public class GetAliasesResponse implements StatusToXContentObject {
-
- private final RestStatus status;
- private final String error;
- private final ElasticsearchException exception;
-
- private final Map> aliases;
-
- GetAliasesResponse(RestStatus status, String error, Map> aliases) {
- this.status = status;
- this.error = error;
- this.aliases = aliases;
- this.exception = null;
- }
-
- private GetAliasesResponse(RestStatus status, ElasticsearchException exception) {
- this.status = status;
- this.error = null;
- this.aliases = Collections.emptyMap();
- this.exception = exception;
- }
-
- @Override
- public RestStatus status() {
- return status;
- }
-
- /**
- * Return the possibly returned error, null otherwise
- */
- public String getError() {
- return error;
- }
-
- /**
- * Return the exception that may have been returned
- */
- public ElasticsearchException getException() {
- return exception;
- }
-
- /**
- * Return the requested aliases
- */
- public Map> getAliases() {
- return aliases;
- }
-
- @Override
- public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
- builder.startObject();
- {
- if (status != RestStatus.OK) {
- builder.field("error", error);
- builder.field("status", status.getStatus());
- }
-
- for (Map.Entry> entry : aliases.entrySet()) {
- builder.startObject(entry.getKey());
- {
- builder.startObject("aliases");
- {
- for (final AliasMetadata alias : entry.getValue()) {
- AliasMetadata.Builder.toXContent(alias, builder, ToXContent.EMPTY_PARAMS);
- }
- }
- builder.endObject();
- }
- builder.endObject();
- }
- }
- builder.endObject();
- return builder;
- }
-
- /**
- * Parse the get aliases response
- */
- public static GetAliasesResponse fromXContent(XContentParser parser) throws IOException {
- if (parser.currentToken() == null) {
- parser.nextToken();
- }
- ensureExpectedToken(Token.START_OBJECT, parser.currentToken(), parser);
- Map> aliases = new HashMap<>();
-
- String currentFieldName;
- Token token;
- String error = null;
- ElasticsearchException exception = null;
- RestStatus status = RestStatus.OK;
-
- while (parser.nextToken() != Token.END_OBJECT) {
- if (parser.currentToken() == Token.FIELD_NAME) {
- currentFieldName = parser.currentName();
-
- if ("status".equals(currentFieldName)) {
- if ((token = parser.nextToken()) != Token.FIELD_NAME) {
- ensureExpectedToken(Token.VALUE_NUMBER, token, parser);
- status = RestStatus.fromCode(parser.intValue());
- }
- } else if ("error".equals(currentFieldName)) {
- token = parser.nextToken();
- if (token == Token.VALUE_STRING) {
- error = parser.text();
- } else if (token == Token.START_OBJECT) {
- parser.nextToken();
- exception = ElasticsearchException.innerFromXContent(parser, true);
- } else if (token == Token.START_ARRAY) {
- parser.skipChildren();
- }
- } else {
- String indexName = parser.currentName();
- if (parser.nextToken() == Token.START_OBJECT) {
- Set parseInside = parseAliases(parser);
- aliases.put(indexName, parseInside);
- }
- }
- }
- }
- if (exception != null) {
- assert error == null;
- assert aliases.isEmpty();
- return new GetAliasesResponse(status, exception);
- }
- return new GetAliasesResponse(status, error, aliases);
- }
-
- private static Set parseAliases(XContentParser parser) throws IOException {
- Set aliases = new HashSet<>();
- Token token;
- String currentFieldName = null;
- while ((token = parser.nextToken()) != Token.END_OBJECT) {
- if (token == Token.FIELD_NAME) {
- currentFieldName = parser.currentName();
- } else if (token == Token.START_OBJECT) {
- if ("aliases".equals(currentFieldName)) {
- while (parser.nextToken() != Token.END_OBJECT) {
- AliasMetadata fromXContent = AliasMetadata.Builder.fromXContent(parser);
- aliases.add(fromXContent);
- }
- } else {
- parser.skipChildren();
- }
- } else if (token == Token.START_ARRAY) {
- parser.skipChildren();
- }
- }
- return aliases;
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/NodesResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/NodesResponse.java
deleted file mode 100644
index a0c38498591f..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/NodesResponse.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client;
-
-import org.elasticsearch.xcontent.ConstructingObjectParser;
-import org.elasticsearch.xcontent.ParseField;
-
-/**
- * Base class for responses that are node responses. These responses always contain the cluster
- * name and the {@link NodesResponseHeader}.
- */
-public abstract class NodesResponse {
-
- private final NodesResponseHeader header;
- private final String clusterName;
-
- protected NodesResponse(NodesResponseHeader header, String clusterName) {
- this.header = header;
- this.clusterName = clusterName;
- }
-
- /**
- * Get the cluster name associated with all of the nodes.
- *
- * @return Never {@code null}.
- */
- public String getClusterName() {
- return clusterName;
- }
-
- /**
- * Gets information about the number of total, successful and failed nodes the request was run on.
- * Also includes exceptions if relevant.
- */
- public NodesResponseHeader getHeader() {
- return header;
- }
-
- public static void declareCommonNodesResponseParsing(ConstructingObjectParser parser) {
- parser.declareObject(ConstructingObjectParser.constructorArg(), NodesResponseHeader::fromXContent, new ParseField("_nodes"));
- parser.declareString(ConstructingObjectParser.constructorArg(), new ParseField("cluster_name"));
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/NodesResponseHeader.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/NodesResponseHeader.java
deleted file mode 100644
index e22326dc88fb..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/NodesResponseHeader.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-package org.elasticsearch.client;
-
-import org.elasticsearch.ElasticsearchException;
-import org.elasticsearch.action.support.nodes.BaseNodesResponse;
-import org.elasticsearch.core.Nullable;
-import org.elasticsearch.rest.action.RestActions;
-import org.elasticsearch.xcontent.ConstructingObjectParser;
-import org.elasticsearch.xcontent.ParseField;
-import org.elasticsearch.xcontent.ToXContent;
-import org.elasticsearch.xcontent.XContentBuilder;
-import org.elasticsearch.xcontent.XContentParser;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * A utility class to parse the Nodes Header returned by
- * {@link RestActions#buildNodesHeader(XContentBuilder, ToXContent.Params, BaseNodesResponse)}.
- */
-public final class NodesResponseHeader {
-
- public static final ParseField TOTAL = new ParseField("total");
- public static final ParseField SUCCESSFUL = new ParseField("successful");
- public static final ParseField FAILED = new ParseField("failed");
- public static final ParseField FAILURES = new ParseField("failures");
-
- @SuppressWarnings("unchecked")
- public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- "nodes_response_header",
- true,
- (a) -> {
- int i = 0;
- int total = (Integer) a[i++];
- int successful = (Integer) a[i++];
- int failed = (Integer) a[i++];
- List failures = (List) a[i++];
- return new NodesResponseHeader(total, successful, failed, failures);
- }
- );
-
- static {
- PARSER.declareInt(ConstructingObjectParser.constructorArg(), TOTAL);
- PARSER.declareInt(ConstructingObjectParser.constructorArg(), SUCCESSFUL);
- PARSER.declareInt(ConstructingObjectParser.constructorArg(), FAILED);
- PARSER.declareObjectArray(
- ConstructingObjectParser.optionalConstructorArg(),
- (p, c) -> ElasticsearchException.fromXContent(p),
- FAILURES
- );
- }
-
- private final int total;
- private final int successful;
- private final int failed;
- private final List failures;
-
- public NodesResponseHeader(int total, int successful, int failed, @Nullable List failures) {
- this.total = total;
- this.successful = successful;
- this.failed = failed;
- this.failures = failures == null ? Collections.emptyList() : failures;
- }
-
- public static NodesResponseHeader fromXContent(XContentParser parser, Void context) throws IOException {
- return PARSER.parse(parser, context);
- }
-
- /** the total number of nodes that the operation was carried on */
- public int getTotal() {
- return total;
- }
-
- /** the number of nodes that the operation has failed on */
- public int getFailed() {
- return failed;
- }
-
- /** the number of nodes that the operation was successful on */
- public int getSuccessful() {
- return successful;
- }
-
- /**
- * Get the failed node exceptions.
- *
- * @return Never {@code null}. Can be empty.
- */
- public List getFailures() {
- return failures;
- }
-
- /**
- * Determine if there are any node failures in {@link #failures}.
- *
- * @return {@code true} if {@link #failures} contains at least 1 exception.
- */
- public boolean hasFailures() {
- return failures.isEmpty() == false;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- NodesResponseHeader that = (NodesResponseHeader) o;
- return total == that.total && successful == that.successful && failed == that.failed && Objects.equals(failures, that.failures);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(total, successful, failed, failures);
- }
-
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java
index 1cba9261ec09..fca1e5d29efa 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java
@@ -9,66 +9,33 @@
package org.elasticsearch.client;
import org.apache.http.HttpEntity;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.DocWriteRequest;
-import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
-import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
-import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
-import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequest;
import org.elasticsearch.action.bulk.BulkRequest;
-import org.elasticsearch.action.delete.DeleteRequest;
-import org.elasticsearch.action.explain.ExplainRequest;
-import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
-import org.elasticsearch.action.get.GetRequest;
-import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.index.IndexRequest;
-import org.elasticsearch.action.search.ClearScrollRequest;
-import org.elasticsearch.action.search.ClosePointInTimeRequest;
-import org.elasticsearch.action.search.MultiSearchRequest;
-import org.elasticsearch.action.search.OpenPointInTimeRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
import org.elasticsearch.action.update.UpdateRequest;
-import org.elasticsearch.client.core.CountRequest;
-import org.elasticsearch.client.core.GetSourceRequest;
-import org.elasticsearch.client.core.MultiTermVectorsRequest;
-import org.elasticsearch.client.core.TermVectorsRequest;
-import org.elasticsearch.client.internal.Requests;
-import org.elasticsearch.cluster.health.ClusterHealthStatus;
-import org.elasticsearch.common.Priority;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.lucene.uid.Versions;
-import org.elasticsearch.common.util.CollectionUtils;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.core.SuppressForbidden;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.VersionType;
-import org.elasticsearch.index.rankeval.RankEvalRequest;
-import org.elasticsearch.index.reindex.AbstractBulkByScrollRequest;
-import org.elasticsearch.index.reindex.DeleteByQueryRequest;
-import org.elasticsearch.index.reindex.ReindexRequest;
-import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.index.seqno.SequenceNumbers;
import org.elasticsearch.rest.action.search.RestSearchAction;
-import org.elasticsearch.script.mustache.MultiSearchTemplateRequest;
-import org.elasticsearch.script.mustache.SearchTemplateRequest;
-import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.xcontent.DeprecationHandler;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.ToXContent;
-import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;
@@ -78,9 +45,7 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
-import java.util.Arrays;
import java.util.HashMap;
-import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringJoiner;
@@ -92,27 +57,6 @@ private RequestConverters() {
// Contains only status utility methods
}
- static Request delete(DeleteRequest deleteRequest) {
- String endpoint = endpoint(deleteRequest.index(), deleteRequest.id());
- Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
-
- Params parameters = new Params();
- parameters.withRouting(deleteRequest.routing());
- parameters.withTimeout(deleteRequest.timeout());
- parameters.withVersion(deleteRequest.version());
- parameters.withVersionType(deleteRequest.versionType());
- parameters.withIfSeqNo(deleteRequest.ifSeqNo());
- parameters.withIfPrimaryTerm(deleteRequest.ifPrimaryTerm());
- parameters.withRefreshPolicy(deleteRequest.getRefreshPolicy());
- parameters.withWaitForActiveShards(deleteRequest.waitForActiveShards());
- request.addParameters(parameters.asMap());
- return request;
- }
-
- static Request info() {
- return new Request(HttpGet.METHOD_NAME, "/");
- }
-
static Request bulk(BulkRequest bulkRequest) throws IOException {
Request request = new Request(HttpPost.METHOD_NAME, "/_bulk");
@@ -246,64 +190,6 @@ static Request bulk(BulkRequest bulkRequest) throws IOException {
return request;
}
- static Request exists(GetRequest getRequest) {
- return getStyleRequest(HttpHead.METHOD_NAME, getRequest);
- }
-
- static Request get(GetRequest getRequest) {
- return getStyleRequest(HttpGet.METHOD_NAME, getRequest);
- }
-
- private static Request getStyleRequest(String method, GetRequest getRequest) {
- Request request = new Request(method, endpoint(getRequest.index(), getRequest.id()));
-
- Params parameters = new Params();
- parameters.withPreference(getRequest.preference());
- parameters.withRouting(getRequest.routing());
- parameters.withRefresh(getRequest.refresh());
- parameters.withRealtime(getRequest.realtime());
- parameters.withStoredFields(getRequest.storedFields());
- parameters.withVersion(getRequest.version());
- parameters.withVersionType(getRequest.versionType());
- parameters.withFetchSourceContext(getRequest.fetchSourceContext());
- request.addParameters(parameters.asMap());
- return request;
- }
-
- static Request sourceExists(GetSourceRequest getSourceRequest) {
- return sourceRequest(getSourceRequest, HttpHead.METHOD_NAME);
- }
-
- static Request getSource(GetSourceRequest getSourceRequest) {
- return sourceRequest(getSourceRequest, HttpGet.METHOD_NAME);
- }
-
- private static Request sourceRequest(GetSourceRequest getSourceRequest, String httpMethodName) {
- Params parameters = new Params();
- parameters.withPreference(getSourceRequest.preference());
- parameters.withRouting(getSourceRequest.routing());
- parameters.withRefresh(getSourceRequest.refresh());
- parameters.withRealtime(getSourceRequest.realtime());
- parameters.withFetchSourceContext(getSourceRequest.fetchSourceContext());
-
- String endpoint = endpoint(getSourceRequest.index(), "_source", getSourceRequest.id());
- Request request = new Request(httpMethodName, endpoint);
- request.addParameters(parameters.asMap());
- return request;
- }
-
- static Request multiGet(MultiGetRequest multiGetRequest) throws IOException {
- Request request = new Request(HttpPost.METHOD_NAME, "/_mget");
-
- Params parameters = new Params();
- parameters.withPreference(multiGetRequest.preference());
- parameters.withRealtime(multiGetRequest.realtime());
- parameters.withRefresh(multiGetRequest.refresh());
- request.addParameters(parameters.asMap());
- request.setEntity(createEntity(multiGetRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
static Request index(IndexRequest indexRequest) {
String method = Strings.hasLength(indexRequest.id()) ? HttpPut.METHOD_NAME : HttpPost.METHOD_NAME;
@@ -335,57 +221,6 @@ static Request index(IndexRequest indexRequest) {
return request;
}
- static Request ping() {
- return new Request(HttpHead.METHOD_NAME, "/");
- }
-
- static Request update(UpdateRequest updateRequest) throws IOException {
- String endpoint = endpoint(updateRequest.index(), "_update", updateRequest.id());
- Request request = new Request(HttpPost.METHOD_NAME, endpoint);
-
- Params parameters = new Params();
- parameters.withRouting(updateRequest.routing());
- parameters.withTimeout(updateRequest.timeout());
- parameters.withRefreshPolicy(updateRequest.getRefreshPolicy());
- parameters.withWaitForActiveShards(updateRequest.waitForActiveShards());
- parameters.withDocAsUpsert(updateRequest.docAsUpsert());
- parameters.withFetchSourceContext(updateRequest.fetchSource());
- parameters.withRetryOnConflict(updateRequest.retryOnConflict());
- parameters.withVersion(updateRequest.version());
- parameters.withVersionType(updateRequest.versionType());
- parameters.withRequireAlias(updateRequest.isRequireAlias());
-
- // The Java API allows update requests with different content types
- // set for the partial document and the upsert document. This client
- // only accepts update requests that have the same content types set
- // for both doc and upsert.
- XContentType xContentType = null;
- if (updateRequest.doc() != null) {
- xContentType = updateRequest.doc().getContentType();
- }
- if (updateRequest.upsertRequest() != null) {
- XContentType upsertContentType = updateRequest.upsertRequest().getContentType();
- if ((xContentType != null) && (xContentType != upsertContentType)) {
- throw new IllegalStateException(
- "Update request cannot have different content types for doc ["
- + xContentType
- + "]"
- + " and upsert ["
- + upsertContentType
- + "] documents"
- );
- } else {
- xContentType = upsertContentType;
- }
- }
- if (xContentType == null) {
- xContentType = Requests.INDEX_CONTENT_TYPE;
- }
- request.addParameters(parameters.asMap());
- request.setEntity(createEntity(updateRequest, xContentType));
- return request;
- }
-
/**
* Convert a {@linkplain SearchRequest} into a {@linkplain Request}.
* @param searchRequest the request to convert
@@ -439,326 +274,6 @@ static Request searchScroll(SearchScrollRequest searchScrollRequest) throws IOEx
return request;
}
- static Request clearScroll(ClearScrollRequest clearScrollRequest) throws IOException {
- Request request = new Request(HttpDelete.METHOD_NAME, "/_search/scroll");
- request.setEntity(createEntity(clearScrollRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request openPointInTime(OpenPointInTimeRequest openRequest) {
- Request request = new Request(HttpPost.METHOD_NAME, endpoint(openRequest.indices(), "_pit"));
- Params params = new Params();
- if (OpenPointInTimeRequest.DEFAULT_INDICES_OPTIONS.equals(openRequest.indicesOptions()) == false) {
- params.withIndicesOptions(openRequest.indicesOptions());
- }
- params.withRouting(openRequest.routing());
- params.withPreference(openRequest.preference());
- params.putParam("keep_alive", openRequest.keepAlive());
- request.addParameters(params.asMap());
- return request;
- }
-
- static Request closePointInTime(ClosePointInTimeRequest closeRequest) throws IOException {
- Request request = new Request(HttpDelete.METHOD_NAME, "/_pit");
- request.setEntity(createEntity(closeRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request multiSearch(MultiSearchRequest multiSearchRequest) throws IOException {
- Request request = new Request(HttpPost.METHOD_NAME, "/_msearch");
-
- Params params = new Params();
- params.putParam(RestSearchAction.TYPED_KEYS_PARAM, "true");
- if (multiSearchRequest.maxConcurrentSearchRequests() != MultiSearchRequest.MAX_CONCURRENT_SEARCH_REQUESTS_DEFAULT) {
- params.putParam("max_concurrent_searches", Integer.toString(multiSearchRequest.maxConcurrentSearchRequests()));
- }
-
- XContent xContent = REQUEST_BODY_CONTENT_TYPE.xContent();
- byte[] source = MultiSearchRequest.writeMultiLineFormat(multiSearchRequest, xContent);
- request.addParameters(params.asMap());
- request.setEntity(new NByteArrayEntity(source, createContentType(xContent.type())));
- return request;
- }
-
- static Request searchTemplate(SearchTemplateRequest searchTemplateRequest) throws IOException {
- Request request;
-
- if (searchTemplateRequest.isSimulate()) {
- request = new Request(HttpGet.METHOD_NAME, "_render/template");
- } else {
- SearchRequest searchRequest = searchTemplateRequest.getRequest();
- String endpoint = endpoint(searchRequest.indices(), "_search/template");
- request = new Request(HttpPost.METHOD_NAME, endpoint);
-
- Params params = new Params();
- addSearchRequestParams(params, searchRequest);
- request.addParameters(params.asMap());
- }
-
- request.setEntity(createEntity(searchTemplateRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request multiSearchTemplate(MultiSearchTemplateRequest multiSearchTemplateRequest) throws IOException {
- Request request = new Request(HttpPost.METHOD_NAME, "/_msearch/template");
-
- Params params = new Params();
- params.putParam(RestSearchAction.TYPED_KEYS_PARAM, "true");
- if (multiSearchTemplateRequest.maxConcurrentSearchRequests() != MultiSearchRequest.MAX_CONCURRENT_SEARCH_REQUESTS_DEFAULT) {
- params.putParam("max_concurrent_searches", Integer.toString(multiSearchTemplateRequest.maxConcurrentSearchRequests()));
- }
- request.addParameters(params.asMap());
-
- XContent xContent = REQUEST_BODY_CONTENT_TYPE.xContent();
- byte[] source = MultiSearchTemplateRequest.writeMultiLineFormat(multiSearchTemplateRequest, xContent);
- request.setEntity(new NByteArrayEntity(source, createContentType(xContent.type())));
- return request;
- }
-
- static Request count(CountRequest countRequest) throws IOException {
- Request request = new Request(HttpPost.METHOD_NAME, endpoint(countRequest.indices(), countRequest.types(), "_count"));
- Params params = new Params();
- params.withRouting(countRequest.routing());
- params.withPreference(countRequest.preference());
- params.withIndicesOptions(countRequest.indicesOptions());
- if (countRequest.terminateAfter() != 0) {
- params.withTerminateAfter(countRequest.terminateAfter());
- }
- if (countRequest.minScore() != null) {
- params.putParam("min_score", String.valueOf(countRequest.minScore()));
- }
- request.addParameters(params.asMap());
- request.setEntity(createEntity(countRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request explain(ExplainRequest explainRequest) throws IOException {
- String endpoint = endpoint(explainRequest.index(), "_explain", explainRequest.id());
- Request request = new Request(HttpGet.METHOD_NAME, endpoint);
-
- Params params = new Params();
- params.withStoredFields(explainRequest.storedFields());
- params.withFetchSourceContext(explainRequest.fetchSourceContext());
- params.withRouting(explainRequest.routing());
- params.withPreference(explainRequest.preference());
- request.addParameters(params.asMap());
- request.setEntity(createEntity(explainRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request fieldCaps(FieldCapabilitiesRequest fieldCapabilitiesRequest) throws IOException {
- String methodName = fieldCapabilitiesRequest.indexFilter() != null ? HttpPost.METHOD_NAME : HttpGet.METHOD_NAME;
- Request request = new Request(methodName, endpoint(fieldCapabilitiesRequest.indices(), "_field_caps"));
-
- Params params = new Params();
- params.withFields(fieldCapabilitiesRequest.fields());
- if (FieldCapabilitiesRequest.DEFAULT_INDICES_OPTIONS.equals(fieldCapabilitiesRequest.indicesOptions()) == false) {
- params.withIndicesOptions(fieldCapabilitiesRequest.indicesOptions());
- }
- request.addParameters(params.asMap());
- if (fieldCapabilitiesRequest.indexFilter() != null) {
- request.setEntity(createEntity(fieldCapabilitiesRequest, REQUEST_BODY_CONTENT_TYPE));
- }
- return request;
- }
-
- static Request rankEval(RankEvalRequest rankEvalRequest) throws IOException {
- Request request = new Request(HttpGet.METHOD_NAME, endpoint(rankEvalRequest.indices(), Strings.EMPTY_ARRAY, "_rank_eval"));
-
- Params params = new Params();
- if (SearchRequest.DEFAULT_INDICES_OPTIONS.equals(rankEvalRequest.indicesOptions()) == false) {
- params.withIndicesOptions(rankEvalRequest.indicesOptions());
- }
- params.putParam("search_type", rankEvalRequest.searchType().name().toLowerCase(Locale.ROOT));
- request.addParameters(params.asMap());
- request.setEntity(createEntity(rankEvalRequest.getRankEvalSpec(), REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request reindex(ReindexRequest reindexRequest) throws IOException {
- return prepareReindexRequest(reindexRequest, true);
- }
-
- static Request deleteByQuery(DeleteByQueryRequest deleteByQueryRequest) throws IOException {
- return prepareDeleteByQueryRequest(deleteByQueryRequest, true);
- }
-
- static Request updateByQuery(UpdateByQueryRequest updateByQueryRequest) throws IOException {
- return prepareUpdateByQueryRequest(updateByQueryRequest, true);
- }
-
- private static Request prepareReindexRequest(ReindexRequest reindexRequest, boolean waitForCompletion) throws IOException {
- String endpoint = new EndpointBuilder().addPathPart("_reindex").build();
- Request request = new Request(HttpPost.METHOD_NAME, endpoint);
- Params params = new Params().withWaitForCompletion(waitForCompletion)
- .withRefresh(reindexRequest.isRefresh())
- .withTimeout(reindexRequest.getTimeout())
- .withWaitForActiveShards(reindexRequest.getWaitForActiveShards())
- .withRequestsPerSecond(reindexRequest.getRequestsPerSecond())
- .withSlices(reindexRequest.getSlices())
- .withRequireAlias(reindexRequest.getDestination().isRequireAlias());
-
- if (reindexRequest.getScrollTime() != null) {
- params.putParam("scroll", reindexRequest.getScrollTime());
- }
-
- request.addParameters(params.asMap());
- request.setEntity(createEntity(reindexRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- private static Request prepareDeleteByQueryRequest(DeleteByQueryRequest deleteByQueryRequest, boolean waitForCompletion)
- throws IOException {
- String endpoint = endpoint(deleteByQueryRequest.indices(), "_delete_by_query");
- Request request = new Request(HttpPost.METHOD_NAME, endpoint);
- Params params = new Params().withRouting(deleteByQueryRequest.getRouting())
- .withRefresh(deleteByQueryRequest.isRefresh())
- .withTimeout(deleteByQueryRequest.getTimeout())
- .withWaitForActiveShards(deleteByQueryRequest.getWaitForActiveShards())
- .withRequestsPerSecond(deleteByQueryRequest.getRequestsPerSecond())
- .withWaitForCompletion(waitForCompletion)
- .withSlices(deleteByQueryRequest.getSlices());
-
- if (SearchRequest.DEFAULT_INDICES_OPTIONS.equals(deleteByQueryRequest.indicesOptions()) == false) {
- params = params.withIndicesOptions(deleteByQueryRequest.indicesOptions());
- }
-
- if (deleteByQueryRequest.isAbortOnVersionConflict() == false) {
- params.putParam("conflicts", "proceed");
- }
- if (deleteByQueryRequest.getBatchSize() != AbstractBulkByScrollRequest.DEFAULT_SCROLL_SIZE) {
- params.putParam("scroll_size", Integer.toString(deleteByQueryRequest.getBatchSize()));
- }
- if (deleteByQueryRequest.getScrollTime() != AbstractBulkByScrollRequest.DEFAULT_SCROLL_TIMEOUT) {
- params.putParam("scroll", deleteByQueryRequest.getScrollTime());
- }
- if (deleteByQueryRequest.getMaxDocs() > 0) {
- params.putParam("max_docs", Integer.toString(deleteByQueryRequest.getMaxDocs()));
- }
- request.addParameters(params.asMap());
- request.setEntity(createEntity(deleteByQueryRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request prepareUpdateByQueryRequest(UpdateByQueryRequest updateByQueryRequest, boolean waitForCompletion) throws IOException {
- String endpoint = endpoint(updateByQueryRequest.indices(), "_update_by_query");
- Request request = new Request(HttpPost.METHOD_NAME, endpoint);
- Params params = new Params().withRouting(updateByQueryRequest.getRouting())
- .withPipeline(updateByQueryRequest.getPipeline())
- .withRefresh(updateByQueryRequest.isRefresh())
- .withTimeout(updateByQueryRequest.getTimeout())
- .withWaitForActiveShards(updateByQueryRequest.getWaitForActiveShards())
- .withRequestsPerSecond(updateByQueryRequest.getRequestsPerSecond())
- .withWaitForCompletion(waitForCompletion)
- .withSlices(updateByQueryRequest.getSlices());
- if (SearchRequest.DEFAULT_INDICES_OPTIONS.equals(updateByQueryRequest.indicesOptions()) == false) {
- params = params.withIndicesOptions(updateByQueryRequest.indicesOptions());
- }
- if (updateByQueryRequest.isAbortOnVersionConflict() == false) {
- params.putParam("conflicts", "proceed");
- }
- if (updateByQueryRequest.getBatchSize() != AbstractBulkByScrollRequest.DEFAULT_SCROLL_SIZE) {
- params.putParam("scroll_size", Integer.toString(updateByQueryRequest.getBatchSize()));
- }
- if (updateByQueryRequest.getScrollTime() != AbstractBulkByScrollRequest.DEFAULT_SCROLL_TIMEOUT) {
- params.putParam("scroll", updateByQueryRequest.getScrollTime());
- }
- if (updateByQueryRequest.getMaxDocs() > 0) {
- params.putParam("max_docs", Integer.toString(updateByQueryRequest.getMaxDocs()));
- }
- request.addParameters(params.asMap());
- request.setEntity(createEntity(updateByQueryRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request rethrottleReindex(RethrottleRequest rethrottleRequest) {
- return rethrottle(rethrottleRequest, "_reindex");
- }
-
- static Request rethrottleUpdateByQuery(RethrottleRequest rethrottleRequest) {
- return rethrottle(rethrottleRequest, "_update_by_query");
- }
-
- static Request rethrottleDeleteByQuery(RethrottleRequest rethrottleRequest) {
- return rethrottle(rethrottleRequest, "_delete_by_query");
- }
-
- private static Request rethrottle(RethrottleRequest rethrottleRequest, String firstPathPart) {
- String endpoint = new EndpointBuilder().addPathPart(firstPathPart)
- .addPathPart(rethrottleRequest.getTaskId().toString())
- .addPathPart("_rethrottle")
- .build();
- Request request = new Request(HttpPost.METHOD_NAME, endpoint);
- Params params = new Params().withRequestsPerSecond(rethrottleRequest.getRequestsPerSecond());
- // we set "group_by" to "none" because this is the response format we can parse back
- params.putParam("group_by", "none");
- request.addParameters(params.asMap());
- return request;
- }
-
- static Request putScript(PutStoredScriptRequest putStoredScriptRequest) throws IOException {
- String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(putStoredScriptRequest.id()).build();
- Request request = new Request(HttpPost.METHOD_NAME, endpoint);
- Params params = new Params();
- params.withTimeout(putStoredScriptRequest.timeout());
- params.withMasterTimeout(putStoredScriptRequest.masterNodeTimeout());
- if (Strings.hasText(putStoredScriptRequest.context())) {
- params.putParam("context", putStoredScriptRequest.context());
- }
- request.addParameters(params.asMap());
- request.setEntity(createEntity(putStoredScriptRequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request termVectors(TermVectorsRequest tvrequest) throws IOException {
- String endpoint;
- if (tvrequest.getType() != null) {
- endpoint = new EndpointBuilder().addPathPart(tvrequest.getIndex(), tvrequest.getType(), tvrequest.getId())
- .addPathPartAsIs("_termvectors")
- .build();
- } else {
- endpoint = new EndpointBuilder().addPathPart(tvrequest.getIndex())
- .addPathPartAsIs("_termvectors")
- .addPathPart(tvrequest.getId())
- .build();
- }
-
- Request request = new Request(HttpGet.METHOD_NAME, endpoint);
- Params params = new Params();
- params.withRouting(tvrequest.getRouting());
- params.withPreference(tvrequest.getPreference());
- params.withRealtime(tvrequest.getRealtime());
- request.addParameters(params.asMap());
- request.setEntity(createEntity(tvrequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request mtermVectors(MultiTermVectorsRequest mtvrequest) throws IOException {
- String endpoint = "_mtermvectors";
- Request request = new Request(HttpGet.METHOD_NAME, endpoint);
- request.setEntity(createEntity(mtvrequest, REQUEST_BODY_CONTENT_TYPE));
- return request;
- }
-
- static Request getScript(GetStoredScriptRequest getStoredScriptRequest) {
- String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(getStoredScriptRequest.id()).build();
- Request request = new Request(HttpGet.METHOD_NAME, endpoint);
- Params params = new Params();
- params.withMasterTimeout(getStoredScriptRequest.masterNodeTimeout());
- request.addParameters(params.asMap());
- return request;
- }
-
- static Request deleteScript(DeleteStoredScriptRequest deleteStoredScriptRequest) {
- String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(deleteStoredScriptRequest.id()).build();
- Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
- Params params = new Params();
- params.withTimeout(deleteStoredScriptRequest.timeout());
- params.withMasterTimeout(deleteStoredScriptRequest.masterNodeTimeout());
- request.addParameters(params.asMap());
- return request;
- }
-
static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException {
return createEntity(toXContent, xContentType, ToXContent.EMPTY_PARAMS);
}
@@ -783,10 +298,6 @@ static String endpoint(String index, String type, String id, String endpoint) {
return new EndpointBuilder().addPathPart(index, type, id).addPathPartAsIs(endpoint).build();
}
- static String endpoint(String[] indices) {
- return new EndpointBuilder().addCommaSeparatedPathParts(indices).build();
- }
-
static String endpoint(String[] indices, String endpoint) {
return new EndpointBuilder().addCommaSeparatedPathParts(indices).addPathPartAsIs(endpoint).build();
}
@@ -799,13 +310,6 @@ static String endpoint(String[] indices, String[] types, String endpoint) {
.build();
}
- static String endpoint(String[] indices, String endpoint, String[] suffixes) {
- return new EndpointBuilder().addCommaSeparatedPathParts(indices)
- .addPathPartAsIs(endpoint)
- .addCommaSeparatedPathParts(suffixes)
- .build();
- }
-
@Deprecated
static String endpoint(String[] indices, String endpoint, String type) {
return new EndpointBuilder().addCommaSeparatedPathParts(indices).addPathPartAsIs(endpoint).addPathPart(type).build();
@@ -849,39 +353,6 @@ Map asMap() {
return parameters;
}
- Params withDocAsUpsert(boolean docAsUpsert) {
- if (docAsUpsert) {
- return putParam("doc_as_upsert", Boolean.TRUE.toString());
- }
- return this;
- }
-
- Params withFetchSourceContext(FetchSourceContext fetchSourceContext) {
- if (fetchSourceContext != null) {
- if (fetchSourceContext.fetchSource() == false) {
- putParam("_source", Boolean.FALSE.toString());
- }
- if (CollectionUtils.isEmpty(fetchSourceContext.includes()) == false) {
- putParam("_source_includes", String.join(",", fetchSourceContext.includes()));
- }
- if (CollectionUtils.isEmpty(fetchSourceContext.excludes()) == false) {
- putParam("_source_excludes", String.join(",", fetchSourceContext.excludes()));
- }
- }
- return this;
- }
-
- Params withFields(String[] fields) {
- if (CollectionUtils.isEmpty(fields) == false) {
- return putParam("fields", String.join(",", fields));
- }
- return this;
- }
-
- Params withMasterTimeout(TimeValue masterTimeout) {
- return putParam("master_timeout", masterTimeout);
- }
-
Params withPipeline(String pipeline) {
return putParam("pipeline", pipeline);
}
@@ -910,20 +381,6 @@ Params withAllowPartialResults(boolean allowPartialSearchResults) {
return putParam("allow_partial_search_results", Boolean.toString(allowPartialSearchResults));
}
- Params withRealtime(boolean realtime) {
- if (realtime == false) {
- return putParam("realtime", Boolean.FALSE.toString());
- }
- return this;
- }
-
- Params withRefresh(boolean refresh) {
- if (refresh) {
- return withRefreshPolicy(RefreshPolicy.IMMEDIATE);
- }
- return this;
- }
-
Params withRefreshPolicy(RefreshPolicy refreshPolicy) {
if (refreshPolicy != RefreshPolicy.NONE) {
return putParam("refresh", refreshPolicy.getValue());
@@ -931,46 +388,10 @@ Params withRefreshPolicy(RefreshPolicy refreshPolicy) {
return this;
}
- Params withRequestsPerSecond(float requestsPerSecond) {
- // the default in AbstractBulkByScrollRequest is Float.POSITIVE_INFINITY,
- // but we don't want to add that to the URL parameters, instead we use -1
- if (Float.isFinite(requestsPerSecond)) {
- return putParam(RethrottleRequest.REQUEST_PER_SECOND_PARAMETER, Float.toString(requestsPerSecond));
- } else {
- return putParam(RethrottleRequest.REQUEST_PER_SECOND_PARAMETER, "-1");
- }
- }
-
- Params withRetryOnConflict(int retryOnConflict) {
- if (retryOnConflict > 0) {
- return putParam("retry_on_conflict", String.valueOf(retryOnConflict));
- }
- return this;
- }
-
Params withRouting(String routing) {
return putParam("routing", routing);
}
- Params withSlices(int slices) {
- if (slices == 0) {
- // translate to "auto" value in rest request so the receiving end doesn't throw error
- return putParam("slices", AbstractBulkByScrollRequest.AUTO_SLICES_VALUE);
- }
- return putParam("slices", String.valueOf(slices));
- }
-
- Params withStoredFields(String[] storedFields) {
- if (CollectionUtils.isEmpty(storedFields) == false) {
- return putParam("stored_fields", String.join(",", storedFields));
- }
- return this;
- }
-
- Params withTerminateAfter(int terminateAfter) {
- return putParam("terminate_after", String.valueOf(terminateAfter));
- }
-
Params withTimeout(TimeValue timeout) {
return putParam("timeout", timeout);
}
@@ -1049,103 +470,6 @@ Params withIgnoreUnavailable(boolean ignoreUnavailable) {
putParam("ignore_unavailable", Boolean.toString(ignoreUnavailable));
return this;
}
-
- Params withHuman(boolean human) {
- if (human) {
- putParam("human", Boolean.toString(human));
- }
- return this;
- }
-
- Params withLocal(boolean local) {
- if (local) {
- putParam("local", Boolean.toString(local));
- }
- return this;
- }
-
- Params withIncludeDefaults(boolean includeDefaults) {
- if (includeDefaults) {
- return putParam("include_defaults", Boolean.TRUE.toString());
- }
- return this;
- }
-
- Params withPreserveExisting(boolean preserveExisting) {
- if (preserveExisting) {
- return putParam("preserve_existing", Boolean.TRUE.toString());
- }
- return this;
- }
-
- Params withDetailed(boolean detailed) {
- if (detailed) {
- return putParam("detailed", Boolean.TRUE.toString());
- }
- return this;
- }
-
- Params withWaitForCompletion(Boolean waitForCompletion) {
- return putParam("wait_for_completion", waitForCompletion.toString());
- }
-
- Params withNodes(String[] nodes) {
- return withNodes(Arrays.asList(nodes));
- }
-
- Params withNodes(List nodes) {
- if (nodes != null && nodes.size() > 0) {
- return putParam("nodes", String.join(",", nodes));
- }
- return this;
- }
-
- Params withActions(String[] actions) {
- return withActions(Arrays.asList(actions));
- }
-
- Params withActions(List actions) {
- if (actions != null && actions.size() > 0) {
- return putParam("actions", String.join(",", actions));
- }
- return this;
- }
-
- Params withWaitForStatus(ClusterHealthStatus status) {
- if (status != null) {
- return putParam("wait_for_status", status.name().toLowerCase(Locale.ROOT));
- }
- return this;
- }
-
- Params withWaitForNoRelocatingShards(boolean waitNoRelocatingShards) {
- if (waitNoRelocatingShards) {
- return putParam("wait_for_no_relocating_shards", Boolean.TRUE.toString());
- }
- return this;
- }
-
- Params withWaitForNoInitializingShards(boolean waitNoInitShards) {
- if (waitNoInitShards) {
- return putParam("wait_for_no_initializing_shards", Boolean.TRUE.toString());
- }
- return this;
- }
-
- Params withWaitForNodes(String waitForNodes) {
- return putParam("wait_for_nodes", waitForNodes);
- }
-
- Params withLevel(ClusterHealthRequest.Level level) {
- return putParam("level", level.name().toLowerCase(Locale.ROOT));
- }
-
- Params withWaitForEvents(Priority waitForEvents) {
- if (waitForEvents != null) {
- return putParam("wait_for_events", waitForEvents.name().toLowerCase(Locale.ROOT));
- }
- return this;
- }
}
/**
@@ -1199,11 +523,6 @@ EndpointBuilder addCommaSeparatedPathParts(String[] parts) {
return this;
}
- EndpointBuilder addCommaSeparatedPathParts(List parts) {
- addPathPart(String.join(",", parts));
- return this;
- }
-
EndpointBuilder addPathPartAsIs(String... parts) {
for (String part : parts) {
if (Strings.hasLength(part)) {
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
index 1ccdb1ae58df..9b8e92b65981 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
@@ -19,25 +19,11 @@
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
-import org.elasticsearch.action.delete.DeleteRequest;
-import org.elasticsearch.action.delete.DeleteResponse;
-import org.elasticsearch.action.explain.ExplainRequest;
-import org.elasticsearch.action.explain.ExplainResponse;
-import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
-import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse;
-import org.elasticsearch.action.get.GetRequest;
-import org.elasticsearch.action.get.GetResponse;
-import org.elasticsearch.action.get.MultiGetRequest;
-import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
-import org.elasticsearch.action.search.MultiSearchRequest;
-import org.elasticsearch.action.search.MultiSearchResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
-import org.elasticsearch.action.update.UpdateRequest;
-import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.aggregations.bucket.adjacency.AdjacencyMatrixAggregationBuilder;
import org.elasticsearch.aggregations.bucket.adjacency.ParsedAdjacencyMatrix;
import org.elasticsearch.aggregations.bucket.histogram.AutoDateHistogramAggregationBuilder;
@@ -49,23 +35,12 @@
import org.elasticsearch.client.analytics.ParsedTopMetrics;
import org.elasticsearch.client.analytics.StringStatsAggregationBuilder;
import org.elasticsearch.client.analytics.TopMetricsAggregationBuilder;
-import org.elasticsearch.client.core.CountRequest;
-import org.elasticsearch.client.core.CountResponse;
-import org.elasticsearch.client.core.GetSourceRequest;
-import org.elasticsearch.client.core.GetSourceResponse;
-import org.elasticsearch.client.core.MainRequest;
import org.elasticsearch.client.core.MainResponse;
-import org.elasticsearch.client.core.TermVectorsRequest;
-import org.elasticsearch.client.core.TermVectorsResponse;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.util.concurrent.FutureUtils;
import org.elasticsearch.common.util.concurrent.ListenableFuture;
import org.elasticsearch.core.CheckedConsumer;
import org.elasticsearch.core.CheckedFunction;
-import org.elasticsearch.index.reindex.BulkByScrollResponse;
-import org.elasticsearch.index.reindex.DeleteByQueryRequest;
-import org.elasticsearch.index.reindex.ReindexRequest;
-import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.plugins.spi.NamedXContentProvider;
import org.elasticsearch.rest.RestResponse;
import org.elasticsearch.rest.RestStatus;
@@ -198,7 +173,6 @@
import java.util.stream.Stream;
import static java.util.Collections.emptySet;
-import static java.util.Collections.singleton;
import static java.util.stream.Collectors.toList;
/**
@@ -360,223 +334,6 @@ public final Cancellable bulkAsync(BulkRequest bulkRequest, RequestOptions optio
);
}
- /**
- * Executes a reindex request.
- * See Reindex API on elastic.co
- * @param reindexRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final BulkByScrollResponse reindex(ReindexRequest reindexRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(
- reindexRequest,
- RequestConverters::reindex,
- options,
- BulkByScrollResponse::fromXContent,
- singleton(409)
- );
- }
-
- /**
- * Executes a update by query request.
- * See
- * Update By Query API on elastic.co
- * @param updateByQueryRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final BulkByScrollResponse updateByQuery(UpdateByQueryRequest updateByQueryRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(
- updateByQueryRequest,
- RequestConverters::updateByQuery,
- options,
- BulkByScrollResponse::fromXContent,
- singleton(409)
- );
- }
-
- /**
- * Executes a delete by query request.
- * See
- * Delete By Query API on elastic.co
- * @param deleteByQueryRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final BulkByScrollResponse deleteByQuery(DeleteByQueryRequest deleteByQueryRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(
- deleteByQueryRequest,
- RequestConverters::deleteByQuery,
- options,
- BulkByScrollResponse::fromXContent,
- singleton(409)
- );
- }
-
- /**
- * Get the cluster info otherwise provided when sending an HTTP request to '/'
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final MainResponse info(RequestOptions options) throws IOException {
- return performRequestAndParseEntity(
- new MainRequest(),
- (request) -> RequestConverters.info(),
- options,
- MainResponse::fromXContent,
- emptySet()
- );
- }
-
- /**
- * Retrieves a document by id using the Get API.
- * See Get API on elastic.co
- * @param getRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final GetResponse get(GetRequest getRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(getRequest, RequestConverters::get, options, GetResponse::fromXContent, singleton(404));
- }
-
- /**
- * Retrieves multiple documents by id using the Multi Get API.
- * See Multi Get API on elastic.co
- * @param multiGetRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- * @deprecated use {@link #mget(MultiGetRequest, RequestOptions)} instead
- */
- @Deprecated
- public final MultiGetResponse multiGet(MultiGetRequest multiGetRequest, RequestOptions options) throws IOException {
- return mget(multiGetRequest, options);
- }
-
- /**
- * Retrieves multiple documents by id using the Multi Get API.
- * See Multi Get API on elastic.co
- * @param multiGetRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final MultiGetResponse mget(MultiGetRequest multiGetRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(
- multiGetRequest,
- RequestConverters::multiGet,
- options,
- MultiGetResponse::fromXContent,
- singleton(404)
- );
- }
-
- /**
- * Asynchronously retrieves multiple documents by id using the Multi Get API.
- * See Multi Get API on elastic.co
- * @param multiGetRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @param listener the listener to be notified upon request completion
- * @deprecated use {@link #mgetAsync(MultiGetRequest, RequestOptions, ActionListener)} instead
- * @return cancellable that may be used to cancel the request
- */
- @Deprecated
- public final Cancellable multiGetAsync(
- MultiGetRequest multiGetRequest,
- RequestOptions options,
- ActionListener listener
- ) {
- return mgetAsync(multiGetRequest, options, listener);
- }
-
- /**
- * Asynchronously retrieves multiple documents by id using the Multi Get API.
- * See Multi Get API on elastic.co
- * @param multiGetRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @param listener the listener to be notified upon request completion
- * @return cancellable that may be used to cancel the request
- */
- public final Cancellable mgetAsync(MultiGetRequest multiGetRequest, RequestOptions options, ActionListener listener) {
- return performRequestAsyncAndParseEntity(
- multiGetRequest,
- RequestConverters::multiGet,
- options,
- MultiGetResponse::fromXContent,
- listener,
- singleton(404)
- );
- }
-
- /**
- * Checks for the existence of a document. Returns true if it exists, false otherwise.
- * See Get API on elastic.co
- * @param getRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return true if the document exists, false otherwise
- */
- public final boolean exists(GetRequest getRequest, RequestOptions options) throws IOException {
- return performRequest(getRequest, RequestConverters::exists, options, RestHighLevelClient::convertExistsResponse, emptySet());
- }
-
- /**
- * Checks for the existence of a document with a "_source" field. Returns true if it exists, false otherwise.
- * See Source exists API
- * on elastic.co
- * @param getRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return true if the document and _source field exists, false otherwise
- */
- @Deprecated
- public boolean existsSource(GetRequest getRequest, RequestOptions options) throws IOException {
- GetSourceRequest getSourceRequest = GetSourceRequest.from(getRequest);
- return performRequest(
- getSourceRequest,
- RequestConverters::sourceExists,
- options,
- RestHighLevelClient::convertExistsResponse,
- emptySet()
- );
- }
-
- /**
- * Asynchronously checks for the existence of a document with a "_source" field. Returns true if it exists, false otherwise.
- * See Source exists API
- * on elastic.co
- * @param getRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @param listener the listener to be notified upon request completion
- * @return cancellable that may be used to cancel the request
- */
- @Deprecated
- public final Cancellable existsSourceAsync(GetRequest getRequest, RequestOptions options, ActionListener listener) {
- GetSourceRequest getSourceRequest = GetSourceRequest.from(getRequest);
- return performRequestAsync(
- getSourceRequest,
- RequestConverters::sourceExists,
- options,
- RestHighLevelClient::convertExistsResponse,
- listener,
- emptySet()
- );
- }
-
- /**
- * Retrieves the source field only of a document using GetSource API.
- * See Get Source API
- * on elastic.co
- * @param getSourceRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public GetSourceResponse getSource(GetSourceRequest getSourceRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(
- getSourceRequest,
- RequestConverters::getSource,
- options,
- GetSourceResponse::fromXContent,
- emptySet()
- );
- }
-
/**
* Index a document using the Index API.
* See Index API on elastic.co
@@ -588,45 +345,6 @@ public final IndexResponse index(IndexRequest indexRequest, RequestOptions optio
return performRequestAndParseEntity(indexRequest, RequestConverters::index, options, IndexResponse::fromXContent, emptySet());
}
- /**
- * Executes a count request using the Count API.
- * See Count API on elastic.co
- * @param countRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final CountResponse count(CountRequest countRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(countRequest, RequestConverters::count, options, CountResponse::fromXContent, emptySet());
- }
-
- /**
- * Updates a document using the Update API.
- * See Update API on elastic.co
- * @param updateRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final UpdateResponse update(UpdateRequest updateRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(updateRequest, RequestConverters::update, options, UpdateResponse::fromXContent, emptySet());
- }
-
- /**
- * Deletes a document by id using the Delete API.
- * See Delete API on elastic.co
- * @param deleteRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final DeleteResponse delete(DeleteRequest deleteRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(
- deleteRequest,
- RequestConverters::delete,
- options,
- DeleteResponse::fromXContent,
- singleton(404)
- );
- }
-
/**
* Executes a search request using the Search API.
* See Search API on elastic.co
@@ -663,96 +381,6 @@ public final Cancellable searchAsync(SearchRequest searchRequest, RequestOptions
);
}
- /**
- * Executes a multi search using the msearch API.
- * See Multi search API on
- * elastic.co
- * @param multiSearchRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- * @deprecated use {@link #msearch(MultiSearchRequest, RequestOptions)} instead
- */
- @Deprecated
- public final MultiSearchResponse multiSearch(MultiSearchRequest multiSearchRequest, RequestOptions options) throws IOException {
- return msearch(multiSearchRequest, options);
- }
-
- /**
- * Executes a multi search using the msearch API.
- * See Multi search API on
- * elastic.co
- * @param multiSearchRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final MultiSearchResponse msearch(MultiSearchRequest multiSearchRequest, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(
- multiSearchRequest,
- RequestConverters::multiSearch,
- options,
- MultiSearchResponse::fromXContext,
- emptySet()
- );
- }
-
- /**
- * Asynchronously executes a multi search using the msearch API.
- * See Multi search API on
- * elastic.co
- * @param searchRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @param listener the listener to be notified upon request completion
- * @deprecated use {@link #msearchAsync(MultiSearchRequest, RequestOptions, ActionListener)} instead
- * @return cancellable that may be used to cancel the request
- */
- @Deprecated
- public final Cancellable multiSearchAsync(
- MultiSearchRequest searchRequest,
- RequestOptions options,
- ActionListener listener
- ) {
- return msearchAsync(searchRequest, options, listener);
- }
-
- /**
- * Asynchronously executes a multi search using the msearch API.
- * See Multi search API on
- * elastic.co
- * @param searchRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @param listener the listener to be notified upon request completion
- * @return cancellable that may be used to cancel the request
- */
- public final Cancellable msearchAsync(
- MultiSearchRequest searchRequest,
- RequestOptions options,
- ActionListener listener
- ) {
- return performRequestAsyncAndParseEntity(
- searchRequest,
- RequestConverters::multiSearch,
- options,
- MultiSearchResponse::fromXContext,
- listener,
- emptySet()
- );
- }
-
- /**
- * Executes a search using the Search Scroll API.
- * See Search
- * Scroll API on elastic.co
- * @param searchScrollRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- * @deprecated use {@link #scroll(SearchScrollRequest, RequestOptions)} instead
- */
- @Deprecated
- public final SearchResponse searchScroll(SearchScrollRequest searchScrollRequest, RequestOptions options) throws IOException {
- return scroll(searchScrollRequest, options);
- }
-
/**
* Executes a search using the Search Scroll API.
* See Search
- * Scroll API on elastic.co
- * @param searchScrollRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @param listener the listener to be notified upon request completion
- * @deprecated use {@link #scrollAsync(SearchScrollRequest, RequestOptions, ActionListener)} instead
- * @return cancellable that may be used to cancel the request
- */
- @Deprecated
- public final Cancellable searchScrollAsync(
- SearchScrollRequest searchScrollRequest,
- RequestOptions options,
- ActionListener listener
- ) {
- return scrollAsync(searchScrollRequest, options, listener);
- }
-
- /**
- * Asynchronously executes a search using the Search Scroll API.
- * See Search
- * Scroll API on elastic.co
- * @param searchScrollRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @param listener the listener to be notified upon request completion
- * @return cancellable that may be used to cancel the request
- */
- public final Cancellable scrollAsync(
- SearchScrollRequest searchScrollRequest,
- RequestOptions options,
- ActionListener listener
- ) {
- return performRequestAsyncAndParseEntity(
- searchScrollRequest,
- RequestConverters::searchScroll,
- options,
- SearchResponse::fromXContent,
- listener,
- emptySet()
- );
- }
-
- /**
- * Executes a request using the Explain API.
- * See Explain API on elastic.co
- * @param explainRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final ExplainResponse explain(ExplainRequest explainRequest, RequestOptions options) throws IOException {
- return performRequest(explainRequest, RequestConverters::explain, options, response -> {
- CheckedFunction entityParser = parser -> ExplainResponse.fromXContent(
- parser,
- convertExistsResponse(response)
- );
- return parseEntity(response.getEntity(), entityParser);
- }, singleton(404));
- }
-
- /**
- * Calls the Term Vectors API
- *
- * See Term Vectors API on
- * elastic.co
- *
- * @param request the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- */
- public final TermVectorsResponse termvectors(TermVectorsRequest request, RequestOptions options) throws IOException {
- return performRequestAndParseEntity(
- request,
- RequestConverters::termVectors,
- options,
- TermVectorsResponse::fromXContent,
- emptySet()
- );
- }
-
- /**
- * Executes a request using the Field Capabilities API.
- * See Field Capabilities API
- * on elastic.co.
- * @param fieldCapabilitiesRequest the request
- * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
- * @return the response
- */
- public final FieldCapabilitiesResponse fieldCaps(FieldCapabilitiesRequest fieldCapabilitiesRequest, RequestOptions options)
- throws IOException {
- return performRequestAndParseEntity(
- fieldCapabilitiesRequest,
- RequestConverters::fieldCaps,
- options,
- FieldCapabilitiesResponse::fromXContent,
- emptySet()
- );
- }
-
/**
* @deprecated If creating a new HLRC ReST API call, consider creating new actions instead of reusing server actions. The Validation
* layer has been added to the ReST client, and requests should extend {@link Validatable} instead of {@link ActionRequest}.
@@ -887,19 +415,6 @@ protected final Resp performRequestAndParseEnt
return performRequest(request, requestConverter, options, response -> parseEntity(response.getEntity(), entityParser), ignores);
}
- /**
- * Defines a helper method for performing a request and then parsing the returned entity using the provided entityParser.
- */
- protected final Resp performRequestAndParseEntity(
- Req request,
- CheckedFunction requestConverter,
- RequestOptions options,
- CheckedFunction entityParser,
- Set ignores
- ) throws IOException {
- return performRequest(request, requestConverter, options, response -> parseEntity(response.getEntity(), entityParser), ignores);
- }
-
/**
* @deprecated If creating a new HLRC ReST API call, consider creating new actions instead of reusing server actions. The Validation
* layer has been added to the ReST client, and requests should extend {@link Validatable} instead of {@link ActionRequest}.
@@ -1019,26 +534,6 @@ protected final Cancellable performRequestAsyn
return internalPerformRequestAsync(request, requestConverter, options, responseConverter, listener, ignores);
}
- /**
- * Defines a helper method for asynchronously performing a request.
- * @return Cancellable instance that may be used to cancel the request
- */
- protected final Cancellable performRequestAsync(
- Req request,
- CheckedFunction requestConverter,
- RequestOptions options,
- CheckedFunction responseConverter,
- ActionListener listener,
- Set ignores
- ) {
- Optional validationException = request.validate();
- if (validationException != null && validationException.isPresent()) {
- listener.onFailure(validationException.get());
- return Cancellable.NO_OP;
- }
- return internalPerformRequestAsync(request, requestConverter, options, responseConverter, listener, ignores);
- }
-
/**
* Provides common functionality for asynchronously performing a request.
* @return Cancellable instance that may be used to cancel the request
@@ -1104,37 +599,6 @@ public void onFailure(Exception exception) {
};
}
- final ResponseListener wrapResponseListener404sOptional(
- CheckedFunction responseConverter,
- ActionListener> actionListener
- ) {
- return new ResponseListener() {
- @Override
- public void onSuccess(Response response) {
- try {
- actionListener.onResponse(Optional.of(responseConverter.apply(response)));
- } catch (Exception e) {
- IOException ioe = new IOException("Unable to parse response body for " + response, e);
- onFailure(ioe);
- }
- }
-
- @Override
- public void onFailure(Exception exception) {
- if (exception instanceof ResponseException responseException) {
- Response response = responseException.getResponse();
- if (RestStatus.NOT_FOUND.getStatus() == response.getStatusLine().getStatusCode()) {
- actionListener.onResponse(Optional.empty());
- } else {
- actionListener.onFailure(parseResponseException(responseException));
- }
- } else {
- actionListener.onFailure(exception);
- }
- }
- };
- }
-
/**
* Converts a {@link ResponseException} obtained from the low level REST client into an {@link ElasticsearchException}.
* If a response body was returned, tries to parse it as an error returned from Elasticsearch.
@@ -1179,10 +643,6 @@ protected final Resp parseEntity(final HttpEntity entity, final CheckedFu
}
}
- protected static boolean convertExistsResponse(Response response) {
- return response.getStatusLine().getStatusCode() == 200;
- }
-
private enum EntityType {
JSON() {
@Override
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RethrottleRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RethrottleRequest.java
deleted file mode 100644
index a518d74b14c2..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RethrottleRequest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client;
-
-import org.elasticsearch.tasks.TaskId;
-
-import java.util.Objects;
-
-/**
- * A request changing throttling of a task.
- */
-public class RethrottleRequest implements Validatable {
-
- static final String REQUEST_PER_SECOND_PARAMETER = "requests_per_second";
-
- private final TaskId taskId;
- private final float requestsPerSecond;
-
- /**
- * Create a new {@link RethrottleRequest} which disables any throttling for the given taskId.
- * @param taskId the task for which throttling will be disabled
- */
- public RethrottleRequest(TaskId taskId) {
- this.taskId = taskId;
- this.requestsPerSecond = Float.POSITIVE_INFINITY;
- }
-
- /**
- * Create a new {@link RethrottleRequest} which changes the throttling for the given taskId.
- * @param taskId the task that throttling changes will be applied to
- * @param requestsPerSecond the number of requests per second that the task should perform. This needs to be a positive value.
- */
- public RethrottleRequest(TaskId taskId, float requestsPerSecond) {
- Objects.requireNonNull(taskId, "taskId cannot be null");
- if (requestsPerSecond <= 0) {
- throw new IllegalArgumentException("requestsPerSecond needs to be positive value but was [" + requestsPerSecond + "]");
- }
- this.taskId = taskId;
- this.requestsPerSecond = requestsPerSecond;
- }
-
- /**
- * @return the task Id
- */
- public TaskId getTaskId() {
- return taskId;
- }
-
- /**
- * @return the requests per seconds value
- */
- public float getRequestsPerSecond() {
- return requestsPerSecond;
- }
-
- @Override
- public String toString() {
- return "RethrottleRequest: taskID = " + taskId + "; reqestsPerSecond = " + requestsPerSecond;
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/TimedRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/TimedRequest.java
deleted file mode 100644
index a3135b9725eb..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/TimedRequest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-package org.elasticsearch.client;
-
-import org.elasticsearch.core.TimeValue;
-
-import static org.elasticsearch.core.TimeValue.timeValueSeconds;
-
-/**
- * A base request for any requests that supply timeouts.
- *
- * Please note, any requests that use a ackTimeout should set timeout as they
- * represent the same backing field on the server.
- */
-public abstract class TimedRequest implements Validatable {
-
- public static final TimeValue DEFAULT_ACK_TIMEOUT = timeValueSeconds(30);
- public static final TimeValue DEFAULT_MASTER_NODE_TIMEOUT = TimeValue.timeValueSeconds(30);
-
- private TimeValue timeout = DEFAULT_ACK_TIMEOUT;
- private TimeValue masterTimeout = DEFAULT_MASTER_NODE_TIMEOUT;
-
- /**
- * Sets the timeout to wait for the all the nodes to acknowledge
- * @param timeout timeout as a {@link TimeValue}
- */
- public void setTimeout(TimeValue timeout) {
- this.timeout = timeout;
- }
-
- /**
- * Sets the timeout to connect to the master node
- * @param masterTimeout timeout as a {@link TimeValue}
- */
- public void setMasterTimeout(TimeValue masterTimeout) {
- this.masterTimeout = masterTimeout;
- }
-
- /**
- * Returns the request timeout
- */
- public TimeValue timeout() {
- return timeout;
- }
-
- /**
- * Returns the timeout for the request to be completed on the master node
- */
- public TimeValue masterNodeTimeout() {
- return masterTimeout;
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/analytics/StringStatsAggregationBuilder.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/analytics/StringStatsAggregationBuilder.java
index e1dc45e65086..981e6de9c941 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/analytics/StringStatsAggregationBuilder.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/analytics/StringStatsAggregationBuilder.java
@@ -8,7 +8,7 @@
package org.elasticsearch.client.analytics;
-import org.elasticsearch.Version;
+import org.elasticsearch.TransportVersion;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.index.query.QueryRewriteContext;
@@ -124,7 +124,7 @@ public boolean equals(Object obj) {
}
@Override
- public Version getMinimalSupportedVersion() {
- return Version.V_EMPTY;
+ public TransportVersion getMinimalSupportedVersion() {
+ return TransportVersion.ZERO;
}
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/analytics/TopMetricsAggregationBuilder.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/analytics/TopMetricsAggregationBuilder.java
index eb3d9cf0452c..5af136f75bb7 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/analytics/TopMetricsAggregationBuilder.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/analytics/TopMetricsAggregationBuilder.java
@@ -8,7 +8,7 @@
package org.elasticsearch.client.analytics;
-import org.elasticsearch.Version;
+import org.elasticsearch.TransportVersion;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.index.query.QueryRewriteContext;
@@ -101,7 +101,7 @@ protected AggregationBuilder shallowCopy(Builder factoriesBuilder, Map validate() {
- return Optional.empty();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- GetAsyncSearchRequest request = (GetAsyncSearchRequest) o;
- return Objects.equals(getId(), request.getId())
- && Objects.equals(getKeepAlive(), request.getKeepAlive())
- && Objects.equals(getWaitForCompletion(), request.getWaitForCompletion());
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(getId(), getKeepAlive(), getWaitForCompletion());
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/asyncsearch/SubmitAsyncSearchRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/asyncsearch/SubmitAsyncSearchRequest.java
deleted file mode 100644
index 9c381645d6ff..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/asyncsearch/SubmitAsyncSearchRequest.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.asyncsearch;
-
-import org.elasticsearch.action.search.SearchRequest;
-import org.elasticsearch.action.search.SearchType;
-import org.elasticsearch.action.support.IndicesOptions;
-import org.elasticsearch.client.Validatable;
-import org.elasticsearch.client.ValidationException;
-import org.elasticsearch.core.TimeValue;
-import org.elasticsearch.search.builder.SearchSourceBuilder;
-
-import java.util.Objects;
-import java.util.Optional;
-
-/**
- * A request to track asynchronously the progress of a search against one or more indices.
- */
-public class SubmitAsyncSearchRequest implements Validatable {
-
- public static long MIN_KEEP_ALIVE = TimeValue.timeValueMinutes(1).millis();
-
- private TimeValue waitForCompletionTimeout;
- private Boolean keepOnCompletion;
- private TimeValue keepAlive;
- private final SearchRequest searchRequest;
- // The following is optional and will only be sent down with the request if explicitely set by the user
- private Integer batchedReduceSize;
-
- /**
- * Creates a new request
- */
- public SubmitAsyncSearchRequest(SearchSourceBuilder source, String... indices) {
- this.searchRequest = new SearchRequest(indices, source);
- }
-
- /**
- * Get the target indices
- */
- public String[] getIndices() {
- return this.searchRequest.indices();
- }
-
- /**
- * Get the minimum time that the request should wait before returning a partial result (defaults to 1 second).
- */
- public TimeValue getWaitForCompletionTimeout() {
- return waitForCompletionTimeout;
- }
-
- /**
- * Sets the minimum time that the request should wait before returning a partial result (defaults to 1 second).
- */
- public void setWaitForCompletionTimeout(TimeValue waitForCompletionTimeout) {
- this.waitForCompletionTimeout = waitForCompletionTimeout;
- }
-
- /**
- * Returns whether the resource resource should be kept on completion or failure (defaults to false).
- */
- public Boolean isKeepOnCompletion() {
- return keepOnCompletion;
- }
-
- /**
- * Determines if the resource should be kept on completion or failure (defaults to false).
- */
- public void setKeepOnCompletion(boolean keepOnCompletion) {
- this.keepOnCompletion = keepOnCompletion;
- }
-
- /**
- * Get the amount of time after which the result will expire (defaults to 5 days).
- */
- public TimeValue getKeepAlive() {
- return keepAlive;
- }
-
- /**
- * Sets the amount of time after which the result will expire (defaults to 5 days).
- */
- public void setKeepAlive(TimeValue keepAlive) {
- this.keepAlive = keepAlive;
- }
-
- // setters for request parameters of the wrapped SearchRequest
- /**
- * Set the routing value to control the shards that the search will be executed on.
- * A comma separated list of routing values to control the shards the search will be executed on.
- */
- public void setRouting(String routing) {
- this.searchRequest.routing(routing);
- }
-
- /**
- * Set the routing values to control the shards that the search will be executed on.
- */
- public void setRoutings(String... routings) {
- this.searchRequest.routing(routings);
- }
-
- /**
- * Get the routing value to control the shards that the search will be executed on.
- */
- public String getRouting() {
- return this.searchRequest.routing();
- }
-
- /**
- * Sets the preference to execute the search. Defaults to randomize across shards. Can be set to
- * {@code _local} to prefer local shards or a custom value, which guarantees that the same order
- * will be used across different requests.
- */
- public void setPreference(String preference) {
- this.searchRequest.preference(preference);
- }
-
- /**
- * Get the preference to execute the search.
- */
- public String getPreference() {
- return this.searchRequest.preference();
- }
-
- /**
- * Specifies what type of requested indices to ignore and how to deal with indices wildcard expressions.
- */
- public void setIndicesOptions(IndicesOptions indicesOptions) {
- this.searchRequest.indicesOptions(indicesOptions);
- }
-
- /**
- * Get the indices Options.
- */
- public IndicesOptions getIndicesOptions() {
- return this.searchRequest.indicesOptions();
- }
-
- /**
- * The search type to execute, defaults to {@link SearchType#DEFAULT}.
- */
- public void setSearchType(SearchType searchType) {
- this.searchRequest.searchType(searchType);
- }
-
- /**
- * Get the search type to execute, defaults to {@link SearchType#DEFAULT}.
- */
- public SearchType getSearchType() {
- return this.searchRequest.searchType();
- }
-
- /**
- * Sets if this request should allow partial results. (If method is not called,
- * will default to the cluster level setting).
- */
- public void setAllowPartialSearchResults(boolean allowPartialSearchResults) {
- this.searchRequest.allowPartialSearchResults(allowPartialSearchResults);
- }
-
- /**
- * Gets if this request should allow partial results.
- */
- public Boolean getAllowPartialSearchResults() {
- return this.searchRequest.allowPartialSearchResults();
- }
-
- /**
- * Optional. Sets the number of shard results that should be reduced at once on the coordinating node.
- * This value should be used as a protection mechanism to reduce the memory overhead per search
- * request if the potential number of shards in the request can be large. Defaults to 5.
- */
- public void setBatchedReduceSize(int batchedReduceSize) {
- this.batchedReduceSize = batchedReduceSize;
- }
-
- /**
- * Gets the number of shard results that should be reduced at once on the coordinating node.
- * Returns {@code null} if unset.
- */
- public Integer getBatchedReduceSize() {
- return this.batchedReduceSize;
- }
-
- /**
- * Sets if this request should use the request cache or not, assuming that it can (for
- * example, if "now" is used, it will never be cached).
- * By default (if not set) this is turned on for {@link SubmitAsyncSearchRequest}.
- */
- public void setRequestCache(Boolean requestCache) {
- this.searchRequest.requestCache(requestCache);
- }
-
- /**
- * Gets if this request should use the request cache or not, if set.
- * This defaults to `true` on the server side if unset in the client.
- */
- public Boolean getRequestCache() {
- return this.searchRequest.requestCache();
- }
-
- /**
- * Returns the number of shard requests that should be executed concurrently on a single node.
- * The default is {@code 5}.
- */
- public int getMaxConcurrentShardRequests() {
- return this.searchRequest.getMaxConcurrentShardRequests();
- }
-
- /**
- * Sets the number of shard requests that should be executed concurrently on a single node.
- * The default is {@code 5}.
- */
- public void setMaxConcurrentShardRequests(int maxConcurrentShardRequests) {
- this.searchRequest.setMaxConcurrentShardRequests(maxConcurrentShardRequests);
- }
-
- /**
- * Gets if the source of the {@link SearchSourceBuilder} initially used on this request.
- */
- public SearchSourceBuilder getSearchSource() {
- return this.searchRequest.source();
- }
-
- @Override
- public Optional validate() {
- final ValidationException validationException = new ValidationException();
- if (searchRequest.isSuggestOnly()) {
- validationException.addValidationError("suggest-only queries are not supported");
- }
- if (keepAlive != null && keepAlive.getMillis() < MIN_KEEP_ALIVE) {
- validationException.addValidationError("[keep_alive] must be greater than 1 minute, got: " + keepAlive.toString());
- }
- if (validationException.validationErrors().isEmpty()) {
- return Optional.empty();
- }
- return Optional.of(validationException);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- SubmitAsyncSearchRequest request = (SubmitAsyncSearchRequest) o;
- return Objects.equals(searchRequest, request.searchRequest)
- && Objects.equals(getKeepAlive(), request.getKeepAlive())
- && Objects.equals(getWaitForCompletionTimeout(), request.getWaitForCompletionTimeout())
- && Objects.equals(isKeepOnCompletion(), request.isKeepOnCompletion());
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(searchRequest, getKeepAlive(), getWaitForCompletionTimeout(), isKeepOnCompletion());
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/ProxyModeInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/ProxyModeInfo.java
deleted file mode 100644
index 0e55c232cf3f..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/ProxyModeInfo.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.cluster;
-
-import java.util.Objects;
-
-public class ProxyModeInfo implements RemoteConnectionInfo.ModeInfo {
- static final String NAME = "proxy";
- static final String PROXY_ADDRESS = "proxy_address";
- static final String SERVER_NAME = "server_name";
- static final String NUM_PROXY_SOCKETS_CONNECTED = "num_proxy_sockets_connected";
- static final String MAX_PROXY_SOCKET_CONNECTIONS = "max_proxy_socket_connections";
- private final String address;
- private final String serverName;
- private final int maxSocketConnections;
- private final int numSocketsConnected;
-
- ProxyModeInfo(String address, String serverName, int maxSocketConnections, int numSocketsConnected) {
- this.address = address;
- this.serverName = serverName;
- this.maxSocketConnections = maxSocketConnections;
- this.numSocketsConnected = numSocketsConnected;
- }
-
- @Override
- public boolean isConnected() {
- return numSocketsConnected > 0;
- }
-
- @Override
- public String modeName() {
- return NAME;
- }
-
- public String getAddress() {
- return address;
- }
-
- public String getServerName() {
- return serverName;
- }
-
- public int getMaxSocketConnections() {
- return maxSocketConnections;
- }
-
- public int getNumSocketsConnected() {
- return numSocketsConnected;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- ProxyModeInfo otherProxy = (ProxyModeInfo) o;
- return maxSocketConnections == otherProxy.maxSocketConnections
- && numSocketsConnected == otherProxy.numSocketsConnected
- && Objects.equals(address, otherProxy.address)
- && Objects.equals(serverName, otherProxy.serverName);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(address, serverName, maxSocketConnections, numSocketsConnected);
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteConnectionInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteConnectionInfo.java
deleted file mode 100644
index f5069d7771d7..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteConnectionInfo.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.cluster;
-
-import org.elasticsearch.xcontent.ConstructingObjectParser;
-import org.elasticsearch.xcontent.ParseField;
-import org.elasticsearch.xcontent.XContentParser;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Objects;
-
-import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
-import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg;
-
-/**
- * This class encapsulates all remote cluster information to be rendered on
- * {@code _remote/info} requests.
- */
-public final class RemoteConnectionInfo {
- private static final String CONNECTED = "connected";
- private static final String MODE = "mode";
- private static final String INITIAL_CONNECT_TIMEOUT = "initial_connect_timeout";
- private static final String SKIP_UNAVAILABLE = "skip_unavailable";
-
- @SuppressWarnings("unchecked")
- private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- "RemoteConnectionInfoObjectParser",
- false,
- (args, clusterAlias) -> {
- String mode = (String) args[1];
- ModeInfo modeInfo;
- if (mode.equals(ProxyModeInfo.NAME)) {
- modeInfo = new ProxyModeInfo((String) args[4], (String) args[5], (int) args[6], (int) args[7]);
- } else if (mode.equals(SniffModeInfo.NAME)) {
- modeInfo = new SniffModeInfo((List) args[8], (int) args[9], (int) args[10]);
- } else {
- throw new IllegalArgumentException("mode cannot be " + mode);
- }
- return new RemoteConnectionInfo(clusterAlias, modeInfo, (String) args[2], (boolean) args[3]);
- }
- );
-
- static {
- PARSER.declareBoolean(constructorArg(), new ParseField(CONNECTED));
- PARSER.declareString(constructorArg(), new ParseField(MODE));
- PARSER.declareString(constructorArg(), new ParseField(INITIAL_CONNECT_TIMEOUT));
- PARSER.declareBoolean(constructorArg(), new ParseField(SKIP_UNAVAILABLE));
-
- PARSER.declareString(optionalConstructorArg(), new ParseField(ProxyModeInfo.PROXY_ADDRESS));
- PARSER.declareString(optionalConstructorArg(), new ParseField(ProxyModeInfo.SERVER_NAME));
- PARSER.declareInt(optionalConstructorArg(), new ParseField(ProxyModeInfo.MAX_PROXY_SOCKET_CONNECTIONS));
- PARSER.declareInt(optionalConstructorArg(), new ParseField(ProxyModeInfo.NUM_PROXY_SOCKETS_CONNECTED));
-
- PARSER.declareStringArray(optionalConstructorArg(), new ParseField(SniffModeInfo.SEEDS));
- PARSER.declareInt(optionalConstructorArg(), new ParseField(SniffModeInfo.MAX_CONNECTIONS_PER_CLUSTER));
- PARSER.declareInt(optionalConstructorArg(), new ParseField(SniffModeInfo.NUM_NODES_CONNECTED));
- }
-
- private final ModeInfo modeInfo;
- // TODO: deprecate and remove this field in favor of initialConnectionTimeout field that is of type TimeValue.
- // When rest api versioning exists then change org.elasticsearch.transport.RemoteConnectionInfo to properly serialize
- // the initialConnectionTimeout field so that we can properly parse initialConnectionTimeout as TimeValue
- private final String initialConnectionTimeoutString;
- private final String clusterAlias;
- private final boolean skipUnavailable;
-
- RemoteConnectionInfo(String clusterAlias, ModeInfo modeInfo, String initialConnectionTimeoutString, boolean skipUnavailable) {
- this.clusterAlias = clusterAlias;
- this.modeInfo = modeInfo;
- this.initialConnectionTimeoutString = initialConnectionTimeoutString;
- this.skipUnavailable = skipUnavailable;
- }
-
- public boolean isConnected() {
- return modeInfo.isConnected();
- }
-
- public String getClusterAlias() {
- return clusterAlias;
- }
-
- public ModeInfo getModeInfo() {
- return modeInfo;
- }
-
- public String getInitialConnectionTimeoutString() {
- return initialConnectionTimeoutString;
- }
-
- public boolean isSkipUnavailable() {
- return skipUnavailable;
- }
-
- public static RemoteConnectionInfo fromXContent(XContentParser parser, String clusterAlias) throws IOException {
- return PARSER.parse(parser, clusterAlias);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- RemoteConnectionInfo that = (RemoteConnectionInfo) o;
- return skipUnavailable == that.skipUnavailable
- && Objects.equals(modeInfo, that.modeInfo)
- && Objects.equals(initialConnectionTimeoutString, that.initialConnectionTimeoutString)
- && Objects.equals(clusterAlias, that.clusterAlias);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(modeInfo, initialConnectionTimeoutString, clusterAlias, skipUnavailable);
- }
-
- public interface ModeInfo {
-
- boolean isConnected();
-
- String modeName();
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoRequest.java
deleted file mode 100644
index 7672c1054c04..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoRequest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-package org.elasticsearch.client.cluster;
-
-import org.elasticsearch.client.Validatable;
-
-/**
- * The request object used by the Remote cluster info API.
- */
-public final class RemoteInfoRequest implements Validatable {
-
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoResponse.java
deleted file mode 100644
index 9aff43bf3871..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoResponse.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-package org.elasticsearch.client.cluster;
-
-import org.elasticsearch.xcontent.XContentParser;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
-
-/**
- * A response to _remote/info API request.
- */
-public final class RemoteInfoResponse {
-
- private List infos;
-
- RemoteInfoResponse(Collection infos) {
- this.infos = List.copyOf(infos);
- }
-
- public List getInfos() {
- return infos;
- }
-
- public static RemoteInfoResponse fromXContent(XContentParser parser) throws IOException {
- ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
-
- List infos = new ArrayList<>();
-
- XContentParser.Token token;
- while ((token = parser.nextToken()) == XContentParser.Token.FIELD_NAME) {
- String clusterAlias = parser.currentName();
- RemoteConnectionInfo info = RemoteConnectionInfo.fromXContent(parser, clusterAlias);
- infos.add(info);
- }
- ensureExpectedToken(XContentParser.Token.END_OBJECT, token, parser);
- return new RemoteInfoResponse(infos);
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/SniffModeInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/SniffModeInfo.java
deleted file mode 100644
index e08509dd14b6..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/SniffModeInfo.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.cluster;
-
-import java.util.List;
-import java.util.Objects;
-
-public class SniffModeInfo implements RemoteConnectionInfo.ModeInfo {
- public static final String NAME = "sniff";
- static final String SEEDS = "seeds";
- static final String NUM_NODES_CONNECTED = "num_nodes_connected";
- static final String MAX_CONNECTIONS_PER_CLUSTER = "max_connections_per_cluster";
- final List seedNodes;
- final int maxConnectionsPerCluster;
- final int numNodesConnected;
-
- SniffModeInfo(List seedNodes, int maxConnectionsPerCluster, int numNodesConnected) {
- this.seedNodes = seedNodes;
- this.maxConnectionsPerCluster = maxConnectionsPerCluster;
- this.numNodesConnected = numNodesConnected;
- }
-
- @Override
- public boolean isConnected() {
- return numNodesConnected > 0;
- }
-
- @Override
- public String modeName() {
- return NAME;
- }
-
- public List getSeedNodes() {
- return seedNodes;
- }
-
- public int getMaxConnectionsPerCluster() {
- return maxConnectionsPerCluster;
- }
-
- public int getNumNodesConnected() {
- return numNodesConnected;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- SniffModeInfo sniff = (SniffModeInfo) o;
- return maxConnectionsPerCluster == sniff.maxConnectionsPerCluster
- && numNodesConnected == sniff.numNodesConnected
- && Objects.equals(seedNodes, sniff.seedNodes);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(seedNodes, maxConnectionsPerCluster, numNodesConnected);
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/BroadcastResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/BroadcastResponse.java
deleted file mode 100644
index ef3b35a0896d..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/BroadcastResponse.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.action.support.DefaultShardOperationFailedException;
-import org.elasticsearch.xcontent.ConstructingObjectParser;
-import org.elasticsearch.xcontent.ParseField;
-import org.elasticsearch.xcontent.XContentParser;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Objects;
-
-/**
- * Represents a response to a request that is broadcast to a collection of shards.
- */
-public class BroadcastResponse {
-
- private final Shards shards;
-
- /**
- * Represents the shard-level summary of the response execution.
- *
- * @return the shard-level response summary
- */
- public Shards shards() {
- return shards;
- }
-
- protected BroadcastResponse(final Shards shards) {
- this.shards = Objects.requireNonNull(shards);
- }
-
- private static final ParseField SHARDS_FIELD = new ParseField("_shards");
-
- static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- "broadcast_response",
- a -> new BroadcastResponse((Shards) a[0])
- );
-
- static {
- declareShardsField(PARSER);
- }
-
- /**
- * Parses a broadcast response.
- *
- * @param parser the parser
- * @return a broadcast response parsed from the specified parser
- * @throws IOException if an I/O exception occurs parsing the response
- */
- public static BroadcastResponse fromXContent(final XContentParser parser) throws IOException {
- return PARSER.parse(parser, null);
- }
-
- protected static void declareShardsField(ConstructingObjectParser parser) {
- parser.declareObject(ConstructingObjectParser.constructorArg(), Shards.SHARDS_PARSER, SHARDS_FIELD);
- }
-
- /**
- * Represents the results of a collection of shards on which a request was executed against.
- */
- public static class Shards {
-
- private final int total;
-
- /**
- * The total number of shards on which a request was executed against.
- *
- * @return the total number of shards
- */
- public int total() {
- return total;
- }
-
- private final int successful;
-
- /**
- * The number of successful shards on which a request was executed against.
- *
- * @return the number of successful shards
- */
- public int successful() {
- return successful;
- }
-
- private final int skipped;
-
- /**
- * The number of shards skipped by the request.
- *
- * @return the number of skipped shards
- */
- public int skipped() {
- return skipped;
- }
-
- private final int failed;
-
- /**
- * The number of shards on which a request failed to be executed against.
- *
- * @return the number of failed shards
- */
- public int failed() {
- return failed;
- }
-
- private final Collection failures;
-
- /**
- * The failures corresponding to the shards on which a request failed to be executed against. Note that the number of failures might
- * not match {@link #failed()} as some responses group together shard failures.
- *
- * @return the failures
- */
- public Collection failures() {
- return failures;
- }
-
- Shards(
- final int total,
- final int successful,
- final int skipped,
- final int failed,
- final Collection failures
- ) {
- this.total = total;
- this.successful = successful;
- this.skipped = skipped;
- this.failed = failed;
- this.failures = Collections.unmodifiableCollection(Objects.requireNonNull(failures));
- }
-
- private static final ParseField TOTAL_FIELD = new ParseField("total");
- private static final ParseField SUCCESSFUL_FIELD = new ParseField("successful");
- private static final ParseField SKIPPED_FIELD = new ParseField("skipped");
- private static final ParseField FAILED_FIELD = new ParseField("failed");
- private static final ParseField FAILURES_FIELD = new ParseField("failures");
-
- @SuppressWarnings("unchecked")
- static final ConstructingObjectParser SHARDS_PARSER = new ConstructingObjectParser<>(
- "shards",
- a -> new Shards(
- (int) a[0], // total
- (int) a[1], // successful
- a[2] == null ? 0 : (int) a[2], // skipped
- (int) a[3], // failed
- a[4] == null ? Collections.emptyList() : (Collection) a[4]
- )
- ); // failures
-
- static {
- SHARDS_PARSER.declareInt(ConstructingObjectParser.constructorArg(), TOTAL_FIELD);
- SHARDS_PARSER.declareInt(ConstructingObjectParser.constructorArg(), SUCCESSFUL_FIELD);
- SHARDS_PARSER.declareInt(ConstructingObjectParser.optionalConstructorArg(), SKIPPED_FIELD);
- SHARDS_PARSER.declareInt(ConstructingObjectParser.constructorArg(), FAILED_FIELD);
- SHARDS_PARSER.declareObjectArray(
- ConstructingObjectParser.optionalConstructorArg(),
- DefaultShardOperationFailedException.PARSER,
- FAILURES_FIELD
- );
- }
-
- }
-
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/CountRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/CountRequest.java
deleted file mode 100644
index 0899eb03311d..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/CountRequest.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.action.support.IndicesOptions;
-import org.elasticsearch.client.Validatable;
-import org.elasticsearch.common.Strings;
-import org.elasticsearch.index.query.QueryBuilder;
-import org.elasticsearch.search.builder.SearchSourceBuilder;
-import org.elasticsearch.search.internal.SearchContext;
-import org.elasticsearch.xcontent.ToXContentObject;
-import org.elasticsearch.xcontent.XContentBuilder;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Objects;
-
-/**
- * Encapsulates a request to _count API against one, several or all indices.
- */
-public final class CountRequest implements Validatable, ToXContentObject {
-
- private String[] indices = Strings.EMPTY_ARRAY;
- private String[] types = Strings.EMPTY_ARRAY;
- private String routing;
- private String preference;
- private QueryBuilder query;
- private IndicesOptions indicesOptions;
- private int terminateAfter = SearchContext.DEFAULT_TERMINATE_AFTER;
- private Float minScore;
-
- public CountRequest() {}
-
- /**
- * Constructs a new count request against the indices. No indices provided here means that count will execute on all indices.
- */
- public CountRequest(String... indices) {
- indices(indices);
- }
-
- /**
- * Constructs a new search request against the provided indices with the given search source.
- *
- * @deprecated The count api only supports a query. Use {@link #CountRequest(String[], QueryBuilder)} instead.
- */
- @Deprecated
- public CountRequest(String[] indices, SearchSourceBuilder searchSourceBuilder) {
- indices(indices);
- this.query = Objects.requireNonNull(searchSourceBuilder, "source must not be null").query();
- }
-
- /**
- * Constructs a new search request against the provided indices with the given query.
- */
- public CountRequest(String[] indices, QueryBuilder query) {
- indices(indices);
- this.query = Objects.requireNonNull(query, "query must not be null");
- ;
- }
-
- /**
- * Sets the indices the count will be executed on.
- */
- public CountRequest indices(String... indices) {
- Objects.requireNonNull(indices, "indices must not be null");
- for (String index : indices) {
- Objects.requireNonNull(index, "index must not be null");
- }
- this.indices = indices;
- return this;
- }
-
- /**
- * The source of the count request.
- *
- * @deprecated The count api only supports a query. Use {@link #query(QueryBuilder)} instead.
- */
- @Deprecated
- public CountRequest source(SearchSourceBuilder searchSourceBuilder) {
- this.query = Objects.requireNonNull(searchSourceBuilder, "source must not be null").query();
- return this;
- }
-
- /**
- * Sets the query to execute for this count request.
- */
- public CountRequest query(QueryBuilder query) {
- this.query = Objects.requireNonNull(query, "query must not be null");
- return this;
- }
-
- /**
- * The document types to execute the count against. Defaults to be executed against all types.
- *
- * @deprecated Types are in the process of being removed. Instead of using a type, prefer to
- * filter on a field on the document.
- */
- @Deprecated
- public CountRequest types(String... types) {
- Objects.requireNonNull(types, "types must not be null");
- for (String type : types) {
- Objects.requireNonNull(type, "type must not be null");
- }
- this.types = types;
- return this;
- }
-
- /**
- * The routing values to control the shards that the search will be executed on.
- */
- public CountRequest routing(String routing) {
- this.routing = routing;
- return this;
- }
-
- /**
- * A comma separated list of routing values to control the shards the count will be executed on.
- */
- public CountRequest routing(String... routings) {
- this.routing = Strings.arrayToCommaDelimitedString(routings);
- return this;
- }
-
- /**
- * Returns the indices options used to resolve indices. They tell for instance whether a single index is accepted, whether an empty
- * array will be converted to _all, and how wildcards will be expanded if needed.
- *
- * @see org.elasticsearch.action.support.IndicesOptions
- */
- public CountRequest indicesOptions(IndicesOptions indicesOptions) {
- this.indicesOptions = Objects.requireNonNull(indicesOptions, "indicesOptions must not be null");
- return this;
- }
-
- /**
- * Sets the preference to execute the count. Defaults to randomize across shards. Can be set to {@code _local} to prefer local shards
- * or a custom value, which guarantees that the same order will be used across different requests.
- */
- public CountRequest preference(String preference) {
- this.preference = preference;
- return this;
- }
-
- public IndicesOptions indicesOptions() {
- return this.indicesOptions;
- }
-
- public String routing() {
- return this.routing;
- }
-
- public String preference() {
- return this.preference;
- }
-
- public String[] indices() {
- return Arrays.copyOf(this.indices, this.indices.length);
- }
-
- public Float minScore() {
- return minScore;
- }
-
- public CountRequest minScore(Float minScore) {
- this.minScore = minScore;
- return this;
- }
-
- public int terminateAfter() {
- return this.terminateAfter;
- }
-
- public CountRequest terminateAfter(int terminateAfter) {
- if (terminateAfter < 0) {
- throw new IllegalArgumentException("terminateAfter must be > 0");
- }
- this.terminateAfter = terminateAfter;
- return this;
- }
-
- /**
- * @deprecated Types are in the process of being removed. Instead of using a type, prefer to
- * filter on a field on the document.
- */
- @Deprecated
- public String[] types() {
- return Arrays.copyOf(this.types, this.types.length);
- }
-
- /**
- * @return the source builder
- * @deprecated The count api only supports a query. Use {@link #query()} instead.
- */
- @Deprecated
- public SearchSourceBuilder source() {
- return new SearchSourceBuilder().query(query);
- }
-
- /**
- * @return The provided query to execute with the count request or
- * null if no query was provided.
- */
- public QueryBuilder query() {
- return query;
- }
-
- @Override
- public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
- builder.startObject();
- if (query != null) {
- builder.field("query", query);
- }
- builder.endObject();
- return builder;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- CountRequest that = (CountRequest) o;
- return Objects.equals(indicesOptions, that.indicesOptions)
- && Arrays.equals(indices, that.indices)
- && Arrays.equals(types, that.types)
- && Objects.equals(routing, that.routing)
- && Objects.equals(preference, that.preference)
- && Objects.equals(terminateAfter, that.terminateAfter)
- && Objects.equals(minScore, that.minScore)
- && Objects.equals(query, that.query);
- }
-
- @Override
- public int hashCode() {
- int result = Objects.hash(indicesOptions, routing, preference, terminateAfter, minScore, query);
- result = 31 * result + Arrays.hashCode(indices);
- result = 31 * result + Arrays.hashCode(types);
- return result;
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/CountResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/CountResponse.java
deleted file mode 100644
index c19245c4d09f..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/CountResponse.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.action.search.ShardSearchFailure;
-import org.elasticsearch.rest.RestStatus;
-import org.elasticsearch.xcontent.ParseField;
-import org.elasticsearch.xcontent.XContentParser;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
-
-/**
- * A response to _count API request.
- */
-public final class CountResponse {
-
- static final ParseField COUNT = new ParseField("count");
- static final ParseField TERMINATED_EARLY = new ParseField("terminated_early");
- static final ParseField SHARDS = new ParseField("_shards");
-
- private final long count;
- private final Boolean terminatedEarly;
- private final ShardStats shardStats;
-
- public CountResponse(long count, Boolean terminatedEarly, ShardStats shardStats) {
- this.count = count;
- this.terminatedEarly = terminatedEarly;
- this.shardStats = shardStats;
- }
-
- public ShardStats getShardStats() {
- return shardStats;
- }
-
- /**
- * Number of documents matching request.
- */
- public long getCount() {
- return count;
- }
-
- /**
- * The total number of shards the search was executed on.
- */
- public int getTotalShards() {
- return shardStats.totalShards;
- }
-
- /**
- * The successful number of shards the search was executed on.
- */
- public int getSuccessfulShards() {
- return shardStats.successfulShards;
- }
-
- /**
- * The number of shards skipped due to pre-filtering
- */
- public int getSkippedShards() {
- return shardStats.skippedShards;
- }
-
- /**
- * The failed number of shards the search was executed on.
- */
- public int getFailedShards() {
- return shardStats.shardFailures.length;
- }
-
- /**
- * The failures that occurred during the search.
- */
- public ShardSearchFailure[] getShardFailures() {
- return shardStats.shardFailures;
- }
-
- public RestStatus status() {
- return RestStatus.status(shardStats.successfulShards, shardStats.totalShards, shardStats.shardFailures);
- }
-
- public static CountResponse fromXContent(XContentParser parser) throws IOException {
- ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
- parser.nextToken();
- ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.currentToken(), parser);
- String currentName = parser.currentName();
- Boolean terminatedEarly = null;
- long count = 0;
- ShardStats shardStats = new ShardStats(-1, -1, 0, ShardSearchFailure.EMPTY_ARRAY);
-
- for (XContentParser.Token token = parser.nextToken(); token != XContentParser.Token.END_OBJECT; token = parser.nextToken()) {
- if (token == XContentParser.Token.FIELD_NAME) {
- currentName = parser.currentName();
- } else if (token.isValue()) {
- if (COUNT.match(currentName, parser.getDeprecationHandler())) {
- count = parser.longValue();
- } else if (TERMINATED_EARLY.match(currentName, parser.getDeprecationHandler())) {
- terminatedEarly = parser.booleanValue();
- } else {
- parser.skipChildren();
- }
- } else if (token == XContentParser.Token.START_OBJECT) {
- if (SHARDS.match(currentName, parser.getDeprecationHandler())) {
- shardStats = ShardStats.fromXContent(parser);
- } else {
- parser.skipChildren();
- }
- }
- }
- return new CountResponse(count, terminatedEarly, shardStats);
- }
-
- @Override
- public String toString() {
- String s = "{"
- + "count="
- + count
- + (isTerminatedEarly() != null ? ", terminatedEarly=" + terminatedEarly : "")
- + ", "
- + shardStats
- + '}';
- return s;
- }
-
- public Boolean isTerminatedEarly() {
- return terminatedEarly;
- }
-
- /**
- * Encapsulates _shards section of count api response.
- */
- public static final class ShardStats {
-
- static final ParseField FAILED = new ParseField("failed");
- static final ParseField SKIPPED = new ParseField("skipped");
- static final ParseField TOTAL = new ParseField("total");
- static final ParseField SUCCESSFUL = new ParseField("successful");
- static final ParseField FAILURES = new ParseField("failures");
-
- private final int successfulShards;
- private final int totalShards;
- private final int skippedShards;
- private final ShardSearchFailure[] shardFailures;
-
- public ShardStats(int successfulShards, int totalShards, int skippedShards, ShardSearchFailure[] shardFailures) {
- this.successfulShards = successfulShards;
- this.totalShards = totalShards;
- this.skippedShards = skippedShards;
- this.shardFailures = Arrays.copyOf(shardFailures, shardFailures.length);
- }
-
- public int getSuccessfulShards() {
- return successfulShards;
- }
-
- public int getTotalShards() {
- return totalShards;
- }
-
- public int getSkippedShards() {
- return skippedShards;
- }
-
- public ShardSearchFailure[] getShardFailures() {
- return Arrays.copyOf(shardFailures, shardFailures.length, ShardSearchFailure[].class);
- }
-
- static ShardStats fromXContent(XContentParser parser) throws IOException {
- int successfulShards = -1;
- int totalShards = -1;
- int skippedShards = 0; // BWC @see org.elasticsearch.action.search.SearchResponse
- List failures = new ArrayList<>();
- XContentParser.Token token;
- String currentName = parser.currentName();
- while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
- if (token == XContentParser.Token.FIELD_NAME) {
- currentName = parser.currentName();
- } else if (token.isValue()) {
- if (FAILED.match(currentName, parser.getDeprecationHandler())) {
- parser.intValue();
- } else if (SKIPPED.match(currentName, parser.getDeprecationHandler())) {
- skippedShards = parser.intValue();
- } else if (TOTAL.match(currentName, parser.getDeprecationHandler())) {
- totalShards = parser.intValue();
- } else if (SUCCESSFUL.match(currentName, parser.getDeprecationHandler())) {
- successfulShards = parser.intValue();
- } else {
- parser.skipChildren();
- }
- } else if (token == XContentParser.Token.START_ARRAY) {
- if (FAILURES.match(currentName, parser.getDeprecationHandler())) {
- while ((parser.nextToken()) != XContentParser.Token.END_ARRAY) {
- failures.add(ShardSearchFailure.fromXContent(parser));
- }
- } else {
- parser.skipChildren();
- }
- } else {
- parser.skipChildren();
- }
- }
- return new ShardStats(successfulShards, totalShards, skippedShards, failures.toArray(new ShardSearchFailure[failures.size()]));
- }
-
- @Override
- public String toString() {
- return "_shards : {"
- + "total="
- + totalShards
- + ", successful="
- + successfulShards
- + ", skipped="
- + skippedShards
- + ", failed="
- + (shardFailures != null && shardFailures.length > 0 ? shardFailures.length : 0)
- + (shardFailures != null && shardFailures.length > 0 ? ", failures: " + Arrays.asList(shardFailures) : "")
- + '}';
- }
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceRequest.java
deleted file mode 100644
index 6e26457a27a5..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceRequest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.action.get.GetRequest;
-import org.elasticsearch.client.Validatable;
-import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
-
-public final class GetSourceRequest implements Validatable {
- private String routing;
- private String preference;
-
- private boolean refresh = false;
- private boolean realtime = true;
-
- private FetchSourceContext fetchSourceContext;
-
- private final String index;
- private final String id;
-
- public GetSourceRequest(String index, String id) {
- this.index = index;
- this.id = id;
- }
-
- public static GetSourceRequest from(GetRequest getRequest) {
- return new GetSourceRequest(getRequest.index(), getRequest.id()).routing(getRequest.routing())
- .preference(getRequest.preference())
- .refresh(getRequest.refresh())
- .realtime(getRequest.realtime())
- .fetchSourceContext(getRequest.fetchSourceContext());
- }
-
- /**
- * Controls the shard routing of the request. Using this value to hash the shard
- * and not the id.
- */
- public GetSourceRequest routing(String routing) {
- if (routing != null && routing.length() == 0) {
- this.routing = null;
- } else {
- this.routing = routing;
- }
- return this;
- }
-
- /**
- * Sets the preference to execute the search. Defaults to randomize across shards. Can be set to
- * {@code _local} to prefer local shards or a custom value, which guarantees that the same order
- * will be used across different requests.
- */
- public GetSourceRequest preference(String preference) {
- this.preference = preference;
- return this;
- }
-
- /**
- * Should a refresh be executed before this get operation causing the operation to
- * return the latest value. Note, heavy get should not set this to {@code true}. Defaults
- * to {@code false}.
- */
- public GetSourceRequest refresh(boolean refresh) {
- this.refresh = refresh;
- return this;
- }
-
- public GetSourceRequest realtime(boolean realtime) {
- this.realtime = realtime;
- return this;
- }
-
- /**
- * Allows setting the {@link FetchSourceContext} for this request, controlling if and how _source should be returned.
- * Note, the {@code fetchSource} field of the context must be set to {@code true}.
- */
-
- public GetSourceRequest fetchSourceContext(FetchSourceContext context) {
- this.fetchSourceContext = context;
- return this;
- }
-
- public String index() {
- return index;
- }
-
- public String id() {
- return id;
- }
-
- public String routing() {
- return routing;
- }
-
- public String preference() {
- return preference;
- }
-
- public boolean refresh() {
- return refresh;
- }
-
- public boolean realtime() {
- return realtime;
- }
-
- public FetchSourceContext fetchSourceContext() {
- return fetchSourceContext;
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceResponse.java
deleted file mode 100644
index 45469cf1d1fb..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceResponse.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.xcontent.XContentParser;
-
-import java.io.IOException;
-import java.util.Map;
-
-public final class GetSourceResponse {
-
- private final Map source;
-
- public GetSourceResponse(Map source) {
- this.source = source;
- }
-
- public static GetSourceResponse fromXContent(XContentParser parser) throws IOException {
- return new GetSourceResponse(parser.map());
- }
-
- public Map getSource() {
- return this.source;
- }
-
- @Override
- public String toString() {
- return source.toString();
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/IndexerJobStats.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/IndexerJobStats.java
deleted file mode 100644
index e404f254e17a..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/IndexerJobStats.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.xcontent.ParseField;
-
-import java.util.Objects;
-
-public abstract class IndexerJobStats {
- public static ParseField NUM_PAGES = new ParseField("pages_processed");
- public static ParseField NUM_INPUT_DOCUMENTS = new ParseField("documents_processed");
- public static ParseField NUM_OUTPUT_DOCUMENTS = new ParseField("documents_indexed");
- public static ParseField NUM_INVOCATIONS = new ParseField("trigger_count");
- public static ParseField INDEX_TIME_IN_MS = new ParseField("index_time_in_ms");
- public static ParseField SEARCH_TIME_IN_MS = new ParseField("search_time_in_ms");
- public static ParseField PROCESSING_TIME_IN_MS = new ParseField("processing_time_in_ms");
- public static ParseField INDEX_TOTAL = new ParseField("index_total");
- public static ParseField SEARCH_TOTAL = new ParseField("search_total");
- public static ParseField PROCESSING_TOTAL = new ParseField("processing_total");
- public static ParseField SEARCH_FAILURES = new ParseField("search_failures");
- public static ParseField INDEX_FAILURES = new ParseField("index_failures");
-
- protected final long numPages;
- protected final long numInputDocuments;
- protected final long numOuputDocuments;
- protected final long numInvocations;
- protected final long indexTime;
- protected final long indexTotal;
- protected final long searchTime;
- protected final long searchTotal;
- protected final long processingTime;
- protected final long processingTotal;
- protected final long indexFailures;
- protected final long searchFailures;
-
- public IndexerJobStats(
- long numPages,
- long numInputDocuments,
- long numOutputDocuments,
- long numInvocations,
- long indexTime,
- long searchTime,
- long processingTime,
- long indexTotal,
- long searchTotal,
- long processingTotal,
- long indexFailures,
- long searchFailures
- ) {
- this.numPages = numPages;
- this.numInputDocuments = numInputDocuments;
- this.numOuputDocuments = numOutputDocuments;
- this.numInvocations = numInvocations;
- this.indexTime = indexTime;
- this.indexTotal = indexTotal;
- this.searchTime = searchTime;
- this.searchTotal = searchTotal;
- this.processingTime = processingTime;
- this.processingTotal = processingTotal;
- this.indexFailures = indexFailures;
- this.searchFailures = searchFailures;
- }
-
- /**
- * The number of pages read from the input indices
- */
- public long getNumPages() {
- return numPages;
- }
-
- /**
- * The number of documents read from the input indices
- */
- public long getNumDocuments() {
- return numInputDocuments;
- }
-
- /**
- * Number of times that the job woke up to write documents
- */
- public long getNumInvocations() {
- return numInvocations;
- }
-
- /**
- * Number of documents written
- */
- public long getOutputDocuments() {
- return numOuputDocuments;
- }
-
- /**
- * Number of index failures that have occurred
- */
- public long getIndexFailures() {
- return indexFailures;
- }
-
- /**
- * Number of failures that have occurred
- */
- public long getSearchFailures() {
- return searchFailures;
- }
-
- /**
- * Returns the time spent indexing (cumulative) in milliseconds
- */
- public long getIndexTime() {
- return indexTime;
- }
-
- /**
- * Returns the time spent searching (cumulative) in milliseconds
- */
- public long getSearchTime() {
- return searchTime;
- }
-
- /**
- * Returns the time spent processing (cumulative) in milliseconds
- */
- public long getProcessingTime() {
- return processingTime;
- }
-
- /**
- * Returns the total number of indexing requests that have been processed
- * (Note: this is not the number of _documents_ that have been indexed)
- */
- public long getIndexTotal() {
- return indexTotal;
- }
-
- /**
- * Returns the total number of search requests that have been made
- */
- public long getSearchTotal() {
- return searchTotal;
- }
-
- /**
- * Returns the total number of processing runs that have been made
- */
- public long getProcessingTotal() {
- return processingTotal;
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- }
-
- if (other instanceof IndexerJobStats == false) {
- return false;
- }
-
- IndexerJobStats that = (IndexerJobStats) other;
- return Objects.equals(this.numPages, that.numPages)
- && Objects.equals(this.numInputDocuments, that.numInputDocuments)
- && Objects.equals(this.numOuputDocuments, that.numOuputDocuments)
- && Objects.equals(this.numInvocations, that.numInvocations)
- && Objects.equals(this.indexTime, that.indexTime)
- && Objects.equals(this.searchTime, that.searchTime)
- && Objects.equals(this.processingTime, that.processingTime)
- && Objects.equals(this.indexFailures, that.indexFailures)
- && Objects.equals(this.searchFailures, that.searchFailures)
- && Objects.equals(this.searchTotal, that.searchTotal)
- && Objects.equals(this.processingTotal, that.processingTotal)
- && Objects.equals(this.indexTotal, that.indexTotal);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(
- numPages,
- numInputDocuments,
- numOuputDocuments,
- numInvocations,
- indexTime,
- searchTime,
- processingTime,
- indexFailures,
- searchFailures,
- searchTotal,
- indexTotal,
- processingTotal
- );
- }
-
- @Override
- public final String toString() {
- return "{pages="
- + numPages
- + ", input_docs="
- + numInputDocuments
- + ", output_docs="
- + numOuputDocuments
- + ", invocations="
- + numInvocations
- + ", index_failures="
- + indexFailures
- + ", search_failures="
- + searchFailures
- + ", index_time_in_ms="
- + indexTime
- + ", index_total="
- + indexTotal
- + ", search_time_in_ms="
- + searchTime
- + ", search_total="
- + searchTotal
- + ", processing_time_in_ms="
- + processingTime
- + ", processing_total="
- + processingTotal
- + "}";
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/IndexerState.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/IndexerState.java
deleted file mode 100644
index 95ca55505261..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/IndexerState.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import java.util.Locale;
-
-/**
- * IndexerState represents the internal state of the indexer. It
- * is also persistent when changing from started/stopped in case the allocated
- * task is restarted elsewhere.
- */
-public enum IndexerState {
- /** Indexer is running, but not actively indexing data (e.g. it's idle). */
- STARTED,
-
- /** Indexer is actively indexing data. */
- INDEXING,
-
- /**
- * Transition state to where an indexer has acknowledged the stop
- * but is still in process of halting.
- */
- STOPPING,
-
- /** Indexer is "paused" and ignoring scheduled triggers. */
- STOPPED,
-
- /**
- * Something (internal or external) has requested the indexer abort
- * and shutdown.
- */
- ABORTING;
-
- public static IndexerState fromString(String name) {
- return valueOf(name.trim().toUpperCase(Locale.ROOT));
- }
-
- public String value() {
- return name().toLowerCase(Locale.ROOT);
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/MainRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/MainRequest.java
deleted file mode 100644
index 592d98674372..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/MainRequest.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.client.Validatable;
-
-public class MainRequest implements Validatable {}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/MultiTermVectorsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/MultiTermVectorsRequest.java
deleted file mode 100644
index cdd98bb12a56..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/MultiTermVectorsRequest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.client.Validatable;
-import org.elasticsearch.xcontent.ToXContentObject;
-import org.elasticsearch.xcontent.XContentBuilder;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.elasticsearch.client.core.TermVectorsRequest.createFromTemplate;
-
-public class MultiTermVectorsRequest implements ToXContentObject, Validatable {
-
- private List requests = new ArrayList<>();
-
- /**
- * Constructs an empty MultiTermVectorsRequest
- * After that use {@code add} method to add individual {@code TermVectorsRequest} to it.
- */
- public MultiTermVectorsRequest() {}
-
- /**
- * Constructs a MultiTermVectorsRequest from the given document ids
- * and a template {@code TermVectorsRequest}.
- * Used when individual requests share the same index, type and other settings.
- * @param ids - ids of documents for which term vectors are requested
- * @param template - a template {@code TermVectorsRequest} that allows to set all
- * settings only once for all requests.
- */
- public MultiTermVectorsRequest(String[] ids, TermVectorsRequest template) {
- for (String id : ids) {
- TermVectorsRequest request = createFromTemplate(template, id);
- requests.add(request);
- }
- }
-
- /**
- * Adds another {@code TermVectorsRequest} to this {@code MultiTermVectorsRequest}
- * @param request - {@code TermVectorsRequest} to add
- */
- public void add(TermVectorsRequest request) {
- requests.add(request);
- }
-
- @Override
- public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
- builder.startObject();
- builder.startArray("docs");
- for (TermVectorsRequest request : requests) {
- request.toXContent(builder, params);
- }
- builder.endArray();
- builder.endObject();
- return builder;
- }
-
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/MultiTermVectorsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/MultiTermVectorsResponse.java
deleted file mode 100644
index 3f836d714433..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/MultiTermVectorsResponse.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.xcontent.ConstructingObjectParser;
-import org.elasticsearch.xcontent.ParseField;
-import org.elasticsearch.xcontent.XContentParser;
-
-import java.util.List;
-import java.util.Objects;
-
-import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
-
-public class MultiTermVectorsResponse {
- private final List responses;
-
- public MultiTermVectorsResponse(List responses) {
- this.responses = responses;
- }
-
- private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- "multi_term_vectors",
- true,
- args -> {
- // as the response comes from server, we are sure that args[0] will be a list of TermVectorsResponse
- @SuppressWarnings("unchecked")
- List termVectorsResponsesList = (List) args[0];
- return new MultiTermVectorsResponse(termVectorsResponsesList);
- }
- );
-
- static {
- PARSER.declareObjectArray(constructorArg(), (p, c) -> TermVectorsResponse.fromXContent(p), new ParseField("docs"));
- }
-
- public static MultiTermVectorsResponse fromXContent(XContentParser parser) {
- return PARSER.apply(parser, null);
- }
-
- /**
- * Returns the list of {@code TermVectorsResponse} for this {@code MultiTermVectorsResponse}
- */
- public List getTermVectorsResponses() {
- return responses;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if ((obj instanceof MultiTermVectorsResponse) == false) return false;
- MultiTermVectorsResponse other = (MultiTermVectorsResponse) obj;
- return Objects.equals(responses, other.responses);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(responses);
- }
-
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/PageParams.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/PageParams.java
deleted file mode 100644
index c41e17e5d1ed..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/PageParams.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.core.Nullable;
-import org.elasticsearch.xcontent.ConstructingObjectParser;
-import org.elasticsearch.xcontent.ParseField;
-import org.elasticsearch.xcontent.ToXContentObject;
-import org.elasticsearch.xcontent.XContentBuilder;
-
-import java.io.IOException;
-import java.util.Objects;
-
-/**
- * Paging parameters for GET requests
- */
-public class PageParams implements ToXContentObject {
-
- public static final ParseField PAGE = new ParseField("page");
- public static final ParseField FROM = new ParseField("from");
- public static final ParseField SIZE = new ParseField("size");
-
- public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- PAGE.getPreferredName(),
- a -> new PageParams((Integer) a[0], (Integer) a[1])
- );
-
- static {
- PARSER.declareInt(ConstructingObjectParser.optionalConstructorArg(), FROM);
- PARSER.declareInt(ConstructingObjectParser.optionalConstructorArg(), SIZE);
- }
-
- private final Integer from;
- private final Integer size;
-
- /**
- * Constructs paging parameters
- * @param from skips the specified number of items. When {@code null} the default value will be used.
- * @param size specifies the maximum number of items to obtain. When {@code null} the default value will be used.
- */
- public PageParams(@Nullable Integer from, @Nullable Integer size) {
- this.from = from;
- this.size = size;
- }
-
- public Integer getFrom() {
- return from;
- }
-
- public Integer getSize() {
- return size;
- }
-
- @Override
- public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
- builder.startObject();
- if (from != null) {
- builder.field(FROM.getPreferredName(), from);
- }
- if (size != null) {
- builder.field(SIZE.getPreferredName(), size);
- }
- builder.endObject();
- return builder;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(from, size);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- PageParams other = (PageParams) obj;
- return Objects.equals(from, other.from) && Objects.equals(size, other.size);
- }
-
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/TermVectorsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/TermVectorsRequest.java
deleted file mode 100644
index af27dae1c04c..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/TermVectorsRequest.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.client.Validatable;
-import org.elasticsearch.common.bytes.BytesReference;
-import org.elasticsearch.core.Nullable;
-import org.elasticsearch.xcontent.ToXContentObject;
-import org.elasticsearch.xcontent.XContentBuilder;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Map;
-
-public class TermVectorsRequest implements ToXContentObject, Validatable {
-
- private final String index;
- @Nullable
- private final String type;
- private String id = null;
- private XContentBuilder docBuilder = null;
-
- private String routing = null;
- private String preference = null;
- private boolean realtime = true;
- private String[] fields = null;
- private boolean requestPositions = true;
- private boolean requestPayloads = true;
- private boolean requestOffsets = true;
- private boolean requestFieldStatistics = true;
- private boolean requestTermStatistics = false;
- private Map perFieldAnalyzer = null;
- private Map filterSettings = null;
-
- /**
- * Constructs TermVectorRequest for the given document
- *
- * @param index - index of the document
- * @param docId - id of the document
- */
- public TermVectorsRequest(String index, String docId) {
- this.index = index;
- this.type = null;
- this.id = docId;
- }
-
- /**
- * Constructs TermVectorRequest for the given document
- *
- * @param index - index of the document
- * @param type - type of the document
- * @param docId - id of the document
- *
- * @deprecated Types are in the process of being removed, use
- * {@link #TermVectorsRequest(String, String)} instead.
- */
- @Deprecated
- public TermVectorsRequest(String index, String type, String docId) {
- this.index = index;
- this.type = type;
- this.id = docId;
- }
-
- /**
- * Constructs TermVectorRequest for an artificial document
- *
- * @param index - index of the document
- * @param docBuilder - an artificial document
- */
- public TermVectorsRequest(String index, XContentBuilder docBuilder) {
- this.index = index;
- this.type = null;
- this.docBuilder = docBuilder;
- }
-
- /**
- * Constructs TermVectorRequest for an artificial document
- * @param index - index of the document
- * @param type - type of the document
- * @param docBuilder - an artificial document
- *
- * @deprecated Types are in the process of being removed, use
- * {@link TermVectorsRequest(String, XContentBuilder)} instead.
- */
- @Deprecated
- public TermVectorsRequest(String index, String type, XContentBuilder docBuilder) {
- this.index = index;
- this.type = type;
- this.docBuilder = docBuilder;
- }
-
- /**
- * Constructs a new TermVectorRequest from a template
- * using the provided document id
- * @param template - a term vector request served as a template
- * @param id - id of the requested document
- */
- static TermVectorsRequest createFromTemplate(TermVectorsRequest template, String id) {
- TermVectorsRequest request = new TermVectorsRequest(template.getIndex(), template.getType(), id);
- request.realtime = template.getRealtime();
- request.requestPositions = template.requestPositions;
- request.requestPayloads = template.requestPayloads;
- request.requestOffsets = template.requestOffsets;
- request.requestFieldStatistics = template.requestFieldStatistics;
- request.requestTermStatistics = template.requestTermStatistics;
- if (template.routing != null) request.setRouting(template.getRouting());
- if (template.preference != null) request.setPreference(template.getPreference());
- if (template.fields != null) request.setFields(template.getFields());
- if (template.perFieldAnalyzer != null) request.setPerFieldAnalyzer(template.perFieldAnalyzer);
- if (template.filterSettings != null) request.setFilterSettings(template.filterSettings);
- return request;
- }
-
- /**
- * Returns the index of the request
- */
- public String getIndex() {
- return index;
- }
-
- /**
- * Returns the type of the request
- *
- * @deprecated Types are in the process of being removed.
- */
- @Deprecated
- public String getType() {
- return type;
- }
-
- /**
- * Returns the id of the request
- * can be NULL if there is no document ID
- */
- public String getId() {
- return id;
- }
-
- /**
- * Sets the fields for which term vectors information should be retrieved
- */
- public void setFields(String... fields) {
- this.fields = fields;
- }
-
- public String[] getFields() {
- return fields;
- }
-
- /**
- * Sets whether to request term positions
- */
- public void setPositions(boolean positions) {
- this.requestPositions = positions;
- }
-
- /**
- * Sets whether to request term payloads
- */
- public void setPayloads(boolean payloads) {
- this.requestPayloads = payloads;
- }
-
- /**
- * Sets whether to request term offsets
- */
- public void setOffsets(boolean offsets) {
- this.requestOffsets = offsets;
- }
-
- /**
- * Sets whether to request field statistics
- */
- public void setFieldStatistics(boolean fieldStatistics) {
- this.requestFieldStatistics = fieldStatistics;
- }
-
- /**
- * Sets whether to request term statistics
- */
- public void setTermStatistics(boolean termStatistics) {
- this.requestTermStatistics = termStatistics;
- }
-
- /**
- * Sets different analyzers than the one at the fields
- */
- public void setPerFieldAnalyzer(Map perFieldAnalyzer) {
- this.perFieldAnalyzer = perFieldAnalyzer;
- }
-
- /**
- * Sets conditions for terms filtering
- */
- public void setFilterSettings(Map filterSettings) {
- this.filterSettings = filterSettings;
- }
-
- /**
- * Sets a routing to route a request to a particular shard
- */
- public void setRouting(String routing) {
- this.routing = routing;
- }
-
- public String getRouting() {
- return routing;
- }
-
- /**
- * Set a preference of which shard copies to execute the request
- */
- public void setPreference(String preference) {
- this.preference = preference;
- }
-
- public String getPreference() {
- return preference;
- }
-
- /**
- * Sets if the request should be realtime or near-realtime
- */
- public void setRealtime(boolean realtime) {
- this.realtime = realtime;
- }
-
- /**
- * Returns if the request is realtime(true) or near-realtime(false)
- */
- public boolean getRealtime() {
- return realtime;
- }
-
- @Override
- public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
- builder.startObject();
- builder.field("_index", index);
- if (type != null) {
- builder.field("_type", type);
- }
- if (id != null) builder.field("_id", id);
- if (fields != null) builder.field("fields", fields);
- // set values only when different from defaults
- if (requestPositions == false) builder.field("positions", false);
- if (requestPayloads == false) builder.field("payloads", false);
- if (requestOffsets == false) builder.field("offsets", false);
- if (requestFieldStatistics == false) builder.field("field_statistics", false);
- if (requestTermStatistics) builder.field("term_statistics", true);
- if (perFieldAnalyzer != null) builder.field("per_field_analyzer", perFieldAnalyzer);
-
- if (docBuilder != null) {
- BytesReference doc = BytesReference.bytes(docBuilder);
- try (InputStream stream = doc.streamInput()) {
- builder.rawField("doc", stream, docBuilder.contentType());
- }
- }
-
- if (filterSettings != null) {
- builder.startObject("filter");
- String[] filterSettingNames = {
- "max_num_terms",
- "min_term_freq",
- "max_term_freq",
- "min_doc_freq",
- "max_doc_freq",
- "min_word_length",
- "max_word_length" };
- for (String settingName : filterSettingNames) {
- if (filterSettings.containsKey(settingName)) builder.field(settingName, filterSettings.get(settingName));
- }
- builder.endObject();
- }
- builder.endObject();
- return builder;
- }
-
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/TermVectorsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/TermVectorsResponse.java
deleted file mode 100644
index 89764f639e1a..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/TermVectorsResponse.java
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-package org.elasticsearch.client.core;
-
-import org.elasticsearch.core.Nullable;
-import org.elasticsearch.xcontent.ConstructingObjectParser;
-import org.elasticsearch.xcontent.ParseField;
-import org.elasticsearch.xcontent.XContentParser;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Objects;
-
-import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
-import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg;
-
-public class TermVectorsResponse {
- private final String index;
- private final String id;
- private final long docVersion;
- private final boolean found;
- private final long tookInMillis;
- private final List termVectorList;
-
- public TermVectorsResponse(String index, String id, long version, boolean found, long tookInMillis, List termVectorList) {
- this.index = index;
- this.id = id;
- this.docVersion = version;
- this.found = found;
- this.tookInMillis = tookInMillis;
- this.termVectorList = termVectorList;
- }
-
- private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- "term_vectors",
- true,
- args -> {
- // as the response comes from server, we are sure that args[5] will be a list of TermVector
- @SuppressWarnings("unchecked")
- List termVectorList = (List) args[5];
- if (termVectorList != null) {
- Collections.sort(termVectorList, Comparator.comparing(TermVector::getFieldName));
- }
- return new TermVectorsResponse(
- (String) args[0],
- (String) args[1],
- (long) args[2],
- (boolean) args[3],
- (long) args[4],
- termVectorList
- );
- }
- );
-
- static {
- PARSER.declareString(constructorArg(), new ParseField("_index"));
- PARSER.declareString(optionalConstructorArg(), new ParseField("_id"));
- PARSER.declareLong(constructorArg(), new ParseField("_version"));
- PARSER.declareBoolean(constructorArg(), new ParseField("found"));
- PARSER.declareLong(constructorArg(), new ParseField("took"));
- PARSER.declareNamedObjects(
- optionalConstructorArg(),
- (p, c, fieldName) -> TermVector.fromXContent(p, fieldName),
- new ParseField("term_vectors")
- );
- }
-
- public static TermVectorsResponse fromXContent(XContentParser parser) {
- return PARSER.apply(parser, null);
- }
-
- /**
- * Returns the index for the response
- */
- public String getIndex() {
- return index;
- }
-
- /**
- * Returns the id of the request
- * can be NULL if there is no document ID
- */
- public String getId() {
- return id;
- }
-
- /**
- * Returns if the document is found
- * always true for artificial documents
- */
- public boolean getFound() {
- return found;
- }
-
- /**
- * Returns the document version
- */
- public long getDocVersion() {
- return docVersion;
- }
-
- /**
- * Returns the time that a request took in milliseconds
- */
- public long getTookInMillis() {
- return tookInMillis;
- }
-
- /**
- * Returns the list of term vectors
- */
- public List getTermVectorsList() {
- return termVectorList;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if ((obj instanceof TermVectorsResponse) == false) return false;
- TermVectorsResponse other = (TermVectorsResponse) obj;
- return index.equals(other.index)
- && Objects.equals(id, other.id)
- && docVersion == other.docVersion
- && found == other.found
- && tookInMillis == other.tookInMillis
- && Objects.equals(termVectorList, other.termVectorList);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(index, id, docVersion, found, tookInMillis, termVectorList);
- }
-
- public static final class TermVector {
-
- private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- "term_vector",
- true,
- (args, ctxFieldName) -> {
- // as the response comes from server, we are sure that args[1] will be a list of Term
- @SuppressWarnings("unchecked")
- List terms = (List) args[1];
- if (terms != null) {
- Collections.sort(terms, Comparator.comparing(Term::getTerm));
- }
- return new TermVector(ctxFieldName, (FieldStatistics) args[0], terms);
- }
- );
-
- static {
- PARSER.declareObject(optionalConstructorArg(), (p, c) -> FieldStatistics.fromXContent(p), new ParseField("field_statistics"));
- PARSER.declareNamedObjects(optionalConstructorArg(), (p, c, term) -> Term.fromXContent(p, term), new ParseField("terms"));
- }
-
- private final String fieldName;
- @Nullable
- private final FieldStatistics fieldStatistics;
- @Nullable
- private final List terms;
-
- public TermVector(String fieldName, FieldStatistics fieldStatistics, List terms) {
- this.fieldName = fieldName;
- this.fieldStatistics = fieldStatistics;
- this.terms = terms;
- }
-
- public static TermVector fromXContent(XContentParser parser, String fieldName) {
- return PARSER.apply(parser, fieldName);
- }
-
- /**
- * Returns the field name of the current term vector
- */
- public String getFieldName() {
- return fieldName;
- }
-
- /**
- * Returns the list of terms for the current term vector
- */
- public List getTerms() {
- return terms;
- }
-
- /**
- * Returns the field statistics for the current field
- */
- public FieldStatistics getFieldStatistics() {
- return fieldStatistics;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if ((obj instanceof TermVector) == false) return false;
- TermVector other = (TermVector) obj;
- return fieldName.equals(other.fieldName)
- && Objects.equals(fieldStatistics, other.fieldStatistics)
- && Objects.equals(terms, other.terms);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(fieldName, fieldStatistics, terms);
- }
-
- // Class containing a general field statistics for the field
- public static final class FieldStatistics {
-
- private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- "field_statistics",
- true,
- args -> { return new FieldStatistics((long) args[0], (int) args[1], (long) args[2]); }
- );
-
- static {
- PARSER.declareLong(constructorArg(), new ParseField("sum_doc_freq"));
- PARSER.declareInt(constructorArg(), new ParseField("doc_count"));
- PARSER.declareLong(constructorArg(), new ParseField("sum_ttf"));
- }
- private final long sumDocFreq;
- private final int docCount;
- private final long sumTotalTermFreq;
-
- public FieldStatistics(long sumDocFreq, int docCount, long sumTotalTermFreq) {
- this.sumDocFreq = sumDocFreq;
- this.docCount = docCount;
- this.sumTotalTermFreq = sumTotalTermFreq;
- }
-
- public static FieldStatistics fromXContent(XContentParser parser) {
- return PARSER.apply(parser, null);
- }
-
- /*
- * Returns how many documents this field contains
- */
- public int getDocCount() {
- return docCount;
- }
-
- /**
- * Returns the sum of document frequencies for all terms in this field
- */
- public long getSumDocFreq() {
- return sumDocFreq;
- }
-
- /**
- * Returns the sum of total term frequencies of all terms in this field
- */
- public long getSumTotalTermFreq() {
- return sumTotalTermFreq;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if ((obj instanceof FieldStatistics) == false) return false;
- FieldStatistics other = (FieldStatistics) obj;
- return docCount == other.docCount && sumDocFreq == other.sumDocFreq && sumTotalTermFreq == other.sumTotalTermFreq;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(docCount, sumDocFreq, sumTotalTermFreq);
- }
- }
-
- public static final class Term {
- private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- "token",
- true,
- (args, ctxTerm) -> {
- // as the response comes from server, we are sure that args[4] will be a list of Token
- @SuppressWarnings("unchecked")
- List tokens = (List) args[4];
- if (tokens != null) {
- Collections.sort(
- tokens,
- Comparator.comparing(Token::getPosition, Comparator.nullsFirst(Integer::compareTo))
- .thenComparing(Token::getStartOffset, Comparator.nullsFirst(Integer::compareTo))
- .thenComparing(Token::getEndOffset, Comparator.nullsFirst(Integer::compareTo))
- );
- }
- return new Term(ctxTerm, (int) args[0], (Integer) args[1], (Long) args[2], (Float) args[3], tokens);
- }
- );
- static {
- PARSER.declareInt(constructorArg(), new ParseField("term_freq"));
- PARSER.declareInt(optionalConstructorArg(), new ParseField("doc_freq"));
- PARSER.declareLong(optionalConstructorArg(), new ParseField("ttf"));
- PARSER.declareFloat(optionalConstructorArg(), new ParseField("score"));
- PARSER.declareObjectArray(optionalConstructorArg(), (p, c) -> Token.fromXContent(p), new ParseField("tokens"));
- }
-
- private final String term;
- private final int termFreq;
- @Nullable
- private final Integer docFreq;
- @Nullable
- private final Long totalTermFreq;
- @Nullable
- private final Float score;
- @Nullable
- private final List tokens;
-
- public Term(String term, int termFreq, Integer docFreq, Long totalTermFreq, Float score, List tokens) {
- this.term = term;
- this.termFreq = termFreq;
- this.docFreq = docFreq;
- this.totalTermFreq = totalTermFreq;
- this.score = score;
- this.tokens = tokens;
- }
-
- public static Term fromXContent(XContentParser parser, String term) {
- return PARSER.apply(parser, term);
- }
-
- /**
- * Returns the string representation of the term
- */
- public String getTerm() {
- return term;
- }
-
- /**
- * Returns term frequency - the number of times this term occurs in the current document
- */
- public int getTermFreq() {
- return termFreq;
- }
-
- /**
- * Returns document frequency - the number of documents in the index that contain this term
- */
- public Integer getDocFreq() {
- return docFreq;
- }
-
- /**
- * Returns total term frequency - the number of times this term occurs across all documents
- */
- public Long getTotalTermFreq() {
- return totalTermFreq;
- }
-
- /**
- * Returns tf-idf score, if the request used some form of terms filtering
- */
- public Float getScore() {
- return score;
- }
-
- /**
- * Returns a list of tokens for the term
- */
- public List getTokens() {
- return tokens;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if ((obj instanceof Term) == false) return false;
- Term other = (Term) obj;
- return term.equals(other.term)
- && termFreq == other.termFreq
- && Objects.equals(docFreq, other.docFreq)
- && Objects.equals(totalTermFreq, other.totalTermFreq)
- && Objects.equals(score, other.score)
- && Objects.equals(tokens, other.tokens);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(term, termFreq, docFreq, totalTermFreq, score, tokens);
- }
- }
-
- public static final class Token {
-
- private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
- "token",
- true,
- args -> { return new Token((Integer) args[0], (Integer) args[1], (Integer) args[2], (String) args[3]); }
- );
- static {
- PARSER.declareInt(optionalConstructorArg(), new ParseField("start_offset"));
- PARSER.declareInt(optionalConstructorArg(), new ParseField("end_offset"));
- PARSER.declareInt(optionalConstructorArg(), new ParseField("position"));
- PARSER.declareString(optionalConstructorArg(), new ParseField("payload"));
- }
-
- @Nullable
- private final Integer startOffset;
- @Nullable
- private final Integer endOffset;
- @Nullable
- private final Integer position;
- @Nullable
- private final String payload;
-
- public Token(Integer startOffset, Integer endOffset, Integer position, String payload) {
- this.startOffset = startOffset;
- this.endOffset = endOffset;
- this.position = position;
- this.payload = payload;
- }
-
- public static Token fromXContent(XContentParser parser) {
- return PARSER.apply(parser, null);
- }
-
- /**
- * Returns the start offset of the token in the document's field
- */
- public Integer getStartOffset() {
- return startOffset;
- }
-
- /**
- * Returns the end offset of the token in the document's field
- */
- public Integer getEndOffset() {
- return endOffset;
- }
-
- /**
- * Returns the position of the token in the document's field
- */
- public Integer getPosition() {
- return position;
- }
-
- /**
- * Returns the payload of the token or null if the payload doesn't exist
- */
- public String getPayload() {
- return payload;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if ((obj instanceof Token) == false) return false;
- Token other = (Token) obj;
- return Objects.equals(startOffset, other.startOffset)
- && Objects.equals(endOffset, other.endOffset)
- && Objects.equals(position, other.position)
- && Objects.equals(payload, other.payload);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(startOffset, endOffset, position, payload);
- }
- }
- }
-}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/license/LicenseStatus.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/license/LicenseStatus.java
deleted file mode 100644
index 3038b702c84e..000000000000
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/license/LicenseStatus.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-package org.elasticsearch.client.license;
-
-/**
- * Status of an X-Pack license.
- */
-public enum LicenseStatus {
-
- ACTIVE("active"),
- INVALID("invalid"),
- EXPIRED("expired");
-
- private final String label;
-
- LicenseStatus(String label) {
- this.label = label;
- }
-
- public String label() {
- return label;
- }
-
- public static LicenseStatus fromString(String value) {
- return switch (value) {
- case "active" -> ACTIVE;
- case "invalid" -> INVALID;
- case "expired" -> EXPIRED;
- default -> throw new IllegalArgumentException("unknown license status [" + value + "]");
- };
- }
-}
diff --git a/distribution/archives/integ-test-zip/build.gradle b/distribution/archives/integ-test-zip/build.gradle
index e57c6cf32141..d91d919619ff 100644
--- a/distribution/archives/integ-test-zip/build.gradle
+++ b/distribution/archives/integ-test-zip/build.gradle
@@ -8,7 +8,7 @@
import org.apache.tools.ant.filters.ReplaceTokens
-apply plugin: 'elasticsearch.internal-java-rest-test'
+apply plugin: 'elasticsearch.legacy-java-rest-test'
// The integ-test-distribution is published to maven
apply plugin: 'elasticsearch.publish'
diff --git a/distribution/archives/integ-test-zip/src/javaRestTest/java/org/elasticsearch/test/rest/WaitForRefreshAndCloseIT.java b/distribution/archives/integ-test-zip/src/javaRestTest/java/org/elasticsearch/test/rest/WaitForRefreshAndCloseIT.java
index bdb0a76cf970..19afb4932ff2 100644
--- a/distribution/archives/integ-test-zip/src/javaRestTest/java/org/elasticsearch/test/rest/WaitForRefreshAndCloseIT.java
+++ b/distribution/archives/integ-test-zip/src/javaRestTest/java/org/elasticsearch/test/rest/WaitForRefreshAndCloseIT.java
@@ -10,6 +10,7 @@
import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.ActionFuture;
+import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
@@ -117,11 +118,7 @@ private ActionFuture start(Request request) {
client().performRequestAsync(request, new ResponseListener() {
@Override
public void onSuccess(Response response) {
- try {
- future.onResponse(EntityUtils.toString(response.getEntity()));
- } catch (IOException e) {
- future.onFailure(e);
- }
+ ActionListener.completeWith(future, () -> EntityUtils.toString(response.getEntity()));
}
@Override
diff --git a/distribution/build.gradle b/distribution/build.gradle
index 6b8cdb128042..08920ed173d7 100644
--- a/distribution/build.gradle
+++ b/distribution/build.gradle
@@ -116,6 +116,14 @@ def processIntegTestOutputsTaskProvider = tasks.register("processIntegTestOutput
into integTestOutputs
}
+def integTestConfigFiles = fileTree("${integTestOutputs}/config") {
+ builtBy processIntegTestOutputsTaskProvider
+}
+
+def integTestBinFiles = fileTree("${integTestOutputs}/bin") {
+ builtBy processIntegTestOutputsTaskProvider
+}
+
def defaultModulesFiles = fileTree("${defaultOutputs}/modules") {
builtBy processDefaultOutputsTaskProvider
}
@@ -358,7 +366,7 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) {
filter("tokens" : expansionsForDistribution(distributionType, isTestDistro), ReplaceTokens.class)
}
from buildDefaultLog4jConfigTaskProvider
- from defaultConfigFiles
+ from isTestDistro ? integTestConfigFiles : defaultConfigFiles
}
}
@@ -388,7 +396,7 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) {
// module provided bin files
with copySpec {
eachFile { it.setMode(0755) }
- from(defaultBinFiles)
+ from(testDistro ? integTestBinFiles : defaultBinFiles)
if (distributionType != 'zip') {
exclude '*.bat'
}
diff --git a/distribution/bwc/build.gradle b/distribution/bwc/build.gradle
index 8827e5e4b808..11b0f99c5026 100644
--- a/distribution/bwc/build.gradle
+++ b/distribution/bwc/build.gradle
@@ -15,10 +15,10 @@ import org.elasticsearch.gradle.internal.info.BuildParams
BuildParams.getBwcVersions().forPreviousUnreleased { unreleasedVersion ->
project(unreleasedVersion.gradleProjectPath) {
Version currentVersion = Version.fromString(version)
- TaskProvider resolveAllBwcDepsTaskProvider = bwcSetup.bwcTask("resolveAllBwcDependencies") {
+ TaskProvider resolveAllBwcDepsTaskProvider = bwcSetup.bwcTask("resolveAllBwcDependencies", {
t -> t.args("resolveAllDependencies", "-Dorg.gradle.warning.mode=none")
- }
- if (currentVersion.getMinor() == 0 && currentVersion.getRevision() == 0) {
+ }, false)
+ if (Boolean.getBoolean("recurse.bwc")) {
// We only want to resolve dependencies for live versions of main, without cascading this to older versions
tasks.named("resolveAllDependencies").configure {
dependsOn(resolveAllBwcDepsTaskProvider)
diff --git a/distribution/docker/README.md b/distribution/docker/README.md
index 2e22fe099f4f..4c8052cfc26b 100644
--- a/distribution/docker/README.md
+++ b/distribution/docker/README.md
@@ -92,6 +92,33 @@ images, and combining them with a Docker manifest. The Elasticsearch Delivery
team aren't responsible for this - rather, it happens during our unified release
process.
+To build multi-architecture images on `x86_64` hosts using Docker[^1], you'll
+need [buildx](https://docs.docker.com/build/buildx/install/) and ensure that it
+supports both `linux/amd64` **and** `linux/arm64` targets.
+
+You can verify the supported targets using `docker buildx ls`. For example, the
+following output indicates that support for `linux/arm64` is missing:
+
+```shell
+$ docker buildx ls
+NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
+default * docker
+ default default running 20.10.21 linux/amd64, linux/386
+```
+
+On Linux `x86_64` hosts, to enable `linux-arm64` you need to install
+[qemu-user-static-binfmt](https://github.com/multiarch/qemu-user-static).
+Installation details depend on the Linux distribution but, as described in the
+[getting started docs](https://github.com/multiarch/qemu-user-static#getting-started),
+running `docker run --rm --privileged multiarch/qemu-user-static --reset -p yes`
+will add the necessary support (but will not persist across reboots):
+
+```shell
+$ docker buildx ls
+NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
+default * docker
+ default default running 20.10.21 linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
+```
## Testing
@@ -130,3 +157,5 @@ Ideally this import / export stuff should be completely removed.
[DockerTests]: ../../qa/os/src/test/java/org/elasticsearch/packaging/test/DockerTests.java
[multi-arch]: https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/
[ubi]: https://developers.redhat.com/products/rhel/ubi
+
+[^1]: `podman/buildah` also [supports building multi-platform images](https://github.com/containers/buildah/issues/1590).
diff --git a/distribution/docker/build.gradle b/distribution/docker/build.gradle
index fe4a1e8b48a7..52b8d7b574d4 100644
--- a/distribution/docker/build.gradle
+++ b/distribution/docker/build.gradle
@@ -8,14 +8,13 @@ import org.elasticsearch.gradle.internal.docker.DockerSupportPlugin
import org.elasticsearch.gradle.internal.docker.DockerSupportService
import org.elasticsearch.gradle.internal.docker.ShellRetry
import org.elasticsearch.gradle.internal.docker.TransformLog4jConfigFilter
-import org.elasticsearch.gradle.internal.dra.DraResolvePlugin
import org.elasticsearch.gradle.internal.info.BuildParams
import org.elasticsearch.gradle.util.GradleUtils
import java.nio.file.Path
import java.time.temporal.ChronoUnit
-apply plugin: 'elasticsearch.internal-yaml-rest-test'
+apply plugin: 'elasticsearch.legacy-yaml-rest-test'
apply plugin: 'elasticsearch.test.fixtures'
apply plugin: 'elasticsearch.internal-distribution-download'
apply plugin: 'elasticsearch.dra-artifacts'
@@ -75,11 +74,12 @@ configurations {
log4jConfig
tini
allPlugins
- filebeat
- metricbeat
+ filebeat_aarch64
+ filebeat_x86_64
+ metricbeat_aarch64
+ metricbeat_x86_64
}
-String beatsArch = Architecture.current() == Architecture.AARCH64 ? 'arm64' : 'x86_64'
String tiniArch = Architecture.current() == Architecture.AARCH64 ? 'arm64' : 'amd64'
dependencies {
@@ -88,8 +88,10 @@ dependencies {
log4jConfig project(path: ":distribution", configuration: 'log4jConfig')
tini "krallin:tini:0.19.0:${tiniArch}"
allPlugins project(path: ':plugins', configuration: 'allPlugins')
- filebeat "beats:filebeat:${VersionProperties.elasticsearch}:linux-${beatsArch}@tar.gz"
- metricbeat "beats:metricbeat:${VersionProperties.elasticsearch}:linux-${beatsArch}@tar.gz"
+ filebeat_aarch64 "beats:filebeat:${VersionProperties.elasticsearch}:linux-arm64@tar.gz"
+ filebeat_x86_64 "beats:filebeat:${VersionProperties.elasticsearch}:linux-x86_64@tar.gz"
+ metricbeat_aarch64 "beats:metricbeat:${VersionProperties.elasticsearch}:linux-arm64@tar.gz"
+ metricbeat_x86_64 "beats:metricbeat:${VersionProperties.elasticsearch}:linux-x86_64@tar.gz"
}
ext.expansions = { Architecture architecture, DockerBase base ->
@@ -273,8 +275,8 @@ void addBuildDockerContextTask(Architecture architecture, DockerBase base) {
boolean includeBeats = VersionProperties.isElasticsearchSnapshot() == true || buildId != null || useDra
if (includeBeats) {
- from configurations.filebeat
- from configurations.metricbeat
+ from configurations.getByName("filebeat_${architecture.classifier}")
+ from configurations.getByName("metricbeat_${architecture.classifier}")
}
// For some reason, the artifact name can differ depending on what repository we used.
rename ~/((?:file|metric)beat)-.*\.tar\.gz$/, "\$1-${VersionProperties.elasticsearch}.tar.gz"
@@ -548,5 +550,5 @@ subprojects { Project subProject ->
tasks.named('resolveAllDependencies') {
// Don't try and resolve filebeat or metricbeat snapshots as they may not always be available
- configs = configurations.matching { it.name.endsWith('beat') == false }
+ configs = configurations.matching { it.name.contains('beat') == false }
}
diff --git a/distribution/src/config/jvm.options b/distribution/src/config/jvm.options
index 58d83410cd6d..c999c666ade3 100644
--- a/distribution/src/config/jvm.options
+++ b/distribution/src/config/jvm.options
@@ -72,4 +72,4 @@
@error.file@
## GC logging
--Xlog:gc*,gc+age=trace,safepoint:file=@loggc@:utctime,pid,tags:filecount=32,filesize=64m
+-Xlog:gc*,gc+age=trace,safepoint:file=@loggc@:utctime,level,pid,tags:filecount=32,filesize=64m
diff --git a/distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/KeyStoreWrapperTests.java b/distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/KeyStoreWrapperTests.java
index 02f6b6b3e7ab..f6e357881168 100644
--- a/distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/KeyStoreWrapperTests.java
+++ b/distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/KeyStoreWrapperTests.java
@@ -14,6 +14,7 @@
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexOutput;
import org.elasticsearch.common.Randomness;
+import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.settings.KeyStoreWrapper;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.core.IOUtils;
@@ -51,8 +52,10 @@
import javax.crypto.spec.SecretKeySpec;
import static org.hamcrest.Matchers.anyOf;
+import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
@@ -454,6 +457,48 @@ public void testLegacyV3() throws GeneralSecurityException, IOException {
assertThat(toByteArray(wrapper.getFile("file_setting")), equalTo("file_value".getBytes(StandardCharsets.UTF_8)));
}
+ public void testSerializationNewlyCreated() throws Exception {
+ final KeyStoreWrapper wrapper = KeyStoreWrapper.create();
+ wrapper.setString("string_setting", "string_value".toCharArray());
+
+ // testing when dataBytes[] is null
+ final BytesStreamOutput out = new BytesStreamOutput();
+ wrapper.writeTo(out);
+ final KeyStoreWrapper fromStream = new KeyStoreWrapper(out.bytes().streamInput());
+
+ assertThat(fromStream.getSettingNames(), hasSize(2));
+ assertThat(fromStream.getSettingNames(), containsInAnyOrder("string_setting", "keystore.seed"));
+
+ assertEquals(wrapper.getString("string_setting"), fromStream.getString("string_setting"));
+ assertFalse(wrapper.hasPassword());
+ }
+
+ public void testSerializationWhenLoadedFromFile() throws Exception {
+ final KeyStoreWrapper wrapper = KeyStoreWrapper.create();
+ wrapper.setString("string_setting", "string_value".toCharArray());
+
+ // testing with password and raw dataBytes[]
+ final char[] password = getPossibleKeystorePassword();
+ wrapper.save(env.configFile(), password);
+ final KeyStoreWrapper fromFile = KeyStoreWrapper.load(env.configFile());
+ fromFile.decrypt(password);
+
+ assertThat(fromFile.getSettingNames(), hasSize(2));
+ assertThat(fromFile.getSettingNames(), containsInAnyOrder("string_setting", "keystore.seed"));
+
+ assertEquals(wrapper.getString("string_setting"), fromFile.getString("string_setting"));
+
+ final BytesStreamOutput secondOut = new BytesStreamOutput();
+ fromFile.writeTo(secondOut);
+ final KeyStoreWrapper fromStreamSecond = new KeyStoreWrapper(secondOut.bytes().streamInput());
+
+ assertThat(fromStreamSecond.getSettingNames(), hasSize(2));
+ assertThat(fromStreamSecond.getSettingNames(), containsInAnyOrder("string_setting", "keystore.seed"));
+
+ assertEquals(wrapper.getString("string_setting"), fromStreamSecond.getString("string_setting"));
+ assertEquals(fromFile.hasPassword(), fromStreamSecond.hasPassword());
+ }
+
private byte[] toByteArray(final InputStream is) throws IOException {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
final byte[] buffer = new byte[1024];
diff --git a/distribution/tools/plugin-cli/build.gradle b/distribution/tools/plugin-cli/build.gradle
index d1a53a0e11bd..8ea5b2f963b7 100644
--- a/distribution/tools/plugin-cli/build.gradle
+++ b/distribution/tools/plugin-cli/build.gradle
@@ -10,9 +10,18 @@ apply plugin: 'elasticsearch.build'
archivesBaseName = 'elasticsearch-plugin-cli'
+tasks.named("dependencyLicenses").configure {
+ mapping from: /asm-.*/, to: 'asm'
+}
+
dependencies {
compileOnly project(":server")
compileOnly project(":libs:elasticsearch-cli")
+ implementation project(":libs:elasticsearch-plugin-api")
+ implementation project(":libs:elasticsearch-plugin-scanner")
+ implementation 'org.ow2.asm:asm:9.4'
+ implementation 'org.ow2.asm:asm-tree:9.4'
+
api "org.bouncycastle:bcpg-fips:1.0.4"
api "org.bouncycastle:bc-fips:1.0.2"
testImplementation project(":test:framework")
diff --git a/distribution/tools/plugin-cli/licenses/asm-LICENSE.txt b/distribution/tools/plugin-cli/licenses/asm-LICENSE.txt
new file mode 100644
index 000000000000..afb064f2f266
--- /dev/null
+++ b/distribution/tools/plugin-cli/licenses/asm-LICENSE.txt
@@ -0,0 +1,26 @@
+Copyright (c) 2012 France Télécom
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/distribution/tools/plugin-cli/licenses/asm-NOTICE.txt b/distribution/tools/plugin-cli/licenses/asm-NOTICE.txt
new file mode 100644
index 000000000000..8d1c8b69c3fc
--- /dev/null
+++ b/distribution/tools/plugin-cli/licenses/asm-NOTICE.txt
@@ -0,0 +1 @@
+
diff --git a/distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/InstallPluginAction.java b/distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/InstallPluginAction.java
index 5f7b46e2a749..1afdcd17287f 100644
--- a/distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/InstallPluginAction.java
+++ b/distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/cli/InstallPluginAction.java
@@ -38,9 +38,12 @@
import org.elasticsearch.core.Tuple;
import org.elasticsearch.env.Environment;
import org.elasticsearch.jdk.JarHell;
+import org.elasticsearch.plugin.scanner.ClassReaders;
+import org.elasticsearch.plugin.scanner.NamedComponentScanner;
import org.elasticsearch.plugins.Platforms;
import org.elasticsearch.plugins.PluginDescriptor;
import org.elasticsearch.plugins.PluginsUtils;
+import org.objectweb.asm.ClassReader;
import java.io.BufferedReader;
import java.io.Closeable;
@@ -82,6 +85,7 @@
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -197,6 +201,7 @@ public class InstallPluginAction implements Closeable {
private Environment env;
private boolean batch;
private Proxy proxy = null;
+ private NamedComponentScanner scanner = new NamedComponentScanner();
public InstallPluginAction(Terminal terminal, Environment env, boolean batch) {
this.terminal = terminal;
@@ -208,7 +213,6 @@ public void setProxy(Proxy proxy) {
this.proxy = proxy;
}
- // pkg private for testing
public void execute(List plugins) throws Exception {
if (plugins.isEmpty()) {
throw new UserException(ExitCodes.USAGE, "at least one plugin id is required");
@@ -867,9 +871,24 @@ private PluginDescriptor loadPluginInfo(Path pluginRoot) throws Exception {
// check for jar hell before any copying
jarHellCheck(info, pluginRoot, env.pluginsFile(), env.modulesFile());
+ if (info.isStable() && hasNamedComponentFile(pluginRoot) == false) {
+ generateNameComponentFile(pluginRoot);
+ }
return info;
}
+ private void generateNameComponentFile(Path pluginRoot) throws IOException {
+ Stream classPath = ClassReaders.ofClassPath().stream(); // contains plugin-api
+ List classReaders = Stream.concat(ClassReaders.ofDirWithJars(pluginRoot).stream(), classPath).toList();
+ Map> namedComponentsMap = scanner.scanForNamedClasses(classReaders);
+ Path outputFile = pluginRoot.resolve(PluginDescriptor.NAMED_COMPONENTS_FILENAME);
+ scanner.writeToFile(namedComponentsMap, outputFile);
+ }
+
+ private boolean hasNamedComponentFile(Path pluginRoot) {
+ return Files.exists(pluginRoot.resolve(PluginDescriptor.NAMED_COMPONENTS_FILENAME));
+ }
+
private static final String LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR;
static {
diff --git a/distribution/tools/plugin-cli/src/test/java/org/elasticsearch/plugins/cli/InstallPluginActionTests.java b/distribution/tools/plugin-cli/src/test/java/org/elasticsearch/plugins/cli/InstallPluginActionTests.java
index 9341c469462b..45328397f6ae 100644
--- a/distribution/tools/plugin-cli/src/test/java/org/elasticsearch/plugins/cli/InstallPluginActionTests.java
+++ b/distribution/tools/plugin-cli/src/test/java/org/elasticsearch/plugins/cli/InstallPluginActionTests.java
@@ -43,15 +43,19 @@
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.core.PathUtils;
import org.elasticsearch.core.PathUtilsForTesting;
+import org.elasticsearch.core.Strings;
import org.elasticsearch.core.SuppressForbidden;
import org.elasticsearch.core.Tuple;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.TestEnvironment;
+import org.elasticsearch.plugin.scanner.NamedComponentScanner;
import org.elasticsearch.plugins.Platforms;
import org.elasticsearch.plugins.PluginDescriptor;
import org.elasticsearch.plugins.PluginTestUtil;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.PosixPermissionsResetter;
+import org.elasticsearch.test.compiler.InMemoryJavaCompiler;
+import org.elasticsearch.test.jar.JarUtils;
import org.junit.After;
import org.junit.Before;
@@ -85,6 +89,7 @@
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -123,6 +128,7 @@ public class InstallPluginActionTests extends ESTestCase {
private MockTerminal terminal;
private Tuple env;
private Path pluginDir;
+ private NamedComponentScanner namedComponentScanner;
private final boolean isPosix;
private final boolean isReal;
@@ -130,6 +136,8 @@ public class InstallPluginActionTests extends ESTestCase {
@SuppressForbidden(reason = "sets java.io.tmpdir")
public InstallPluginActionTests(FileSystem fs, Function temp) {
+ assert "false".equals(System.getProperty("tests.security.manager")) : "-Dtests.security.manager=false has to be set";
+
this.temp = temp;
this.isPosix = fs.supportedFileAttributeViews().contains("posix");
this.isReal = fs == PathUtils.getDefaultFileSystem();
@@ -151,6 +159,7 @@ void jarHellCheck(PluginDescriptor candidateInfo, Path candidate, Path pluginsDi
// no jarhell check
}
};
+
defaultAction = new InstallPluginAction(terminal, env.v2(), false);
}
@@ -198,7 +207,9 @@ private static Configuration toPosix(Configuration configuration) {
return configuration.toBuilder().setAttributeViews("basic", "owner", "posix", "unix").build();
}
- /** Creates a test environment with bin, config and plugins directories. */
+ /**
+ * Creates a test environment with bin, config and plugins directories.
+ */
static Tuple createEnv(Function temp) throws IOException {
Path home = temp.apply("install-plugin-command-tests");
Files.createDirectories(home.resolve("bin"));
@@ -215,7 +226,9 @@ static Path createPluginDir(Function temp) {
return temp.apply("pluginDir");
}
- /** creates a fake jar file with empty class files */
+ /**
+ * creates a fake jar file with empty class files
+ */
static void writeJar(Path jar, String... classes) throws IOException {
try (ZipOutputStream stream = new ZipOutputStream(Files.newOutputStream(jar))) {
for (String clazz : classes) {
@@ -236,13 +249,47 @@ static Path writeZip(Path structure, String prefix) throws IOException {
return zip;
}
- /** creates a plugin .zip and returns the url for testing */
+ /**
+ * creates a plugin .zip and returns the url for testing
+ */
static InstallablePlugin createPluginZip(String name, Path structure, String... additionalProps) throws IOException {
return createPlugin(name, structure, additionalProps);
}
+ static void writeStablePlugin(String name, Path structure, boolean hasNamedComponentFile, String... additionalProps)
+ throws IOException {
+ String[] properties = pluginProperties(name, additionalProps, true);
+ PluginTestUtil.writeStablePluginProperties(structure, properties);
+
+ if (hasNamedComponentFile) {
+ PluginTestUtil.writeNamedComponentsFile(structure, namedComponentsJSON());
+ }
+ Path jar = structure.resolve("plugin.jar");
+
+ JarUtils.createJarWithEntries(jar, Map.of("p/A.class", InMemoryJavaCompiler.compile("p.A", """
+ package p;
+ import org.elasticsearch.plugin.*;
+ import org.elasticsearch.plugins.cli.test_model.*;
+ @NamedComponent("a_component")
+ public class A implements ExtensibleInterface{}
+ """), "p/B.class", InMemoryJavaCompiler.compile("p.B", """
+ package p;
+ import org.elasticsearch.plugin.*;
+ import org.elasticsearch.plugins.cli.test_model.*;
+ @NamedComponent("b_component")
+ public class B implements ExtensibleInterface{}
+ """)));
+ }
+
static void writePlugin(String name, Path structure, String... additionalProps) throws IOException {
- String[] properties = Stream.concat(
+ String[] properties = pluginProperties(name, additionalProps, false);
+ PluginTestUtil.writePluginProperties(structure, properties);
+ String className = name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1) + "Plugin";
+ writeJar(structure.resolve("plugin.jar"), className);
+ }
+
+ private static String[] pluginProperties(String name, String[] additionalProps, boolean isStable) {
+ return Stream.of(
Stream.of(
"description",
"fake desc",
@@ -253,15 +300,12 @@ static void writePlugin(String name, Path structure, String... additionalProps)
"elasticsearch.version",
Version.CURRENT.toString(),
"java.version",
- System.getProperty("java.specification.version"),
- "classname",
- "FakePlugin"
+ System.getProperty("java.specification.version")
+
),
+ isStable ? Stream.empty() : Stream.of("classname", "FakePlugin"),
Arrays.stream(additionalProps)
- ).toArray(String[]::new);
- PluginTestUtil.writePluginProperties(structure, properties);
- String className = name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1) + "Plugin";
- writeJar(structure.resolve("plugin.jar"), className);
+ ).flatMap(Function.identity()).toArray(String[]::new);
}
static void writePluginSecurityPolicy(Path pluginDir, String... permissions) throws IOException {
@@ -275,6 +319,12 @@ static void writePluginSecurityPolicy(Path pluginDir, String... permissions) thr
Files.write(pluginDir.resolve("plugin-security.policy"), securityPolicyContent.toString().getBytes(StandardCharsets.UTF_8));
}
+ static InstallablePlugin createStablePlugin(String name, Path structure, boolean hasNamedComponentFile, String... additionalProps)
+ throws IOException {
+ writeStablePlugin(name, structure, hasNamedComponentFile, additionalProps);
+ return new InstallablePlugin(name, writeZip(structure, null).toUri().toURL().toString());
+ }
+
static InstallablePlugin createPlugin(String name, Path structure, String... additionalProps) throws IOException {
writePlugin(name, structure, additionalProps);
return new InstallablePlugin(name, writeZip(structure, null).toUri().toURL().toString());
@@ -309,6 +359,11 @@ void assertPlugin(String name, Path original, Environment environment) throws IO
assertInstallCleaned(environment);
}
+ void assertNamedComponentFile(String name, Path pluginDir, String expectedContent) throws IOException {
+ Path namedComponents = pluginDir.resolve(name).resolve(PluginDescriptor.NAMED_COMPONENTS_FILENAME);
+ assertThat(Files.readString(namedComponents), equalTo(expectedContent));
+ }
+
void assertPluginInternal(String name, Path pluginsFile, Path originalPlugin) throws IOException {
Path got = pluginsFile.resolve(name);
assertTrue("dir " + name + " exists", Files.exists(got));
@@ -505,7 +560,7 @@ public void testInstallFailsIfPreviouslyRemovedPluginFailed() throws Exception {
final Path removing = env.v2().pluginsFile().resolve(".removing-failed");
Files.createDirectory(removing);
final IllegalStateException e = expectThrows(IllegalStateException.class, () -> installPlugin(pluginZip));
- final String expected = formatted(
+ final String expected = Strings.format(
"found file [%s] from a failed attempt to remove the plugin [failed]; execute [elasticsearch-plugin remove failed]",
removing
);
@@ -1506,4 +1561,42 @@ public void testInstallMigratedPlugins() throws Exception {
assertThat(terminal.getErrorOutput(), containsString("[" + id + "] is no longer a plugin"));
}
}
+
+ public void testStablePluginWithNamedComponentsFile() throws Exception {
+ InstallablePlugin stablePluginZip = createStablePlugin("stable1", pluginDir, true);
+ installPlugins(List.of(stablePluginZip), env.v1());
+ assertPlugin("stable1", pluginDir, env.v2());
+ assertNamedComponentFile("stable1", env.v2().pluginsFile(), namedComponentsJSON());
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testStablePluginWithoutNamedComponentsFile() throws Exception {
+ // named component will have to be generated upon install
+ InstallablePlugin stablePluginZip = createStablePlugin("stable1", pluginDir, false);
+
+ installPlugins(List.of(stablePluginZip), env.v1());
+
+ assertPlugin("stable1", pluginDir, env.v2());
+ assertNamedComponentFile("stable1", env.v2().pluginsFile(), namedComponentsJSON());
+ }
+
+ private Map> namedComponentsMap() {
+ Map> result = new LinkedHashMap<>();
+ Map extensibles = new LinkedHashMap<>();
+ extensibles.put("a_component", "p.A");
+ extensibles.put("b_component", "p.B");
+ result.put("org.elasticsearch.plugins.cli.test_model.ExtensibleInterface", extensibles);
+ return result;
+ }
+
+ private static String namedComponentsJSON() {
+ return """
+ {
+ "org.elasticsearch.plugins.cli.test_model.ExtensibleInterface": {
+ "a_component": "p.A",
+ "b_component": "p.B"
+ }
+ }
+ """.replaceAll("[\n\r\s]", "");
+ }
}
diff --git a/distribution/tools/plugin-cli/src/test/java/org/elasticsearch/plugins/cli/test_model/ExtensibleInterface.java b/distribution/tools/plugin-cli/src/test/java/org/elasticsearch/plugins/cli/test_model/ExtensibleInterface.java
new file mode 100644
index 000000000000..517c57a03680
--- /dev/null
+++ b/distribution/tools/plugin-cli/src/test/java/org/elasticsearch/plugins/cli/test_model/ExtensibleInterface.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.plugins.cli.test_model;
+
+import org.elasticsearch.plugin.Extensible;
+
+@Extensible
+public interface ExtensibleInterface {}
diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/APMJvmOptions.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/APMJvmOptions.java
index b89eb166aad8..c13ab9d10681 100644
--- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/APMJvmOptions.java
+++ b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/APMJvmOptions.java
@@ -13,7 +13,7 @@
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.UserException;
import org.elasticsearch.common.Strings;
-import org.elasticsearch.common.settings.KeyStoreWrapper;
+import org.elasticsearch.common.settings.SecureSettings;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.core.Nullable;
@@ -133,11 +133,10 @@ class APMJvmOptions {
* because it will be deleted once Elasticsearch starts.
*
* @param settings the Elasticsearch settings to consider
- * @param keystore a wrapper to access the keystore, or null if there is no keystore
+ * @param secrets a wrapper to access the secrets, or null if there is no secrets
* @param tmpdir Elasticsearch's temporary directory, where the config file will be written
*/
- static List apmJvmOptions(Settings settings, @Nullable KeyStoreWrapper keystore, Path tmpdir) throws UserException,
- IOException {
+ static List apmJvmOptions(Settings settings, @Nullable SecureSettings secrets, Path tmpdir) throws UserException, IOException {
final Path agentJar = findAgentJar();
if (agentJar == null) {
@@ -158,8 +157,8 @@ static List apmJvmOptions(Settings settings, @Nullable KeyStoreWrapper k
}
}
- if (keystore != null) {
- extractSecureSettings(keystore, propertiesMap);
+ if (secrets != null) {
+ extractSecureSettings(secrets, propertiesMap);
}
final Map dynamicSettings = extractDynamicSettings(propertiesMap);
@@ -180,11 +179,11 @@ static String agentCommandLineOption(Path agentJar, Path tmpPropertiesFile) {
return "-javaagent:" + agentJar + "=c=" + tmpPropertiesFile;
}
- private static void extractSecureSettings(KeyStoreWrapper keystore, Map propertiesMap) {
- final Set settingNames = keystore.getSettingNames();
+ private static void extractSecureSettings(SecureSettings secrets, Map propertiesMap) {
+ final Set settingNames = secrets.getSettingNames();
for (String key : List.of("api_key", "secret_token")) {
if (settingNames.contains("tracing.apm." + key)) {
- try (SecureString token = keystore.getString("tracing.apm." + key)) {
+ try (SecureString token = secrets.getString("tracing.apm." + key)) {
propertiesMap.put(key, token.toString());
}
}
diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ErrorPumpThread.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ErrorPumpThread.java
index d8f0c4471c65..397e6a327d1a 100644
--- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ErrorPumpThread.java
+++ b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/ErrorPumpThread.java
@@ -19,19 +19,14 @@
import java.util.concurrent.CountDownLatch;
import static org.elasticsearch.bootstrap.BootstrapInfo.SERVER_READY_MARKER;
-import static org.elasticsearch.bootstrap.BootstrapInfo.USER_EXCEPTION_MARKER;
import static org.elasticsearch.server.cli.ProcessUtil.nonInterruptibleVoid;
/**
* A thread which reads stderr of the jvm process and writes it to this process' stderr.
*
- *
Two special state markers are watched for. These are ascii control characters which signal
- * to the cli process something has changed in the server process. The two possible special messages are:
- *
- *
{@link BootstrapInfo#USER_EXCEPTION_MARKER} - signals a bootstrap error has occurred, and is followed
- * by the error message
- *
{@link BootstrapInfo#SERVER_READY_MARKER} - signals the server is ready so the cli may detach if daemonizing
- *
+ *
The thread watches for a special state marker from the process. The ascii character
+ * {@link BootstrapInfo#SERVER_READY_MARKER} signals the server is ready and the cli may
+ * detach if daemonizing. All other messages are passed through to stderr.
*/
class ErrorPumpThread extends Thread {
private final BufferedReader reader;
@@ -43,9 +38,6 @@ class ErrorPumpThread extends Thread {
// a flag denoting whether the ready marker has been received by the server process
private volatile boolean ready;
- // an exception message received alongside the user exception marker, if a bootstrap error has occurred
- private volatile String userExceptionMsg;
-
// an unexpected io failure that occurred while pumping stderr
private volatile IOException ioFailure;
@@ -66,10 +58,6 @@ String waitUntilReady() throws IOException {
if (ioFailure != null) {
throw ioFailure;
}
- if (ready == false) {
- return userExceptionMsg;
- }
- assert userExceptionMsg == null;
return null;
}
@@ -85,10 +73,7 @@ public void run() {
try {
String line;
while ((line = reader.readLine()) != null) {
- if (line.isEmpty() == false && line.charAt(0) == USER_EXCEPTION_MARKER) {
- userExceptionMsg = line.substring(1);
- readyOrDead.countDown();
- } else if (line.isEmpty() == false && line.charAt(0) == SERVER_READY_MARKER) {
+ if (line.isEmpty() == false && line.charAt(0) == SERVER_READY_MARKER) {
ready = true;
readyOrDead.countDown();
} else {
diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmErgonomics.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmErgonomics.java
index 46e3da3ced90..926d5727a1b4 100644
--- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmErgonomics.java
+++ b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmErgonomics.java
@@ -64,28 +64,42 @@ static boolean tuneG1GCForSmallHeap(final long heapSize) {
}
static boolean tuneG1GCHeapRegion(final Map finalJvmOptions, final boolean tuneG1GCForSmallHeap) {
- JvmOption g1GCHeapRegion = finalJvmOptions.get("G1HeapRegionSize");
- JvmOption g1GC = finalJvmOptions.get("UseG1GC");
- return (tuneG1GCForSmallHeap && g1GC.getMandatoryValue().equals("true") && g1GCHeapRegion.isCommandLineOrigin() == false);
+ return tuneG1GCForSmallHeap && usingG1GcWithoutCommandLineOriginOption(finalJvmOptions, "G1HeapRegionSize");
}
static int tuneG1GCReservePercent(final Map finalJvmOptions, final boolean tuneG1GCForSmallHeap) {
- JvmOption g1GC = finalJvmOptions.get("UseG1GC");
- JvmOption g1GCReservePercent = finalJvmOptions.get("G1ReservePercent");
- if (g1GC.getMandatoryValue().equals("true")) {
- if (g1GCReservePercent.isCommandLineOrigin() == false && tuneG1GCForSmallHeap) {
- return 15;
- } else if (g1GCReservePercent.isCommandLineOrigin() == false && tuneG1GCForSmallHeap == false) {
- return 25;
- }
+ if (usingG1GcWithoutCommandLineOriginOption(finalJvmOptions, "G1ReservePercent")) {
+ return tuneG1GCForSmallHeap ? 15 : 25;
}
return 0;
}
static boolean tuneG1GCInitiatingHeapOccupancyPercent(final Map finalJvmOptions) {
- JvmOption g1GC = finalJvmOptions.get("UseG1GC");
- JvmOption g1GCInitiatingHeapOccupancyPercent = finalJvmOptions.get("InitiatingHeapOccupancyPercent");
- return g1GCInitiatingHeapOccupancyPercent.isCommandLineOrigin() == false && g1GC.getMandatoryValue().equals("true");
+ return usingG1GcWithoutCommandLineOriginOption(finalJvmOptions, "InitiatingHeapOccupancyPercent");
+ }
+
+ /**
+ * @return
+ *
{@code true} if `-XX:+UseG1GC` is in the final JVM options and {@code optionName} was not specified.
+ *
{@code false} if either `-XX:-UseG1GC` is in the final JVM options, or {@code optionName} was specified.
+ *
+ *
+ * @throws IllegalStateException if neither `-XX:+UseG1GC` nor `-XX:-UseG1GC` is in the final JVM options, or `-XX:+UseG1GC` is selected
+ * and {@code optionName} is not in the final JVM options.
+ */
+ private static boolean usingG1GcWithoutCommandLineOriginOption(Map finalJvmOptions, String optionName) {
+ return getRequiredOption(finalJvmOptions, "UseG1GC").getMandatoryValue().equals("true")
+ && getRequiredOption(finalJvmOptions, optionName).isCommandLineOrigin() == false;
+ }
+
+ private static JvmOption getRequiredOption(final Map finalJvmOptions, final String key) {
+ final var jvmOption = finalJvmOptions.get(key);
+ if (jvmOption == null) {
+ throw new IllegalStateException(
+ "JVM option [" + key + "] was unexpectedly missing. Elasticsearch requires this option to be present."
+ );
+ }
+ return jvmOption;
}
private static final Pattern SYSTEM_PROPERTY = Pattern.compile("^-D(?[\\w+].*?)=(?.*)$");
diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOption.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOption.java
index 39bf2e54dade..60cbcb86c02b 100644
--- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOption.java
+++ b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOption.java
@@ -8,6 +8,8 @@
package org.elasticsearch.server.cli;
+import org.elasticsearch.common.Strings;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -29,6 +31,11 @@ class JvmOption {
private final String origin;
JvmOption(String value, String origin) {
+ if (origin == null) {
+ throw new IllegalStateException(Strings.format("""
+ Elasticsearch could not determine the origin of JVM option [%s]. \
+ This indicates that it is running in an unsupported configuration.""", value));
+ }
this.value = value;
this.origin = origin;
}
diff --git a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOptionsParser.java b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOptionsParser.java
index b20aad3a0b84..1b92300ac3dd 100644
--- a/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOptionsParser.java
+++ b/distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/JvmOptionsParser.java
@@ -11,7 +11,6 @@
import org.elasticsearch.bootstrap.ServerArgs;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.UserException;
-import org.elasticsearch.common.settings.KeyStoreWrapper;
import java.io.BufferedReader;
import java.io.IOException;
@@ -70,7 +69,7 @@ SortedMap