Skip to content

Commit

Permalink
♻️ [Test] Improved Job Engine container readiness check
Browse files Browse the repository at this point in the history
Signed-off-by: Alberto Codutti <[email protected]>
  • Loading branch information
Coduz committed Jan 20, 2025
1 parent 4bd1141 commit bd9abbd
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others
* Copyright (c) 2019, 2025 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -40,6 +40,7 @@
import org.eclipse.kapua.qa.common.BasicSteps;
import org.eclipse.kapua.qa.common.DBHelper;
import org.eclipse.kapua.qa.common.StepData;
import org.eclipse.kapua.qa.integration.steps.utils.TestReadinessConnection;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.junit.Assert;
import org.slf4j.Logger;
Expand Down Expand Up @@ -79,12 +80,18 @@ public class DockerSteps {
private static final long WAIT_STEP = 2000;
private static final long WAIT_FOR_DB = 5000;
private static final long WAIT_FOR_ES = 5000;
private static final long WAIT_FOR_EVENTS_BROKER = 5000;
private static final long WAIT_FOR_JOB_ENGINE = 20000;
private static final long WAIT_FOR_EVENTS_BROKER = 10000;
private static final long WAIT_FOR_REST_API = 30000;
private static final long WAIT_FOR_BROKER = 30000;
private static final int HTTP_COMMUNICATION_TIMEOUT = 3000;

private static final int JOB_ENGINE_PORT_INTERNAL = 8080;
private static final int JOB_ENGINE_PORT_EXTERNAL = 8080;
// private static final String JOB_ENGINE_ADDRESS_INTERNAL = "http://job-engine:" + JOB_ENGINE_PORT_INTERNAL; Not used?
private static final String JOB_ENGINE_ADDRESS_EXTERNAL = "http://localhost:" + JOB_ENGINE_PORT_EXTERNAL;
private static final long JOB_ENGINE_READY_CHECK_INTERVAL = 1000;
private static final long JOB_ENGINE_READY_MAX_WAIT = 60000;

private static final int LIFECYCLE_HEALTH_CHECK_PORT = 8090;
private static final int TElEMETRY_HEALTH_CHECK_PORT = 8091;
private static final int AUTH_SERVICE_HEALTH_CHECK_PORT = 8092;
Expand Down Expand Up @@ -669,9 +676,38 @@ public void startJobEngineContainer(String name) throws DockerException, Interru
* @since 2.1.0
*/
private void waitJobEngineContainer(String name) throws Exception{
synchronized (this) {
this.wait(WAIT_FOR_JOB_ENGINE);

long now = System.currentTimeMillis();
while (now + JOB_ENGINE_READY_MAX_WAIT > System.currentTimeMillis()) {
if (isJobEngineContainerReady(name)) {
logger.info("Job Engine ready in: ~{}ms", System.currentTimeMillis() - now);
return;
}

logger.info("Job Engine not ready yet... Retrying in {}ms", JOB_ENGINE_READY_CHECK_INTERVAL);
TimeUnit.MILLISECONDS.sleep(JOB_ENGINE_READY_CHECK_INTERVAL);
}

Assert.fail("Job Engine not ready within: " + JOB_ENGINE_READY_MAX_WAIT + "ms");
}

/**
* Checks if the Job Engine Docker container is ready
*
* @param name The Job Engine Docker container name
* @return {@code true} if is ready, {@code false} otherwise
* @throws Exception
* @since 2.1.0
*/
private boolean isJobEngineContainerReady(String name) throws Exception {
try (TestReadinessConnection testReadinessConnection = new TestReadinessConnection(JOB_ENGINE_ADDRESS_EXTERNAL)){
return testReadinessConnection.isReady();
}
catch (Exception e) {
// Ignoring...
}

return false;
}

@And("Start API container with name {string}")
Expand Down Expand Up @@ -1151,14 +1187,13 @@ private ContainerConfig getEventBrokerContainerConfig() {
* @return Container configuration for job engine instance.
*/
private ContainerConfig getJobEngineContainerConfig() {
final int jobEnginePort = 8080;
final Map<String, List<PortBinding>> portBindings = new HashMap<>();
addHostPort(ALL_IP, portBindings, jobEnginePort, jobEnginePort);
final HostConfig hostConfig = HostConfig.builder().portBindings(portBindings).build();
Map<String, List<PortBinding>> portBindings = new HashMap<>();
addHostPort(ALL_IP, portBindings, JOB_ENGINE_PORT_INTERNAL, JOB_ENGINE_PORT_EXTERNAL);
HostConfig hostConfig = HostConfig.builder().portBindings(portBindings).build();

return ContainerConfig.builder()
.hostConfig(hostConfig)
.exposedPorts(String.valueOf(jobEnginePort))
.exposedPorts(String.valueOf(JOB_ENGINE_PORT_INTERNAL))
.env(
"CRYPTO_SECRET_KEY=kapuaTestsKey!!!"
)
Expand All @@ -1167,16 +1202,19 @@ private ContainerConfig getJobEngineContainerConfig() {
}

/**
* Add docker port to host port mapping.
* Add Docker port to host port mappings.
*
* @param host ip address of host
* @param portBindings list ob bindings that gets updated
* @param port docker port
* @param hostPort port on host
* @param host IP address of host
* @param portBindings {@link List} ob bindings that gets updated
* @param port Docker container port
* @param hostPort Port exposed on host
*
* @since 2.0.0
*/
private void addHostPort(String host, Map<String, List<PortBinding>> portBindings,
int port, int hostPort) {

private void addHostPort(String host,
Map<String, List<PortBinding>> portBindings,
int port,
int hostPort) {
List<PortBinding> hostPorts = new ArrayList<>();
hostPorts.add(PortBinding.of(host, hostPort));
portBindings.put(String.valueOf(port), hostPorts);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*******************************************************************************
* Copyright (c) 2025, 2025 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Eurotech
*******************************************************************************/
package org.eclipse.kapua.qa.integration.steps.utils;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

/**
* Wrapper for {@link HttpURLConnection} that implements {@link AutoCloseable}
*
* @since 2.1.0
*/
public class TestReadinessConnection implements AutoCloseable {

private final HttpURLConnection testReadinessConnection;
private final int readyResponseCode;

/**
* Constructor.
*
* @param testUrl The HTTP URL to check for readiness
* @throws Exception
* @since 2.1.0
*/
public TestReadinessConnection(String testUrl) throws Exception {
this(testUrl, 200);
}


/**
* Constructor.
*
* @param testUrl The HTTP URL to check for readiness
* @param readyResponseCode Which HTTP response code consider valid for readiness
* @throws Exception
* @since 2.1.0
*/
public TestReadinessConnection(String testUrl, int readyResponseCode) throws IOException {
URL testReadinessURL = new URL(testUrl);

testReadinessConnection = (HttpURLConnection) testReadinessURL.openConnection();
testReadinessConnection.setConnectTimeout(5000);
testReadinessConnection.setReadTimeout(5000);
testReadinessConnection.setRequestMethod("GET");

this.readyResponseCode = readyResponseCode;
}

/**
* Checks that the HTTP returns the expected HTTP response code.
*
* @return {@code true} if expected code is returned, {@code false} otherwise
* @throws IOException
* @since 2.1.0
*/
public boolean isReady() throws IOException {
return testReadinessConnection.getResponseCode() == readyResponseCode;
}

/**
* Invokes {@link HttpURLConnection#disconnect()}
*
* @since 2.1.0
*/
@Override
public void close() {
if (testReadinessConnection != null) {
testReadinessConnection.disconnect();
}
}
}

0 comments on commit bd9abbd

Please sign in to comment.