From 19a8bbd8d9d5d595c84749ca59129b7a77390cdb Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Wed, 8 Apr 2026 13:22:08 -0600 Subject: [PATCH 01/30] [Buildkite] Add Docker Build This adds a Docker build and release to the `main` release. --- .buildkite/default-pipeline.yml | 57 ++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index 8ea91e6a..e15230ea 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -1,23 +1,42 @@ --- # $yaml-language-server: $schema=https://raw.githubusercontent.com/buildkite/pipeline-schema/main/schema.json steps: - - label: "Build" - command: "true" -# - label: ":docker: Build and Push Dockerfile" -# commands: -# - "vault kv get -field=password kv/ci-shared/opex/oci-registry-creds-prod | docker login -u $(vault kv get -field=username kv/ci-shared/opex/oci-registry-creds-prod) --password-stdin docker.elastic.co" -# - "docker buildx create --use" -# - "docker buildx build --platform linux/amd64,linux/arm64 --push -t docker.elastic.co/opex/diagnostics:latest ." -# agents: -# provider: "gcp" -# imagePrefix: "core-ubuntu-2204" -# machineType: "n2-standard-2" + - label: ":gradle: Test" + key: "gradle-test" + commands: + - ./gradlew test + plugins: + - docker#v5.11.0: + image: "docker.elastic.co/wolfi/jdk:openjdk-25.0.2-r2-dev@sha256:05e5fd81a2a335ca2872ee70dcd1cc6b183c412b0e559e5eca648a82872d281d" + volumes: + - "$$HOME/.gradle:/root/.gradle" + agents: + provider: "gcp" + imagePrefix: "core-ubuntu-2204" + machineType: "n2-standard-2" - - label: "Test" - command: "true" - - - label: "Deploy" - command: "true" - - - label: "Publish" - command: "true" + - label: ":docker: Build and Push Docker Image" + depends_on: "gradle-test" + if: build.branch == "main" + plugins: + - elastic/vault-secrets#v0.1.0: + path: 'kv/ci-shared/opex/oci-registry-creds-prod' + field: "username" + env_var: "DOCKER_REG_USER" + - elastic/vault-secrets#v0.1.0: + path: 'kv/ci-shared/opex/oci-registry-creds-prod' + field: "password" + env_var: "DOCKER_REG_PASS" + - elastic/vault-secrets#v0.1.0: + path: 'kv/ci-shared/opex/oci-registry-creds-prod' + field: "hostname" + env_var: "DOCKER_REG_HOSTNAME" + commands: + - VERSION=$(grep '^version=' gradle.properties | cut -d'=' -f2) + - set +x && echo "$$DOCKER_REG_PASS" | docker login -u "$$DOCKER_REG_USER" --password-stdin "$$DOCKER_REG_HOSTNAME" + - docker buildx create --use --name multiarch-builder --driver docker-container || docker buildx use multiarch-builder + - docker buildx build --platform linux/amd64,linux/arm64 --push -t "docker.elastic.co/support/diagnostics:$${VERSION}" . + agents: + provider: "gcp" + imagePrefix: "core-ubuntu-2204" + machineType: "n2-standard-2" From 25cd4806c434b832d34802f31113e10544109fdb Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Wed, 8 Apr 2026 16:28:45 -0600 Subject: [PATCH 02/30] Remove unneeded .gradle reference --- .buildkite/default-pipeline.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index e15230ea..c095f9b4 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -8,8 +8,6 @@ steps: plugins: - docker#v5.11.0: image: "docker.elastic.co/wolfi/jdk:openjdk-25.0.2-r2-dev@sha256:05e5fd81a2a335ca2872ee70dcd1cc6b183c412b0e559e5eca648a82872d281d" - volumes: - - "$$HOME/.gradle:/root/.gradle" agents: provider: "gcp" imagePrefix: "core-ubuntu-2204" From eb9679d06da226afdeaef8bbf6f7cbf2ab6d0f30 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Wed, 8 Apr 2026 16:36:22 -0600 Subject: [PATCH 03/30] Use root --- .buildkite/default-pipeline.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index c095f9b4..66dba0f0 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -8,6 +8,7 @@ steps: plugins: - docker#v5.11.0: image: "docker.elastic.co/wolfi/jdk:openjdk-25.0.2-r2-dev@sha256:05e5fd81a2a335ca2872ee70dcd1cc6b183c412b0e559e5eca648a82872d281d" + user: root agents: provider: "gcp" imagePrefix: "core-ubuntu-2204" From e77a298b97ef29ae5d248b16c90419157c99e41d Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Wed, 8 Apr 2026 17:07:44 -0600 Subject: [PATCH 04/30] Use JUnit 6 platform --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 17ce926a..cbca2976 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -74,7 +74,7 @@ dependencies { // Test testImplementation("org.junit.jupiter:junit-jupiter-engine:6.0.3") - testImplementation("org.junit.platform:junit-platform-launcher:1.14.3") + testImplementation("org.junit.platform:junit-platform-launcher:2.0.3") testImplementation("org.wiremock:wiremock:3.13.2") } From 913d7f94194dbd2b9e8181dc31a8cb1ae03ff65c Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Wed, 8 Apr 2026 17:13:16 -0600 Subject: [PATCH 05/30] Disable Gradle Daemon in build since it will never be reused --- .buildkite/default-pipeline.yml | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index 66dba0f0..c8fcffa8 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -4,7 +4,7 @@ steps: - label: ":gradle: Test" key: "gradle-test" commands: - - ./gradlew test + - ./gradlew --no-daemon test plugins: - docker#v5.11.0: image: "docker.elastic.co/wolfi/jdk:openjdk-25.0.2-r2-dev@sha256:05e5fd81a2a335ca2872ee70dcd1cc6b183c412b0e559e5eca648a82872d281d" diff --git a/Dockerfile b/Dockerfile index 3dbddc4f..791814d5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ WORKDIR /build COPY ./ ./ -RUN ./gradlew build +RUN ./gradlew --no-daemon build FROM docker.elastic.co/wolfi/jdk:openjdk-25.0.2-r2@sha256:233d3c800cf649986ed5f0f947a11ce1c69476fab434909d50f3aefadfc35609 AS runner From 40acd0137f6ef27aa26bf8c23bf1fcf0d3f9b01b Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Wed, 8 Apr 2026 17:30:20 -0600 Subject: [PATCH 06/30] Add global per-test timeout --- src/test/resources/junit-platform.properties | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/test/resources/junit-platform.properties diff --git a/src/test/resources/junit-platform.properties b/src/test/resources/junit-platform.properties new file mode 100644 index 00000000..0b69ce3e --- /dev/null +++ b/src/test/resources/junit-platform.properties @@ -0,0 +1 @@ +junit.jupiter.execution.timeout.default = 30s From 94cc1d07cb8b8c4c80811c8427efa6916b5b5e90 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Wed, 8 Apr 2026 17:37:37 -0600 Subject: [PATCH 07/30] Explicitly bind to 127.0.0.1 in tests --- .../co/elastic/support/diagnostics/TestDiagnosticService.java | 2 +- .../support/diagnostics/commands/TestCheckKibanaVersion.java | 2 +- .../diagnostics/commands/TestCheckLogstashVersionTest.java | 2 +- .../support/diagnostics/commands/TestKibanaGetDetails.java | 2 +- src/test/java/co/elastic/support/rest/TestRestExecCalls.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java b/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java index 4416d128..b3565428 100644 --- a/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java +++ b/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java @@ -56,7 +56,7 @@ class TestDiagnosticService { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9880)); + wireMockServer = new WireMockServer(wireMockConfig().port(9880).bindAddress("127.0.0.1")); wireMockServer.start(); } diff --git a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java index a6e62a64..57ab1fad 100644 --- a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java +++ b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java @@ -33,7 +33,7 @@ public class TestCheckKibanaVersion { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9880)); + wireMockServer = new WireMockServer(wireMockConfig().port(9880).bindAddress("127.0.0.1")); wireMockServer.start(); } diff --git a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java index 2a0a5ec9..8bab722c 100644 --- a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java +++ b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java @@ -27,7 +27,7 @@ public class TestCheckLogstashVersionTest { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9881)); + wireMockServer = new WireMockServer(wireMockConfig().port(9881).bindAddress("127.0.0.1")); wireMockServer.start(); } diff --git a/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java b/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java index 55ab9263..c9e2cd7d 100644 --- a/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java +++ b/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java @@ -46,7 +46,7 @@ public class TestKibanaGetDetails { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9880)); + wireMockServer = new WireMockServer(wireMockConfig().port(9880).bindAddress("127.0.0.1")); wireMockServer.start(); } diff --git a/src/test/java/co/elastic/support/rest/TestRestExecCalls.java b/src/test/java/co/elastic/support/rest/TestRestExecCalls.java index 1c7a545b..d347589f 100644 --- a/src/test/java/co/elastic/support/rest/TestRestExecCalls.java +++ b/src/test/java/co/elastic/support/rest/TestRestExecCalls.java @@ -43,7 +43,7 @@ public class TestRestExecCalls { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9880).httpsPort(9443)); + wireMockServer = new WireMockServer(wireMockConfig().port(9880).httpsPort(9443).bindAddress("127.0.0.1")); wireMockServer.start(); } From 60157401b840636e220c675ff4a42e5f8e4159cc Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Wed, 8 Apr 2026 17:41:08 -0600 Subject: [PATCH 08/30] Swap call order for readability --- .../co/elastic/support/diagnostics/TestDiagnosticService.java | 2 +- .../support/diagnostics/commands/TestCheckKibanaVersion.java | 2 +- .../diagnostics/commands/TestCheckLogstashVersionTest.java | 2 +- .../support/diagnostics/commands/TestKibanaGetDetails.java | 2 +- src/test/java/co/elastic/support/rest/TestRestExecCalls.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java b/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java index b3565428..aed4c345 100644 --- a/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java +++ b/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java @@ -56,7 +56,7 @@ class TestDiagnosticService { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9880).bindAddress("127.0.0.1")); + wireMockServer = new WireMockServer(wireMockConfig().bindAddress("127.0.0.1").port(9880)); wireMockServer.start(); } diff --git a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java index 57ab1fad..57d89fc8 100644 --- a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java +++ b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java @@ -33,7 +33,7 @@ public class TestCheckKibanaVersion { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9880).bindAddress("127.0.0.1")); + wireMockServer = new WireMockServer(wireMockConfig().bindAddress("127.0.0.1").port(9880)); wireMockServer.start(); } diff --git a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java index 8bab722c..56c1413a 100644 --- a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java +++ b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java @@ -27,7 +27,7 @@ public class TestCheckLogstashVersionTest { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9881).bindAddress("127.0.0.1")); + wireMockServer = new WireMockServer(wireMockConfig().bindAddress("127.0.0.1").port(9881)); wireMockServer.start(); } diff --git a/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java b/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java index c9e2cd7d..9006937c 100644 --- a/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java +++ b/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java @@ -46,7 +46,7 @@ public class TestKibanaGetDetails { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9880).bindAddress("127.0.0.1")); + wireMockServer = new WireMockServer(wireMockConfig().bindAddress("127.0.0.1").port(9880)); wireMockServer.start(); } diff --git a/src/test/java/co/elastic/support/rest/TestRestExecCalls.java b/src/test/java/co/elastic/support/rest/TestRestExecCalls.java index d347589f..1d229550 100644 --- a/src/test/java/co/elastic/support/rest/TestRestExecCalls.java +++ b/src/test/java/co/elastic/support/rest/TestRestExecCalls.java @@ -43,7 +43,7 @@ public class TestRestExecCalls { @BeforeAll public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9880).httpsPort(9443).bindAddress("127.0.0.1")); + wireMockServer = new WireMockServer(wireMockConfig().port(9880).bindAddress("127.0.0.1").httpsPort(9443)); wireMockServer.start(); } From ba433b66b2fd27b4bb6388ad45c97af06242f25e Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Wed, 8 Apr 2026 17:45:24 -0600 Subject: [PATCH 09/30] Reduce lifecycle timeouts --- src/test/resources/junit-platform.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/resources/junit-platform.properties b/src/test/resources/junit-platform.properties index 0b69ce3e..26ef6c89 100644 --- a/src/test/resources/junit-platform.properties +++ b/src/test/resources/junit-platform.properties @@ -1 +1,2 @@ junit.jupiter.execution.timeout.default = 30s +junit.jupiter.execution.timeout.lifecycle.method.default = 10s From 0e279343805ec8b7bf51affae545edd3d3b8f388 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 09:29:48 -0600 Subject: [PATCH 10/30] Create local Dockerfile.test and use it --- .buildkite/default-pipeline.yml | 7 ++----- Dockerfile.test | 9 +++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 Dockerfile.test diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index c8fcffa8..e57cd4dd 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -4,11 +4,8 @@ steps: - label: ":gradle: Test" key: "gradle-test" commands: - - ./gradlew --no-daemon test - plugins: - - docker#v5.11.0: - image: "docker.elastic.co/wolfi/jdk:openjdk-25.0.2-r2-dev@sha256:05e5fd81a2a335ca2872ee70dcd1cc6b183c412b0e559e5eca648a82872d281d" - user: root + - docker build -f Dockerfile.test -t support-diagnostics-test . + - docker run --rm support-diagnostics-test agents: provider: "gcp" imagePrefix: "core-ubuntu-2204" diff --git a/Dockerfile.test b/Dockerfile.test new file mode 100644 index 00000000..56b67c4c --- /dev/null +++ b/Dockerfile.test @@ -0,0 +1,9 @@ +FROM docker.elastic.co/wolfi/jdk:openjdk-25.0.2-r2-dev@sha256:05e5fd81a2a335ca2872ee70dcd1cc6b183c412b0e559e5eca648a82872d281d + +USER root + +WORKDIR /app + +COPY . . + +CMD ["./gradlew", "--no-daemon", "test"] From 1b309a2bef436334cfdc411c968250366ea82355 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 10:05:26 -0600 Subject: [PATCH 11/30] For tests '-Djava.net.preferIPv4Stack=true' --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index cbca2976..b16a79bb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -178,6 +178,7 @@ tasks.named("build") { // --------------------------------------------------------------------------- tasks.withType { useJUnitPlatform() + jvmArgs("-Djava.net.preferIPv4Stack=true") } tasks.withType { From c6d40fa259a0875af183ce626f83ccebf1f42abb Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 10:47:08 -0600 Subject: [PATCH 12/30] Try some more ipv4 magic for the forked JVM to communicate --- gradle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle.properties b/gradle.properties index f8121842..6ed45726 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,3 @@ group=co.elastic.support version=9.4.0-SNAPSHOT +org.gradle.jvmargs=-Djava.net.preferIPv4Stack=true From d941b11a655bc01e7bc9a73d1b8da49da7c1b1f7 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 12:07:51 -0600 Subject: [PATCH 13/30] Log test failure details --- build.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index b16a79bb..e63ade81 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -179,6 +179,12 @@ tasks.named("build") { tasks.withType { useJUnitPlatform() jvmArgs("-Djava.net.preferIPv4Stack=true") + testLogging { + events("failed") + exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL + showCauses = true + showStackTraces = true + } } tasks.withType { From a57af0de61a446cb0bb619519540282bae4af840 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 14:54:11 -0600 Subject: [PATCH 14/30] Try downgrading JUnit --- build.gradle.kts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e63ade81..34533d35 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -73,8 +73,8 @@ dependencies { implementation("org.freemarker:freemarker:2.3.34") // Test - testImplementation("org.junit.jupiter:junit-jupiter-engine:6.0.3") - testImplementation("org.junit.platform:junit-platform-launcher:2.0.3") + testImplementation("org.junit.jupiter:junit-jupiter-engine:5.14.1") + testImplementation("org.junit.platform:junit-platform-launcher:1.14.3") testImplementation("org.wiremock:wiremock:3.13.2") } @@ -179,12 +179,6 @@ tasks.named("build") { tasks.withType { useJUnitPlatform() jvmArgs("-Djava.net.preferIPv4Stack=true") - testLogging { - events("failed") - exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL - showCauses = true - showStackTraces = true - } } tasks.withType { From 75f01cb27a06ef2704549e08963f255c65966539 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 15:04:23 -0600 Subject: [PATCH 15/30] Dump XML test reports to stdout on failure for CI diagnostics Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.test b/Dockerfile.test index 56b67c4c..ee8b7ca8 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -6,4 +6,4 @@ WORKDIR /app COPY . . -CMD ["./gradlew", "--no-daemon", "test"] +CMD ["bash", "-c", "./gradlew --no-daemon test; rc=$?; find build/test-results -name '*.xml' -exec echo '=== {} ===' \\; -exec cat {} \\; 2>/dev/null; exit $rc"] From 65ec7d1a82b67704ee3d7103a56b8ee64d964354 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 15:42:36 -0600 Subject: [PATCH 16/30] Unrevert JUnit and add Docker Ignore to match local behavior with CI --- .dockerignore | 3 +++ build.gradle.kts | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.dockerignore b/.dockerignore index b6e54da5..274f23a2 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,8 @@ # Build files build +**/build +.gradle +**/.gradle diagnostic-output target diff --git a/build.gradle.kts b/build.gradle.kts index 34533d35..b16a79bb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -73,8 +73,8 @@ dependencies { implementation("org.freemarker:freemarker:2.3.34") // Test - testImplementation("org.junit.jupiter:junit-jupiter-engine:5.14.1") - testImplementation("org.junit.platform:junit-platform-launcher:1.14.3") + testImplementation("org.junit.jupiter:junit-jupiter-engine:6.0.3") + testImplementation("org.junit.platform:junit-platform-launcher:2.0.3") testImplementation("org.wiremock:wiremock:3.13.2") } From 0210893bbec8462ced3a4b7ef85bc9dae49a1434 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 16:28:04 -0600 Subject: [PATCH 17/30] Add --stacktrace to surface test worker crash root cause Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.test b/Dockerfile.test index ee8b7ca8..10408d98 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -6,4 +6,4 @@ WORKDIR /app COPY . . -CMD ["bash", "-c", "./gradlew --no-daemon test; rc=$?; find build/test-results -name '*.xml' -exec echo '=== {} ===' \\; -exec cat {} \\; 2>/dev/null; exit $rc"] +CMD ["bash", "-c", "./gradlew --no-daemon --stacktrace test; rc=$?; find build/test-results -name '*.xml' -exec echo '=== {} ===' \\; -exec cat {} \\; 2>/dev/null; exit $rc"] From 474cec38ac830f0f64f9746ba974041e568f87b3 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 16:40:45 -0600 Subject: [PATCH 18/30] Limit resources --- Dockerfile.test | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile.test b/Dockerfile.test index 10408d98..88e6d2fb 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -6,4 +6,6 @@ WORKDIR /app COPY . . -CMD ["bash", "-c", "./gradlew --no-daemon --stacktrace test; rc=$?; find build/test-results -name '*.xml' -exec echo '=== {} ===' \\; -exec cat {} \\; 2>/dev/null; exit $rc"] +ENV GRADLE_OPTS="-Xmx512m -XX:MaxMetaspaceSize=256m" + +CMD ["./gradlew", "test", "--no-daemon", "--stacktrace", "-Dorg.gradle.workers.max=1"] From 0c6f850fffe452aae03dd40a0bb15212631d533c Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Thu, 9 Apr 2026 19:04:09 -0600 Subject: [PATCH 19/30] Pass security.egd to test worker JVM to prevent entropy starvation on GCP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The forked test worker JVM doesn't inherit system properties from the Gradle process. On GCP agents /dev/random can block during SecureRandom initialization (triggered by JUnit/WireMock class loading), which hangs the worker before it connects back to Gradle — causing the output.bin.idx FileNotFoundException. Co-Authored-By: Claude Sonnet 4.6 --- build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index b16a79bb..6f9f3b7e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -178,7 +178,8 @@ tasks.named("build") { // --------------------------------------------------------------------------- tasks.withType { useJUnitPlatform() - jvmArgs("-Djava.net.preferIPv4Stack=true") + jvmArgs("-Djava.net.preferIPv4Stack=true", "-Djava.security.egd=file:/dev/./urandom") + maxHeapSize = "512m" } tasks.withType { From 9ee00b835c35d694192280024195c83fa3f1d74d Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 17:08:00 -0600 Subject: [PATCH 20/30] Delete old tests --- .../diagnostics/TestDiagnosticService.java | 260 ------------------ .../commands/TestCheckKibanaVersion.java | 156 ----------- .../TestCheckLogstashVersionTest.java | 120 -------- .../commands/TestKibanaGetDetails.java | 179 ------------ 4 files changed, 715 deletions(-) delete mode 100644 src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java delete mode 100644 src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java delete mode 100644 src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java delete mode 100644 src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java diff --git a/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java b/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java deleted file mode 100644 index aed4c345..00000000 --- a/src/test/java/co/elastic/support/diagnostics/TestDiagnosticService.java +++ /dev/null @@ -1,260 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -package co.elastic.support.diagnostics; - -import co.elastic.support.Constants; -import co.elastic.support.diagnostics.chain.DiagnosticContext; -import co.elastic.support.util.JsonYamlUtils; -import co.elastic.support.util.ResourceCache; -import com.github.tomakehurst.wiremock.WireMockServer; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.io.TempDir; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.any; -import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -class TestDiagnosticService { - private WireMockServer wireMockServer; - - @TempDir - private Path folder; - - private static final String headerKey1 = "k1"; - private static final String headerVal1 = "v1"; - private static final String headerKey2 = "k2"; - private static final String headerVal2 = "v2"; - - @BeforeAll - public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().bindAddress("127.0.0.1").port(9880)); - wireMockServer.start(); - } - - @AfterAll - public void globalTeardown() { - wireMockServer.stop(); - } - - private DiagConfig newDiagConfig() { - try { - return new DiagConfig( - JsonYamlUtils.readYamlFromClasspath(Constants.DIAG_CONFIG, true)); - } catch (DiagnosticException e) { - fail(e); - return null; // unreachable because of fail(e) - } - } - - private DiagnosticInputs newDiagnosticInputs() { - DiagnosticInputs diagnosticInputs = new DiagnosticInputs(); - diagnosticInputs.port = 9880; - diagnosticInputs.scheme = "http"; - diagnosticInputs.diagType = Constants.api; - try { - Path outputDir = Files.createTempDirectory(folder, "diag"); - diagnosticInputs.outputDir = outputDir.toString(); - } catch (IOException e) { - fail("Unable to create temp directory", e); - } - return diagnosticInputs; - } - - private void setupResponse(boolean withHeaders) { - if (withHeaders) { - wireMockServer.stubFor(any(urlEqualTo("/")) - .withHeader(headerKey1, equalTo(headerVal1)) - .withHeader(headerKey2, equalTo(headerVal2)) - .willReturn(aResponse() - .withBody("{\"version\": {\"number\": \"7.14.0\"}}"))); - wireMockServer.stubFor(any(urlEqualTo("/_nodes/os,process,settings,transport,http")) - .withHeader(headerKey1, equalTo(headerVal1)) - .withHeader(headerKey2, equalTo(headerVal2)) - .willReturn(aResponse() - .withBody("{}"))); - wireMockServer.stubFor(any(anyUrl()) - .withHeader(headerKey1, equalTo(headerVal1)) - .withHeader(headerKey2, equalTo(headerVal2)) - .atPriority(10) - .willReturn(aResponse() - .withBody("some_response_body"))); - } else { - wireMockServer.stubFor(any(urlEqualTo("/")) - .willReturn(aResponse() - .withBody("{\"version\": {\"number\": \"7.14.0\"}}"))); - wireMockServer.stubFor(any(urlEqualTo("/_nodes/os,process,settings,transport,http")) - .willReturn(aResponse() - .withBody("{}"))); - wireMockServer.stubFor(any(anyUrl()) - .atPriority(10) - .willReturn(aResponse() - .withBody("some_response_body"))); - } - } - - public HashMap zipFileContents(File result) throws IOException { - try (ZipFile zipFile = new ZipFile(result, ZipFile.OPEN_READ)) { - HashMap contents = new HashMap<>(); - - Enumeration entries = zipFile.entries(); - - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - assertFalse(entry.getName().startsWith("./"), entry.getName()); - - if (!entry.isDirectory()) { - // Add file path without leading directory - contents.put(entry.getName().replaceFirst("^(.+/)(.+)", "$2"), entry); - } - } - - return contents; - } - } - - public void checkResult(File result, boolean withLogFile) { - assertTrue(result.toString().matches(".*\\.zip$"), result.toString()); - try { - Map contents = zipFileContents(result); - - assertTrue(contents.containsKey("diagnostic_manifest.json"), - () -> String.join(", ", contents.keySet())); - - assertTrue(contents.containsKey("manifest.json")); - if (withLogFile) { - assertTrue(contents.containsKey("diagnostics.log")); - } else { - assertFalse(contents.containsKey("diagnostics.log")); - } - contents.forEach((key, entry) -> { - if (!entry.isDirectory()) { - assertTrue(entry.getSize() > 0, key); - } - }); - } catch (IOException e) { - fail("Error processing result zip file", e); - } - } - - @Test - public void testWithExtraHeaders() { - setupResponse(true); - - Map extraHeaders = new HashMap<>(); - extraHeaders.put(headerKey1, headerVal1); - extraHeaders.put(headerKey2, headerVal2); - DiagConfig diagConfig = newDiagConfig(); - diagConfig.extraHeaders = extraHeaders; - DiagnosticService diag = new DiagnosticService(); - - try (ResourceCache resourceCache = new ResourceCache()) { - DiagnosticContext context = new DiagnosticContext(diagConfig, newDiagnosticInputs(), resourceCache, true); - File result = diag.exec(context); - checkResult(result, true); - } catch (DiagnosticException e) { - fail(e); - } - } - - @Test - public void testWithoutExtraHeaders() { - setupResponse(false); - - DiagnosticService diag = new DiagnosticService(); - - try (ResourceCache resourceCache = new ResourceCache()) { - DiagnosticContext context = new DiagnosticContext(newDiagConfig(), newDiagnosticInputs(), resourceCache, - true); - File result = diag.exec(context); - checkResult(result, true); - } catch (DiagnosticException e) { - fail(e); - } - } - - @Test - public void testConcurrentExecutions() { - setupResponse(false); - - ConcurrentHashMap results = new ConcurrentHashMap<>(); - - Function task = (Integer i) -> () -> { - DiagnosticService diag = new DiagnosticService(); - - try (ResourceCache resourceCache = new ResourceCache()) { - DiagnosticContext context = new DiagnosticContext(newDiagConfig(), newDiagnosticInputs(), - resourceCache, false); - File result = diag.exec(context); - results.put(i, result); - } catch (DiagnosticException e) { - System.out.println(e.getStackTrace()); - fail(e); - } - }; - - List threads = List.of(new Thread(task.apply(0)), new Thread(task.apply(1)), new Thread(task.apply(2))); - threads.forEach(Thread::start); - - for (Thread t : threads) { - try { - t.join(3000); - } catch (InterruptedException e) { - fail("Thread interrupted", e); - } finally { - if (t.isAlive()) { - t.interrupt(); - fail("Thread got stuck"); - } - } - } - assertEquals(results.size(), threads.size()); - results.forEach((i, result) -> checkResult(result, false)); - try { - Enumeration resultFiles = results.elements(); - // Take one zip file to use as a reference for comparisons with the other ones - Map reference = zipFileContents(resultFiles.nextElement()); - while (resultFiles.hasMoreElements()) { - Map other = zipFileContents(resultFiles.nextElement()); - assertEquals(reference.keySet(), other.keySet(), () -> reference.keySet().stream() - .filter(file -> !other.containsKey(file)).collect(Collectors.joining(", "))); - reference.keySet().forEach((key) -> { - if (!key.equals("manifest.json") && !key.equals("diagnostic_manifest.json")) { - assertEquals(reference.get(key).getSize(), other.get(key).getSize(), key); - assertEquals(reference.get(key).getCrc(), other.get(key).getCrc(), key); - } - }); - } - } catch (IOException e) { - fail("Exception while comparing result contents", e); - } - } -} diff --git a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java deleted file mode 100644 index 57d89fc8..00000000 --- a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckKibanaVersion.java +++ /dev/null @@ -1,156 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -package co.elastic.support.diagnostics.commands; - -import co.elastic.support.diagnostics.DiagnosticException; -import co.elastic.support.rest.RestClient; -import com.github.tomakehurst.wiremock.WireMockServer; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.semver4j.Semver; - -import java.util.Map; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class TestCheckKibanaVersion { - private WireMockServer wireMockServer; - private RestClient httpRestClient; - - @BeforeAll - public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().bindAddress("127.0.0.1").port(9880)); - wireMockServer.start(); - } - - @AfterAll - public void globalTeardown() { - wireMockServer.stop(); - } - - @BeforeEach - public void setup() { - httpRestClient = RestClient.getClient( - "localhost", - 9880, - "http", - "elastic", - "elastic", - "", - 0, - "", - "", - "", - "", - true, - Map.of(), - 3000, - 3000, - 3000 - ); - } - - @AfterEach - public void tearDown() { - wireMockServer.resetAll(); - } - - private void initializeKibanaSettings(String version) { - - wireMockServer.stubFor(get(urlEqualTo("/api/settings")).willReturn(aResponse().withBody( - "{\"cluster_uuid\":\"RLtzkhfBRUadN4WZ8fnnog\",\"settings\":{\"xpack\":{\"default_admin_email\":null},\"kibana\":{\"uuid\":\"a4f369ef-fecd-46b7-8b16-c6c3f885d9ec\",\"name\":\"13d5e793ea51\",\"index\":\".kibana\",\"host\":\"0.0.0.0\",\"port\":18648,\"locale\":\"en\",\"transport_address\":\"0.0.0.0:18648\",\"version\":\"" - + version + "\",\"snapshot\":false,\"status\":\"green\"}}}").withStatus(200))); - } - - private void initializeKibanaStats(String version) { - - wireMockServer.stubFor(get(urlEqualTo("/api/stats")).willReturn(aResponse().withBody( - "{\"kibana\":{\"uuid\":\"669ae985-31f7-493b-9910-522cac4d5479\",\"name\":\"6f5485cce678\",\"index\":\".kibana\",\"host\":\"0.0.0.0\",\"locale\":\"en\",\"transport_address\":\"0.0.0.0:18117\",\"version\":\"" - + version + "\",\"snapshot\":false,\"status\":\"green\"}}").withStatus(200))); - } - - @Test - public void testQueriesForKibanaWhenStats() throws DiagnosticException { - initializeKibanaStats("8.1.2"); - Semver version = new CheckKibanaVersion().getKibanaVersion(httpRestClient); - assertEquals("8.1.2", version.getVersion()); - } - - @Test - public void testQueriesForKibanaWhenStatsWithRC() throws DiagnosticException { - initializeKibanaStats("9.0.0-beta1"); - Semver version = new CheckKibanaVersion().getKibanaVersion(httpRestClient); - assertEquals("9.0.0", version.getVersion()); - } - - @Test - public void testQueriesForKibanaWhenStatsAndSettings() throws DiagnosticException { - initializeKibanaStats("6.5.0"); - initializeKibanaSettings("6.5.0"); - Semver version = new CheckKibanaVersion().getKibanaVersion(httpRestClient); - assertEquals("6.5.0", version.getVersion()); - } - - /** - * version is Mandatory as we use the version to define the APIs that will be executed - */ - @Test - public void testQueriesForKibanaEmptyVersion() { - // The response body contains no version - wireMockServer.stubFor(get(urlEqualTo("/api/stats")).willReturn(aResponse().withBody("{\"kibana\": {}}").withStatus(200))); - - try { - new CheckKibanaVersion().getKibanaVersion(httpRestClient); - fail("Expected to fail"); - } catch (DiagnosticException e) { - assertEquals(e.getMessage(), "Kibana version format is wrong - unable to continue. ()"); - } - } - - /** - * version is Mandatory as we use the version to define the APIs that will be executed - * The format of our version is stable and numeric - */ - @Test - public void testQueriesForKibanaCorruptedVersion() { - initializeKibanaStats("a.v.c"); - try { - new CheckKibanaVersion().getKibanaVersion(httpRestClient); - // if they are more than one node in Kibana we need to throw an Exception - fail("Expected to fail"); - } catch (DiagnosticException e) { - assertEquals(e.getMessage(), "Kibana version format is wrong - unable to continue. (a.v.c)"); - } - } - - /** - * version is Mandatory as we use the version to define the APIs that will be executed - * The format of our version is stable and numeric - */ - @Test - public void testQueriesForKibanaTextWithVersion() { - initializeKibanaStats("test-6.5.1"); - - try { - new CheckKibanaVersion().getKibanaVersion(httpRestClient); - // if they are more than one node in Kibana we need to throw an Exception - fail("Expected to fail"); - } catch (DiagnosticException e) { - assertEquals(e.getMessage(), "Kibana version format is wrong - unable to continue. (test-6.5.1)"); - } - } -} diff --git a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java b/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java deleted file mode 100644 index 56c1413a..00000000 --- a/src/test/java/co/elastic/support/diagnostics/commands/TestCheckLogstashVersionTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package co.elastic.support.diagnostics.commands; - -import co.elastic.support.diagnostics.DiagnosticException; -import co.elastic.support.rest.RestClient; -import com.github.tomakehurst.wiremock.WireMockServer; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.semver4j.Semver; - -import java.util.Collections; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class TestCheckLogstashVersionTest { - private WireMockServer wireMockServer; - private RestClient httpRestClient; - - @BeforeAll - public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().bindAddress("127.0.0.1").port(9881)); - wireMockServer.start(); - } - - @AfterAll - public void globalTeardown() { - wireMockServer.stop(); - } - - @BeforeEach - public void setup() { - httpRestClient = RestClient.getClient( - "localhost", - 9881, - "http", - "elastic", - "elastic", - "", - 0, - "", - "", - "", - "", - true, - Collections.emptyMap(), - 3000, - 3000, - 3000 - ); - } - - @AfterEach - public void tearDown() { - wireMockServer.resetAll(); - } - - private void initializeLogstashMainHandler(String version) { - wireMockServer.stubFor(get(urlEqualTo("/")).willReturn(aResponse().withBody("{\"host\":\"Test\",\"version\":\"" + version - + "\",\"http_address\":\"127.0.0.1:9600\",\"id\":\"9ac54ae7-377e-4352-9727-15db6344332a\",\"name\":\"LucaMBP\",\"ephemeral_id\":\"3f1d87db-07c0-4015-941a-4005bbf908fc\",\"snapshot\":false,\"status\":\"yellow\",\"pipeline\":{\"workers\":11,\"batch_size\":125,\"batch_delay\":50},\"build_date\":\"2025-06-17T14:07:37+00:00\",\"build_sha\":\"01b7a2d93e4cf143d4964c71259655cf4575b709\",\"build_snapshot\":false}") - .withStatus(200))); - } - - @Test - public void testQueriesForLogstashVersionNormal() throws DiagnosticException { - initializeLogstashMainHandler("8.1.2"); - Semver version = new CheckLogstashVersion().getLogstashVersion(httpRestClient); - assertEquals("8.1.2", version.getVersion()); - } - - @Test - public void testQueriesForLogstashVersionWithRC() throws DiagnosticException { - initializeLogstashMainHandler("9.0.0-beta1"); - Semver version = new CheckLogstashVersion().getLogstashVersion(httpRestClient); - assertEquals("9.0.0", version.getVersion()); - } - - @Test - public void testQueriesForLogstashEmptyVersion() { - wireMockServer.stubFor(get(urlEqualTo("/")).willReturn(aResponse().withBody("{}").withStatus(200))); - - try { - new CheckLogstashVersion().getLogstashVersion(httpRestClient); - fail("Expected to fail"); - } catch (DiagnosticException e) { - assertEquals("Logstash version format is wrong - unable to continue. ()", e.getMessage()); - } - } - - @Test - public void testQueriesForLogstashCorruptedVersion() { - initializeLogstashMainHandler("a.v.c"); - try { - new CheckLogstashVersion().getLogstashVersion(httpRestClient); - fail("Expected to fail"); - } catch (DiagnosticException e) { - assertEquals("Logstash version format is wrong - unable to continue. (a.v.c)", e.getMessage()); - } - } - - @Test - public void testQueriesForLogstashTextWithVersion() { - initializeLogstashMainHandler("test-6.5.1"); - - try { - new CheckLogstashVersion().getLogstashVersion(httpRestClient); - fail("Expected to fail"); - } catch (DiagnosticException e) { - assertEquals("Logstash version format is wrong - unable to continue. (test-6.5.1)", e.getMessage()); - } - } -} diff --git a/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java b/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java deleted file mode 100644 index 9006937c..00000000 --- a/src/test/java/co/elastic/support/diagnostics/commands/TestKibanaGetDetails.java +++ /dev/null @@ -1,179 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -package co.elastic.support.diagnostics.commands; - -import co.elastic.support.Constants; -import co.elastic.support.diagnostics.DiagConfig; -import co.elastic.support.diagnostics.DiagnosticException; -import co.elastic.support.diagnostics.DiagnosticInputs; -import co.elastic.support.diagnostics.ProcessProfile; -import co.elastic.support.diagnostics.chain.DiagnosticContext; -import co.elastic.support.rest.RestClient; -import co.elastic.support.rest.RestEntry; -import co.elastic.support.rest.RestEntryConfig; -import co.elastic.support.util.JsonYamlUtils; -import co.elastic.support.util.ResourceCache; -import com.fasterxml.jackson.databind.JsonNode; -import com.github.tomakehurst.wiremock.WireMockServer; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class TestKibanaGetDetails { - - private WireMockServer wireMockServer; - private RestClient httpRestClient; - - @BeforeAll - public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().bindAddress("127.0.0.1").port(9880)); - wireMockServer.start(); - } - - @AfterAll - public void globalTeardown() { - wireMockServer.stop(); - } - - @BeforeEach - public void setup() { - - httpRestClient = RestClient.getClient( - "localhost", - 9880, - "http", - "elastic", - "elastic", - "", - 0, - "", - "", - "", - "", - true, - Collections.emptyMap(), - 3000, - 3000, - 3000); - } - - @AfterEach - public void tearDown() { - wireMockServer.resetAll(); - } - - @Test - public void testGetNodeNetworkAndLogInfo() { - - String kibana_stats = "{\"process\":{\"memory\":{\"heap\":{\"total_bytes\":470466560,\"used_bytes\":343398224,\"size_limit\":1740165498},\"resident_set_size_bytes\":587878400},\"pid\":32,\"event_loop_delay\":0.280181884765625,\"uptime_ms\":97230924},\"os\":{\"platform\":\"win32\",\"platform_release\":\"linux-4.15.0-1032-gcp\",\"load\":{\"1m\":1.37451171875,\"5m\":1.43408203125,\"15m\":1.34375},\"memory\":{\"total_bytes\":147879931904,\"free_bytes\":45620334592,\"used_bytes\":102259597312},\"uptime_ms\":18093713000,\"distro\":\"Centos\",\"distro_release\":\"Centos-7.8.2003\"},\"requests\":{\"disconnects\":0,\"total\":1,\"status_codes\":{\"302\":1}},\"concurrent_connections\":8,\"timestamp\":\"2021-01-06T01:35:11.324Z\",\"kibana\":{\"uuid\":\"a4f369ef-fecd-46b7-8b16-c6c3f885d9ec\",\"name\":\"13d5e793ea51\",\"index\":\".kibana\",\"host\":\"0.0.0.0\",\"locale\":\"en\",\"transport_address\":\"0.0.0.0:18648\",\"version\":\"7.9.0\",\"snapshot\":false,\"status\":\"green\"},\"last_updated\":\"2021-01-06T01:35:15.911Z\",\"collection_interval_ms\":5000,\"cluster_uuid\":\"RfBRUssssadN4WZssnnog\"}"; - JsonNode infoNodes = JsonYamlUtils.createJsonNodeFromString(kibana_stats); - KibanaGetDetails testClass = new KibanaGetDetails(); - List nodeProfiles = new ArrayList<>(); - nodeProfiles = testClass.getNodeNetworkAndLogInfo(infoNodes); - - assertEquals(nodeProfiles.size(), 1); - assertEquals(nodeProfiles.get(0).pid, "32"); - assertEquals(nodeProfiles.get(0).name, "13d5e793ea51"); - assertEquals(nodeProfiles.get(0).isDocker, false); - assertEquals(nodeProfiles.get(0).os, Constants.winPlatform); - assertEquals(nodeProfiles.get(0).networkHost, "0.0.0.0"); - assertEquals(nodeProfiles.get(0).httpPublishAddr, "0.0.0.0"); - assertEquals(nodeProfiles.get(0).httpPort, 18648); - } - - @Test - public void testFindTargetNode() { - - KibanaGetDetails testClass = new KibanaGetDetails(); - List nodeProfiles = new ArrayList<>(); - ProcessProfile diagNode = new ProcessProfile(); - diagNode.name = "kibana-name"; - diagNode.pid = "1"; - diagNode.isDocker = true; - nodeProfiles.add(diagNode); - ProcessProfile testedNodeProfiles = testClass.findTargetNode(nodeProfiles); - assertEquals(testedNodeProfiles.pid, "1"); - assertEquals(testedNodeProfiles.name, "kibana-name"); - assertEquals(testedNodeProfiles.isDocker, true); - } - - /** - * Kibana is working in single mode, so the target node will be the only host - * stored on the nodeProfiles List - * if they are two nodes is an error. - */ - @Test - public void testClusterFindTargetNode() { - KibanaGetDetails testClass = new KibanaGetDetails(); - List nodeProfiles = new ArrayList<>(); - ProcessProfile diagNode = new ProcessProfile(); - diagNode.name = "kibana-name"; - diagNode.pid = "1"; - diagNode.isDocker = true; - nodeProfiles.add(diagNode); - - ProcessProfile diagNode2 = new ProcessProfile(); - diagNode2.name = "kibana-name"; - diagNode2.pid = "1"; - diagNode2.isDocker = true; - nodeProfiles.add(diagNode2); - - try { - ProcessProfile testedNodeProfiles = testClass.findTargetNode(nodeProfiles); - // if they are more than one node in Kibana we need to throw an Exception - assertTrue(false); - } catch (RuntimeException e) { - assertEquals(e.getMessage(), "Unable to get Kibana process profile."); - } - } - - @Test - public void testFunctionGetStats() throws DiagnosticException { - wireMockServer.stubFor(get(urlEqualTo("/api/stats")) - .willReturn(aResponse() - .withBody( - "{\"process\":{\"memory\":{\"heap\":{\"total_bytes\":470466560,\"used_bytes\":343398224,\"size_limit\":1740165498},\"resident_set_size_bytes\":587878400},\"pid\":32,\"event_loop_delay\":0.280181884765625,\"uptime_ms\":97230924},\"os\":{\"platform\":\"linux\",\"platform_release\":\"linux-4.15.0-1032-gcp\",\"load\":{\"1m\":1.37451171875,\"5m\":1.43408203125,\"15m\":1.34375},\"memory\":{\"total_bytes\":147879931904,\"free_bytes\":45620334592,\"used_bytes\":102259597312},\"uptime_ms\":18093713000,\"distro\":\"Centos\",\"distro_release\":\"Centos-7.8.2003\"},\"requests\":{\"disconnects\":0,\"total\":1,\"status_codes\":{\"302\":1}},\"concurrent_connections\":8,\"timestamp\":\"2021-01-06T01:35:11.324Z\",\"kibana\":{\"uuid\":\"a4f369ef-fecd-46b7-8b16-c6c3f885d9ec\",\"name\":\"13d5e793ea51\",\"index\":\".kibana\",\"host\":\"0.0.0.0\",\"locale\":\"en\",\"transport_address\":\"0.0.0.0:18648\",\"version\":\"7.9.0\",\"snapshot\":false,\"status\":\"green\"},\"last_updated\":\"2021-01-06T01:35:15.911Z\",\"collection_interval_ms\":5000,\"cluster_uuid\":\"RfBRUssssadN4WZssnnog\"}") - .withStatus(401))); - - Map diagMap = JsonYamlUtils.readYamlFromClasspath(Constants.DIAG_CONFIG, true); - Map restCalls = JsonYamlUtils.readYamlFromClasspath(Constants.KIBANA_REST, true); - RestEntryConfig builder = new RestEntryConfig("7.10.0"); - Map entries = builder.buildEntryMap(restCalls); - - KibanaGetDetails testClass = new KibanaGetDetails(); - try ( - ResourceCache resourceCache = new ResourceCache();) { - DiagnosticContext context = new DiagnosticContext( - new DiagConfig(diagMap), - new DiagnosticInputs("testKibanaGetDetails"), - resourceCache, - true); - context.elasticRestCalls = entries; - context.fullElasticRestCalls = entries; - resourceCache.addRestClient(Constants.restInputHost, httpRestClient); - testClass.getStats(context); - } catch (DiagnosticException e) { - assertEquals(e.getMessage(), "Kibana responded with [401] for [/api/stats]. Unable to proceed."); - } - } -} From 216c98ceec4e29f77f828af32439c13fca21d494 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 17:08:59 -0600 Subject: [PATCH 21/30] Remove other low quality tests --- .../support/rest/TestRestExecCalls.java | 204 ------------------ 1 file changed, 204 deletions(-) delete mode 100644 src/test/java/co/elastic/support/rest/TestRestExecCalls.java diff --git a/src/test/java/co/elastic/support/rest/TestRestExecCalls.java b/src/test/java/co/elastic/support/rest/TestRestExecCalls.java deleted file mode 100644 index 1d229550..00000000 --- a/src/test/java/co/elastic/support/rest/TestRestExecCalls.java +++ /dev/null @@ -1,204 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -package co.elastic.support.rest; - -import co.elastic.support.diagnostics.commands.RunClusterQueries; -import co.elastic.support.util.SystemProperties; -import com.github.tomakehurst.wiremock.WireMockServer; -import com.github.tomakehurst.wiremock.stubbing.Scenario; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class TestRestExecCalls { - private WireMockServer wireMockServer; - private RestClient httpRestClient, httpsRestClient; - private String temp = SystemProperties.userDir + SystemProperties.fileSeparator + "temp"; - private File tempDir = new File(temp); - private String authStringEnc = new String(Base64.encodeBase64("elastic:elastic".getBytes())); - - @BeforeAll - public void globalSetup() { - wireMockServer = new WireMockServer(wireMockConfig().port(9880).bindAddress("127.0.0.1").httpsPort(9443)); - wireMockServer.start(); - } - - @AfterAll - public void globalTeardown() { - wireMockServer.stop(); - } - - @BeforeEach - public void setup() { - - httpRestClient = RestClient.getClient( - "localhost", - 9880, - "http", - "elastic", - "elastic", - "", - 0, - "", - "", - "", - "", - true, - Collections.emptyMap(), - 3000, - 3000, - 3000 - ); - httpsRestClient = RestClient.getClient( - "localhost", - 9443, - "https", - "elastic", - "elastic", - "", - 0, - "", - "", - "", - "", - true, - Collections.emptyMap(), - 3000, - 3000, - 3000 - ); - - tempDir.mkdir(); - } - - @AfterEach - public void tearDown() { - wireMockServer.resetAll(); - FileUtils.deleteQuietly(tempDir); - } - - @Test - public void testSimpleQuery() { - wireMockServer.stubFor(get(urlEqualTo("/")).withHeader("Authorization", equalTo("Basic " + authStringEnc)) - .willReturn(aResponse().withBody("some_response_body"))); - - RestResult result = httpRestClient.execQuery("/"); - assertEquals(200, result.getStatus()); - assertEquals("some_response_body", result.toString()); - } - - @Test - public void testSecuredQuery() { - String url = "/"; - - wireMockServer.stubFor(get(urlEqualTo("/")).withHeader("Authorization", equalTo("Basic " + authStringEnc)) - .willReturn(aResponse().withBody("some_response_body"))); - - RestResult result = httpRestClient.execQuery(url); - assertEquals(200, result.getStatus()); - assertEquals("some_response_body", result.toString()); - } - - @Test - public void testHttpsQuery() { - String url = "/_nodes"; - wireMockServer.stubFor(get(urlEqualTo("/_nodes")).withHeader("Authorization", equalTo("Basic " + authStringEnc)) - .willReturn(aResponse().withBody("some_response_body"))); - - RestResult result = httpsRestClient.execQuery(url); - assertEquals(200, result.getStatus()); - assertEquals("some_response_body", result.toString()); - } - - @Test - public void testFailThenSucceed() { - RunClusterQueries cmd = new RunClusterQueries(); - List entries = new ArrayList<>(); - entries.add(new RestEntry("nodes", "", ".json", true, "/_nodes", false)); - - wireMockServer.stubFor(get(urlEqualTo("/_nodes")).inScenario("retry") - .whenScenarioStateIs(Scenario.STARTED) - .willReturn(aResponse().withBody("error_response_body").withStatus(502)) - .willSetStateTo("failed-once")); - - wireMockServer.stubFor(get(urlEqualTo("/_nodes")).inScenario("retry") - .whenScenarioStateIs("failed-once") - .willReturn(aResponse().withBody("error_response_body").withStatus(502)) - .willSetStateTo("failed-twice")); - - wireMockServer.stubFor(get(urlEqualTo("/_nodes")).inScenario("retry") - .whenScenarioStateIs("failed-twice") - .willReturn(aResponse().withBody("node_response_body").withStatus(200))); - - String targetFilename = temp + SystemProperties.fileSeparator + "nodes.json"; - int totalRetries = cmd.runQueries(httpRestClient, entries, temp, 3, 500); - assertEquals(2, totalRetries); - assertTrue(fileExistsWithText(targetFilename, "node_response_body")); - } - - @Test - public void testRetryAllFail() { - RunClusterQueries cmd = new RunClusterQueries(); - List entries = new ArrayList<>(); - entries.add(new RestEntry("nodes", "", ".json", true, "/_nodes", false)); - wireMockServer.stubFor(get(urlEqualTo("/_nodes")).willReturn(aResponse().withBody("error_response_body").withStatus(502))); - - String targetFilename = temp + SystemProperties.fileSeparator + "nodes.json"; - - int totalRetries = cmd.runQueries(httpRestClient, entries, temp, 3, 500); - assertEquals(4, totalRetries); - assertTrue(fileExistsWithText(targetFilename, "error_response_body")); - } - - @Test - public void testAuthFailure() { - RunClusterQueries cmd = new RunClusterQueries(); - List entries = new ArrayList<>(); - entries.add(new RestEntry("nodes", "", ".json", true, "/_nodes", false)); - - wireMockServer.stubFor(get(urlEqualTo("/_nodes")).willReturn(aResponse().withBody("autherror_response_body").withStatus(401))); - - int totalRetries = cmd.runQueries(httpRestClient, entries, temp, 3, 500); - assertEquals(0, totalRetries); - - String targetFilename = temp + SystemProperties.fileSeparator + "nodes.json"; - assertTrue(fileExistsWithText(targetFilename, "autherror_response_body")); - } - - private boolean fileExistsWithText(String filename, String compare) { - try { - String fileContents = FileUtils.readFileToString(new File(filename), "UTF8"); - if (!fileContents.contains(compare)) { - return false; - } - } catch (IOException e) { - return false; - } - - return true; - } -} From a1c25aa94839e91c90cae64b236743aa92c20a08 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 17:20:28 -0600 Subject: [PATCH 22/30] Capture test output --- .buildkite/default-pipeline.yml | 4 +++- Dockerfile.test | 2 +- build.gradle.kts | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index e57cd4dd..6d101184 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -5,7 +5,9 @@ steps: key: "gradle-test" commands: - docker build -f Dockerfile.test -t support-diagnostics-test . - - docker run --rm support-diagnostics-test + - docker run --name support-diagnostics-test-run support-diagnostics-test; EXIT_CODE=$$?; docker cp support-diagnostics-test-run:/app/build/reports/tests . || true; docker rm support-diagnostics-test-run; exit $$EXIT_CODE + artifact_paths: + - "reports/tests/test/**/*" agents: provider: "gcp" imagePrefix: "core-ubuntu-2204" diff --git a/Dockerfile.test b/Dockerfile.test index 88e6d2fb..8f40c504 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -8,4 +8,4 @@ COPY . . ENV GRADLE_OPTS="-Xmx512m -XX:MaxMetaspaceSize=256m" -CMD ["./gradlew", "test", "--no-daemon", "--stacktrace", "-Dorg.gradle.workers.max=1"] +CMD ["./gradlew", "test", "e2eTest", "--no-daemon", "--stacktrace", "-Dorg.gradle.workers.max=1"] diff --git a/build.gradle.kts b/build.gradle.kts index 3a1a5df7..fc100358 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -208,7 +208,7 @@ val e2eTest by tasks.registering(Test::class) { tasks.withType { options.compilerArgs.addAll(listOf("-Xlint:deprecation", "-Xlint:unchecked")) - options.isFork = true + options.isFork = true // fork to guarantee that Lombok does not mess with the Gradle JVM options.encoding = "UTF-8" } From 0f9d0899477b8e71c020916af4f41f8d7d6a2322 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 17:29:30 -0600 Subject: [PATCH 23/30] Fix warnings and also cp correct path for test reports --- .buildkite/default-pipeline.yml | 2 +- .../co/elastic/support/rest/RestClient.java | 20 +++++++++---------- .../co/elastic/support/util/RemoteSystem.java | 12 +++++++---- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index 6d101184..3c651cb4 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -7,7 +7,7 @@ steps: - docker build -f Dockerfile.test -t support-diagnostics-test . - docker run --name support-diagnostics-test-run support-diagnostics-test; EXIT_CODE=$$?; docker cp support-diagnostics-test-run:/app/build/reports/tests . || true; docker rm support-diagnostics-test-run; exit $$EXIT_CODE artifact_paths: - - "reports/tests/test/**/*" + - "tests/test/**/*" agents: provider: "gcp" imagePrefix: "core-ubuntu-2204" diff --git a/src/main/java/co/elastic/support/rest/RestClient.java b/src/main/java/co/elastic/support/rest/RestClient.java index 9a46d006..b1fb301d 100644 --- a/src/main/java/co/elastic/support/rest/RestClient.java +++ b/src/main/java/co/elastic/support/rest/RestClient.java @@ -26,6 +26,7 @@ import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.HttpHostConnectException; +import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; @@ -55,11 +56,10 @@ public class RestClient implements Closeable { private static final Logger logger = LogManager.getLogger(RestClient.class); private static final int maxTotal = 100, defaultMaxPerRoute = 10; - private CloseableHttpClient client; - private HttpHost httpHost; - private HttpClientContext httpContext; - - private Map extraHeaders; + private final CloseableHttpClient client; + private final HttpHost httpHost; + private final HttpClientContext httpContext; + private final Map extraHeaders; public RestClient(CloseableHttpClient client, HttpHost httpHost, HttpClientContext context, Map extraHeaders) { @@ -218,18 +218,18 @@ public static RestClient getClient( // We need to create a registry for socket factories // for both http and https or pooling will not work. - Registry registry = RegistryBuilder.create() - .register("https", factory) - .register("http", PlainConnectionSocketFactory.getSocketFactory()).build(); + Registry registry = RegistryBuilder.create() + .register("https", factory) + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .build(); PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager(registry); mgr.setDefaultMaxPerRoute(defaultMaxPerRoute); mgr.setMaxTotal(maxTotal); clientBuilder.setConnectionManager(mgr); CloseableHttpClient httpClient = clientBuilder.build(); - RestClient restClient = new RestClient(httpClient, httpHost, context, extraHeaders); - return restClient; + return new RestClient(httpClient, httpHost, context, extraHeaders); } catch (Exception e) { logger.error("Connection setup failed", e); throw new RuntimeException("Error establishing http connection for: " + host, e); diff --git a/src/main/java/co/elastic/support/util/RemoteSystem.java b/src/main/java/co/elastic/support/util/RemoteSystem.java index 832eae92..5d94c6c8 100644 --- a/src/main/java/co/elastic/support/util/RemoteSystem.java +++ b/src/main/java/co/elastic/support/util/RemoteSystem.java @@ -8,7 +8,12 @@ import co.elastic.support.Constants; import co.elastic.support.diagnostics.DiagnosticException; -import com.jcraft.jsch.*; +import com.jcraft.jsch.ChannelExec; +import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import com.jcraft.jsch.UserInfo; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -81,11 +86,10 @@ public RemoteSystem(String osName, UserInfo userInfo = new RemoteUserInfo(remoteUser, remotePassword, keyFilePass); session = jsch.getSession(remoteUser, host, port); - final Hashtable config = new Hashtable(); + final Hashtable config = new Hashtable<>(); config.put("StrictHostKeyChecking", hostKeyChecking); - config.put("PreferredAuthentications", - "publickey,keyboard-interactive,password"); + config.put("PreferredAuthentications", "publickey,keyboard-interactive,password"); session.setConfig(config); session.setUserInfo(userInfo); From 844cc025efe8c29a25093553c6aa4da976e57799 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 17:39:14 -0600 Subject: [PATCH 24/30] Remove complex logic and instead try to place build test reports into container --- .buildkite/default-pipeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index 3c651cb4..395a83a3 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -5,9 +5,9 @@ steps: key: "gradle-test" commands: - docker build -f Dockerfile.test -t support-diagnostics-test . - - docker run --name support-diagnostics-test-run support-diagnostics-test; EXIT_CODE=$$?; docker cp support-diagnostics-test-run:/app/build/reports/tests . || true; docker rm support-diagnostics-test-run; exit $$EXIT_CODE + - docker run --rm -v "$$(pwd)/test-reports:/app/build/reports/tests" support-diagnostics-test artifact_paths: - - "tests/test/**/*" + - "test-reports/test/**/*" agents: provider: "gcp" imagePrefix: "core-ubuntu-2204" From 9da4c25b4d45a9b02ebc4c7fe7a0173bc0388e38 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 17:41:25 -0600 Subject: [PATCH 25/30] Have tests for explicitly Docker versus not -- not inferred --- .../support/diagnostics/DiagnosticInputsTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/test/java/co/elastic/support/diagnostics/DiagnosticInputsTest.java b/src/test/java/co/elastic/support/diagnostics/DiagnosticInputsTest.java index 9da0bcce..36f39cd9 100644 --- a/src/test/java/co/elastic/support/diagnostics/DiagnosticInputsTest.java +++ b/src/test/java/co/elastic/support/diagnostics/DiagnosticInputsTest.java @@ -49,12 +49,25 @@ void setDefaultPort_doesNotOverrideNonDefault() { @Test void validateDiagType_valid() { DiagnosticInputs inputs = new DiagnosticInputs(); + inputs.runningInDocker = false; for (String type : DiagnosticInputs.diagnosticTypeValues) { List errors = inputs.validateDiagType(type); assertNull(errors, "Expected no errors for type: " + type); } } + @Test + void validateDiagType_localTypesInvalidInDocker() { + DiagnosticInputs inputs = new DiagnosticInputs(); + inputs.runningInDocker = true; + String[] localTypes = { Constants.local, Constants.logstashLocal, Constants.kibanaLocal }; + for (String type : localTypes) { + List errors = inputs.validateDiagType(type); + assertNotNull(errors, "Expected error for local type in Docker: " + type); + assertEquals(1, errors.size()); + } + } + @Test void validateDiagType_invalid() { DiagnosticInputs inputs = new DiagnosticInputs(); From ec7da641deae43b7c97ebaca4fa73be63ff2d716 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 17:49:52 -0600 Subject: [PATCH 26/30] Also capture e2eTest output --- .buildkite/default-pipeline.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index 395a83a3..95ad8262 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -8,6 +8,7 @@ steps: - docker run --rm -v "$$(pwd)/test-reports:/app/build/reports/tests" support-diagnostics-test artifact_paths: - "test-reports/test/**/*" + - "test-reports/e2eTest/**/*" agents: provider: "gcp" imagePrefix: "core-ubuntu-2204" From 4b85c97434717421a7953e3fa9f9325f92f0898a Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 21:20:30 -0600 Subject: [PATCH 27/30] Let Docker see the socket --- .buildkite/default-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index 95ad8262..e7d4a46d 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -5,7 +5,7 @@ steps: key: "gradle-test" commands: - docker build -f Dockerfile.test -t support-diagnostics-test . - - docker run --rm -v "$$(pwd)/test-reports:/app/build/reports/tests" support-diagnostics-test + - docker run --rm -v "$$(pwd)/test-reports:/app/build/reports/tests" -v /var/run/docker.sock:/var/run/docker.sock support-diagnostics-test artifact_paths: - "test-reports/test/**/*" - "test-reports/e2eTest/**/*" From 84179485972bc430ed5f43416e519bfada67a557 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 21:30:44 -0600 Subject: [PATCH 28/30] Try without running it in Docker at all --- .buildkite/default-pipeline.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index e7d4a46d..b7a25f4a 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -4,11 +4,7 @@ steps: - label: ":gradle: Test" key: "gradle-test" commands: - - docker build -f Dockerfile.test -t support-diagnostics-test . - - docker run --rm -v "$$(pwd)/test-reports:/app/build/reports/tests" -v /var/run/docker.sock:/var/run/docker.sock support-diagnostics-test - artifact_paths: - - "test-reports/test/**/*" - - "test-reports/e2eTest/**/*" + - ./gradlew test e2eTest --no-daemon agents: provider: "gcp" imagePrefix: "core-ubuntu-2204" From 7f3b649f600b70c4213146ce6913dcddd35e535f Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 21:41:22 -0600 Subject: [PATCH 29/30] Debug Docker --- .buildkite/default-pipeline.yml | 11 ++++++++++- Dockerfile.test | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index b7a25f4a..a0d2ab17 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -4,7 +4,16 @@ steps: - label: ":gradle: Test" key: "gradle-test" commands: - - ./gradlew test e2eTest --no-daemon + - docker build -f Dockerfile.test -t support-diagnostics-test . + - docker ps + - echo $DOCKER_HOST + - ls -l /var/run/docker.sock + - docker run --rm -v "$$(pwd)/test-reports:/app/build/reports/tests" -v /var/run/docker.sock:/var/run/docker.sock support-diagnostics-test + environment: + DOCKER_HOST: unix:///var/run/docker.sock + artifact_paths: + - "test-reports/test/**/*" + - "test-reports/e2eTest/**/*" agents: provider: "gcp" imagePrefix: "core-ubuntu-2204" diff --git a/Dockerfile.test b/Dockerfile.test index 8f40c504..0fb0cf08 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -8,4 +8,4 @@ COPY . . ENV GRADLE_OPTS="-Xmx512m -XX:MaxMetaspaceSize=256m" -CMD ["./gradlew", "test", "e2eTest", "--no-daemon", "--stacktrace", "-Dorg.gradle.workers.max=1"] +CMD ["./gradlew", "test", "e2eTest", "--no-daemon", "--stacktrace"] From 8464864cbff9511a0f52a485e367ef9c47e75c05 Mon Sep 17 00:00:00 2001 From: Chris Earle Date: Fri, 1 May 2026 22:11:47 -0600 Subject: [PATCH 30/30] Drop environment --- .buildkite/default-pipeline.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index a0d2ab17..15a0a51f 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -9,8 +9,6 @@ steps: - echo $DOCKER_HOST - ls -l /var/run/docker.sock - docker run --rm -v "$$(pwd)/test-reports:/app/build/reports/tests" -v /var/run/docker.sock:/var/run/docker.sock support-diagnostics-test - environment: - DOCKER_HOST: unix:///var/run/docker.sock artifact_paths: - "test-reports/test/**/*" - "test-reports/e2eTest/**/*"