diff --git a/.buildkite/default-pipeline.yml b/.buildkite/default-pipeline.yml index 8ea91e6a..15a0a51f 100644 --- a/.buildkite/default-pipeline.yml +++ b/.buildkite/default-pipeline.yml @@ -1,23 +1,44 @@ --- # $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: + - 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 + artifact_paths: + - "test-reports/test/**/*" + - "test-reports/e2eTest/**/*" + 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" 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/Dockerfile b/Dockerfile index 7e21af0d..03905446 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.3-r2@sha256:ef761f476e5f50b6755c17c7d679d7e08b8cca47ec3b8f12765adb7f863f0418 AS runner diff --git a/Dockerfile.test b/Dockerfile.test new file mode 100644 index 00000000..0fb0cf08 --- /dev/null +++ b/Dockerfile.test @@ -0,0 +1,11 @@ +FROM docker.elastic.co/wolfi/jdk:openjdk-25.0.2-r2-dev@sha256:05e5fd81a2a335ca2872ee70dcd1cc6b183c412b0e559e5eca648a82872d281d + +USER root + +WORKDIR /app + +COPY . . + +ENV GRADLE_OPTS="-Xmx512m -XX:MaxMetaspaceSize=256m" + +CMD ["./gradlew", "test", "e2eTest", "--no-daemon", "--stacktrace"] diff --git a/build.gradle.kts b/build.gradle.kts index 9977f623..fc100358 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -185,6 +185,8 @@ tasks.named("build") { // --------------------------------------------------------------------------- tasks.withType { useJUnitPlatform() + jvmArgs("-Djava.net.preferIPv4Stack=true", "-Djava.security.egd=file:/dev/./urandom") + maxHeapSize = "512m" } tasks.named("test") { @@ -206,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" } 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 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); 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();