diff --git a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/containers/PulsarContainer.java b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/containers/PulsarContainer.java index 8c6a5d8267861..e53db88e4208f 100644 --- a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/containers/PulsarContainer.java +++ b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/containers/PulsarContainer.java @@ -22,8 +22,10 @@ import java.time.Duration; import java.util.Objects; +import java.util.UUID; import lombok.extern.slf4j.Slf4j; import org.apache.pulsar.tests.integration.utils.DockerUtils; +import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; @@ -48,6 +50,16 @@ public abstract class PulsarContainer> exte public static final String PULSAR_2_1_IMAGE_NAME = "apachepulsar/pulsar:2.1.0"; public static final String PULSAR_2_0_IMAGE_NAME = "apachepulsar/pulsar:2.0.0"; + /** + * For debugging purposes, it is useful to have the ability to leave containers running. + * This mode can be activated by setting environment variables + * PULSAR_CONTAINERS_LEAVE_RUNNING=true and TESTCONTAINERS_REUSE_ENABLE=true + * After debugging, one can use this command to kill all containers that were left running: + * docker kill $(docker ps -q --filter "label=pulsarcontainer=true") + */ + public static final boolean PULSAR_CONTAINERS_LEAVE_RUNNING = + Boolean.parseBoolean(System.getenv("PULSAR_CONTAINERS_LEAVE_RUNNING")); + private final String hostname; private final String serviceName; private final String serviceEntryPoint; @@ -71,13 +83,8 @@ public PulsarContainer(String clusterName, int servicePort, int httpPort, String httpPath) { - super(clusterName, DEFAULT_IMAGE_NAME); - this.hostname = hostname; - this.serviceName = serviceName; - this.serviceEntryPoint = serviceEntryPoint; - this.servicePort = servicePort; - this.httpPort = httpPort; - this.httpPath = httpPath; + this(clusterName, hostname, serviceName, serviceEntryPoint, servicePort, httpPort, httpPath, + DEFAULT_IMAGE_NAME); } public PulsarContainer(String clusterName, @@ -95,6 +102,20 @@ public PulsarContainer(String clusterName, this.servicePort = servicePort; this.httpPort = httpPort; this.httpPath = httpPath; + + configureLeaveContainerRunning(this); + } + + public static void configureLeaveContainerRunning( + GenericContainer container) { + if (PULSAR_CONTAINERS_LEAVE_RUNNING) { + // use Testcontainers reuse containers feature to leave the container running + container.withReuse(true); + // add label that can be used to find containers that are left running. + container.withLabel("pulsarcontainer", "true"); + // add a random label to prevent reuse of containers + container.withLabel("pulsarcontainer.random", UUID.randomUUID().toString()); + } } @Override @@ -109,6 +130,15 @@ protected void beforeStop() { } } + @Override + public void stop() { + if (PULSAR_CONTAINERS_LEAVE_RUNNING) { + log.warn("Ignoring stop due to PULSAR_CONTAINERS_LEAVE_RUNNING=true."); + return; + } + super.stop(); + } + @Override public String getContainerName() { return clusterName + "-" + hostname; diff --git a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/topologies/PulsarCluster.java b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/topologies/PulsarCluster.java index dfb24f3c70a67..f9b7c699894a4 100644 --- a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/topologies/PulsarCluster.java +++ b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/topologies/PulsarCluster.java @@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static org.apache.pulsar.tests.integration.containers.PulsarContainer.BROKER_HTTP_PORT; import static org.apache.pulsar.tests.integration.containers.PulsarContainer.CS_PORT; +import static org.apache.pulsar.tests.integration.containers.PulsarContainer.PULSAR_CONTAINERS_LEAVE_RUNNING; import static org.apache.pulsar.tests.integration.containers.PulsarContainer.ZK_PORT; import com.google.common.collect.Lists; @@ -269,6 +270,7 @@ public void start() throws Exception { GenericContainer serviceContainer = service.getValue(); serviceContainer.withNetwork(network); serviceContainer.withNetworkAliases(service.getKey()); + PulsarContainer.configureLeaveContainerRunning(serviceContainer); serviceContainer.start(); log.info("Successfully start external service {}.", service.getKey()); }); @@ -280,12 +282,17 @@ public void startService(String networkAlias, log.info("Starting external service {} ...", networkAlias); serviceContainer.withNetwork(network); serviceContainer.withNetworkAliases(networkAlias); + PulsarContainer.configureLeaveContainerRunning(serviceContainer); serviceContainer.start(); log.info("Successfully start external service {}", networkAlias); } - public void stopService(String networkAlias, - GenericContainer serviceContainer) { + public static void stopService(String networkAlias, + GenericContainer serviceContainer) { + if (PULSAR_CONTAINERS_LEAVE_RUNNING) { + logIgnoringStopDueToLeaveRunning(); + return; + } log.info("Stopping external service {} ...", networkAlias); serviceContainer.stop(); log.info("Successfully stop external service {}", networkAlias); @@ -309,6 +316,10 @@ public PrestoWorkerContainer getPrestoWorkerContainer() { } public synchronized void stop() { + if (PULSAR_CONTAINERS_LEAVE_RUNNING) { + logIgnoringStopDueToLeaveRunning(); + return; + } List containers = new ArrayList<>(); @@ -361,6 +372,10 @@ public void startPrestoWorker(String offloadDriver, String offloadProperties) { } public void stopPrestoWorker() { + if (PULSAR_CONTAINERS_LEAVE_RUNNING) { + logIgnoringStopDueToLeaveRunning(); + return; + } if (sqlFollowWorkerContainers != null && sqlFollowWorkerContainers.size() > 0) { for (PrestoWorkerContainer followWorker : sqlFollowWorkerContainers.values()) { followWorker.stop(); @@ -495,6 +510,10 @@ public synchronized void startWorkers() { } public synchronized void stopWorkers() { + if (PULSAR_CONTAINERS_LEAVE_RUNNING) { + logIgnoringStopDueToLeaveRunning(); + return; + } // Stop workers that have been initialized workerContainers.values().parallelStream().forEach(WorkerContainer::stop); workerContainers.clear(); @@ -502,6 +521,7 @@ public synchronized void stopWorkers() { public void startContainers(Map> containers) { containers.forEach((name, container) -> { + PulsarContainer.configureLeaveContainerRunning(container); container .withNetwork(network) .withNetworkAliases(name) @@ -510,11 +530,19 @@ public void startContainers(Map> containers) { }); } - public void stopContainers(Map> containers) { + public static void stopContainers(Map> containers) { + if (PULSAR_CONTAINERS_LEAVE_RUNNING) { + logIgnoringStopDueToLeaveRunning(); + return; + } containers.values().parallelStream().forEach(GenericContainer::stop); log.info("Successfully stop containers : {}", containers); } + private static void logIgnoringStopDueToLeaveRunning() { + log.warn("Ignoring stop due to PULSAR_CONTAINERS_LEAVE_RUNNING=true."); + } + public BrokerContainer getAnyBroker() { return getAnyContainer(brokerContainers, "pulsar-broker"); }