Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.apache.camel.quarkus.component.master.it;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
Expand All @@ -37,6 +38,8 @@
import org.eclipse.microprofile.config.ConfigProvider;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zeroturnaround.exec.ProcessExecutor;
import org.zeroturnaround.exec.StartedProcess;

Expand All @@ -47,6 +50,7 @@
@QuarkusTest
class MasterOpenShiftTest {

private static final Logger LOG = LoggerFactory.getLogger(MasterOpenShiftTest.class);
@KubernetesTestServer
private KubernetesServer mockOpenShiftServer;

Expand All @@ -69,38 +73,47 @@ public void testFailover() throws IOException {
jvmArgs.add("-Dkubernetes.trust.certificates=" + config.getValue("kubernetes.trust.certificates", String.class));
jvmArgs.add(
"-Dkubernetes.auth.tryServiceAccount=" + config.getValue("kubernetes.auth.tryServiceAccount", String.class));
jvmArgs.add("-Dhttp2.disable=" + config.getValue("http2.disable", String.class));

// Start secondary application process faking KubernetesClusterService so it assumes being run from a pod named follower
Consumer<ProcessExecutor> customizer = pe -> pe.environment("HOSTNAME", "follower");
QuarkusProcessExecutor followerProcessExecutor = new QuarkusProcessExecutor(customizer, jvmArgs.toArray(String[]::new));
StartedProcess followerProcess = null;

try {
// Verify that this process is the cluster leader
Awaitility.await().atMost(10, TimeUnit.SECONDS).with().until(() -> {
return readLeaderFile("leader").equals("leader");
});

// Start the follower process and wait until fully initialized
followerProcess = followerProcessExecutor.start();
awaitStartup(followerProcessExecutor);

// Verify the follower hasn't taken the leader role yet
assertThat(readLeaderFile("follower"), emptyString());

// Stop camel and delete the lease mock to trigger fail-over
RestAssured.given().get("/master/camel/stop/leader").then().statusCode(204);
mockOpenShiftServer.getClient().leases().delete();

// Verify that the secondary application has been elected as the
// cluster leader
Awaitility.await().atMost(10, TimeUnit.SECONDS).until(() -> {
return readLeaderFile("follower").equals("leader");
});
} finally {
if (followerProcess != null && followerProcess.getProcess().isAlive()) {
followerProcessExecutor.destroy();
try (ByteArrayOutputStream standardStream = new ByteArrayOutputStream();
ByteArrayOutputStream errorStream = new ByteArrayOutputStream()) {
Consumer<ProcessExecutor> customizer = pe -> pe.environment("HOSTNAME", "follower")
.redirectOutputAlsoTo(standardStream)
.redirectErrorAlsoTo(errorStream);
QuarkusProcessExecutor followerProcessExecutor = new QuarkusProcessExecutor(customizer,
jvmArgs.toArray(String[]::new));
StartedProcess followerProcess = null;

try {
// Verify that this process is the cluster leader
Awaitility.await().atMost(10, TimeUnit.SECONDS).with().until(() -> {
return readLeaderFile("leader").equals("leader");
});

// Start the follower process and wait until fully initialized
followerProcess = followerProcessExecutor.start();
awaitStartup(followerProcessExecutor);

// Verify the follower hasn't taken the leader role yet
assertThat(readLeaderFile("follower"), emptyString());

// Stop camel and delete the lease mock to trigger fail-over
RestAssured.given().get("/master/camel/stop/leader").then().statusCode(204);
mockOpenShiftServer.getClient().leases().delete();

// Verify that the secondary application has been elected as the
// cluster leader
Awaitility.await().atMost(10, TimeUnit.SECONDS).until(() -> {
return readLeaderFile("follower").equals("leader");
});
} finally {
LOG.info("Follower process standard log[start] {}", standardStream);
LOG.info("Follower process standard log[end]");
LOG.info("Follower process error log[start] {}", errorStream);
LOG.info("Follower process error log[end]");
if (followerProcess != null && followerProcess.getProcess().isAlive()) {
followerProcessExecutor.destroy();
}
}
}
}
Expand All @@ -116,6 +129,7 @@ private boolean isApplicationHealthy(int port) {
int status = RestAssured.given().port(port).get("/q/health").then().extract().statusCode();
return status == 200;
} catch (Exception e) {
LOG.error("App is not healthy yet", e);
return false;
}
}
Expand Down