package org.arquillian.cube.docker.impl.await;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.arquillian.cube.HealthCheck;
import org.arquillian.cube.docker.impl.docker.DockerClientExecutor;
import org.arquillian.cube.docker.impl.util.Ping;
import org.arquillian.cube.impl.util.ReflectionUtil;
import org.arquillian.cube.impl.util.Timespan;
import org.arquillian.cube.spi.Cube;
import org.arquillian.cube.spi.CubeRegistry;
import org.arquillian.cube.spi.metadata.HasPortBindings;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.api.annotation.Observes;
import org.jboss.arquillian.test.spi.TestClass;
import org.jboss.arquillian.test.spi.event.suite.BeforeClass;
public class HealthCheckBeforeClassObserver {
@Inject
Instance<DockerClientExecutor> dockerClientExecutorInstance;
@Inject
Instance<CubeRegistry> cubeRegistryInstance;
public void executeHealthCheck(@Observes BeforeClass beforeClass) {
final TestClass testClass = beforeClass.getTestClass();
if (ReflectionUtil.isClassWithAnnotation(testClass.getJavaClass(), HealthCheck.class)) {
final HealthCheck healthCheck = testClass.getAnnotation(HealthCheck.class);
executeHealthCheck(healthCheck);
}
}
private boolean executeHealthCheck(HealthCheck healthCheck) {
final URL url = buildUrl(healthCheck);
final int pollIterations = healthCheck.iterations();
final long sleepTime = Timespan.toMilliseconds(healthCheck.interval());
final int responseCode = healthCheck.responseCode();
final String method = healthCheck.method();
final Long connectTimeout = Timespan.toMilliseconds(healthCheck.timeout());
return Ping.ping(pollIterations, sleepTime, TimeUnit.MILLISECONDS, () -> {
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod(method);
urlConnection.setConnectTimeout(connectTimeout.intValue());
urlConnection.setReadTimeout(connectTimeout.intValue());
urlConnection.connect();
int connectionResponseCode = urlConnection.getResponseCode();
if (responseCode != connectionResponseCode) {
return false;
}
} catch (IOException e) {
return false;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return true;
});
}
private URL buildUrl(HealthCheck healthCheck) {
final String dockerServerIp = dockerClientExecutorInstance.get().getDockerServerIp();
final String schema = healthCheck.schema();
final int port = resolvePort(healthCheck.containerName(), healthCheck.port());
final String context = healthCheck.value();
return getUrlToService(schema, dockerServerIp, port, context);
}
private URL getUrlToService(String schema, String dockerServerIp, int port, String context) {
try {
return new URL(schema, dockerServerIp, port, context);
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
}
private int resolvePort(String containerName, int port) {
if ("".equals(containerName.trim())) {
return port;
}
return getBindingPort(containerName, port);
}
private int getBindingPort(String cubeId, int exposedPort) {
int bindPort = -1;
final Cube cube = getCube(cubeId);
if (cube != null) {
final HasPortBindings portBindings = (HasPortBindings) cube.getMetadata(HasPortBindings.class);
final HasPortBindings.PortAddress mappedAddress = portBindings.getMappedAddress(exposedPort);
if (mappedAddress != null) {
bindPort = mappedAddress.getPort();
}
}
return bindPort;
}
private Cube getCube(String cubeId) {
return cubeRegistryInstance.get().getCube(cubeId);
}
}