use of org.testcontainers.containers.output.FrameConsumerResultCallback in project testcontainers-java by testcontainers.
the class LogUtils method followOutput.
/**
* {@inheritDoc}
*/
public void followOutput(DockerClient dockerClient, String containerId, Consumer<OutputFrame> consumer, OutputFrame.OutputType... types) {
final LogContainerCmd cmd = dockerClient.logContainerCmd(containerId).withFollowStream(true).withSince(0);
final FrameConsumerResultCallback callback = new FrameConsumerResultCallback();
for (OutputFrame.OutputType type : types) {
callback.addConsumer(type, consumer);
if (type == STDOUT)
cmd.withStdOut(true);
if (type == STDERR)
cmd.withStdErr(true);
}
cmd.exec(callback);
}
use of org.testcontainers.containers.output.FrameConsumerResultCallback in project testcontainers-java by testcontainers.
the class ExecInContainerPattern method execInContainer.
/**
* Run a command inside a running container, as though using "docker exec".
* <p>
* This functionality is not available on a docker daemon running the older "lxc" execution driver. At
* the time of writing, CircleCI was using this driver.
* @param containerInfo the container info
* @param outputCharset the character set used to interpret the output.
* @param command the parts of the command to run
* @return the result of execution
* @throws IOException if there's an issue communicating with Docker
* @throws InterruptedException if the thread waiting for the response is interrupted
* @throws UnsupportedOperationException if the docker daemon you're connecting to doesn't support "exec".
*/
public Container.ExecResult execInContainer(InspectContainerResponse containerInfo, Charset outputCharset, String... command) throws UnsupportedOperationException, IOException, InterruptedException {
if (!TestEnvironment.dockerExecutionDriverSupportsExec()) {
// at time of writing, this is the expected result in CircleCI.
throw new UnsupportedOperationException("Your docker daemon is running the \"lxc\" driver, which doesn't support \"docker exec\".");
}
if (!isRunning(containerInfo)) {
throw new IllegalStateException("execInContainer can only be used while the Container is running");
}
String containerId = containerInfo.getId();
String containerName = containerInfo.getName();
DockerClient dockerClient = DockerClientFactory.instance().client();
dockerClient.execCreateCmd(containerId).withCmd(command);
log.debug("{}: Running \"exec\" command: {}", containerName, String.join(" ", command));
final ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId).withAttachStdout(true).withAttachStderr(true).withCmd(command).exec();
final ToStringConsumer stdoutConsumer = new ToStringConsumer();
final ToStringConsumer stderrConsumer = new ToStringConsumer();
FrameConsumerResultCallback callback = new FrameConsumerResultCallback();
callback.addConsumer(OutputFrame.OutputType.STDOUT, stdoutConsumer);
callback.addConsumer(OutputFrame.OutputType.STDERR, stderrConsumer);
dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec(callback).awaitCompletion();
final Container.ExecResult result = new Container.ExecResult(stdoutConsumer.toString(outputCharset), stderrConsumer.toString(outputCharset));
log.trace("{}: stdout: {}", containerName, result.getStdout());
log.trace("{}: stderr: {}", containerName, result.getStderr());
return result;
}
use of org.testcontainers.containers.output.FrameConsumerResultCallback in project testcontainers-java by testcontainers.
the class GenericContainer method tryStart.
private void tryStart(Profiler profiler) {
try {
String dockerImageName = image.get();
logger().debug("Starting container: {}", dockerImageName);
logger().info("Creating container for image: {}", dockerImageName);
profiler.start("Create container");
CreateContainerCmd createCommand = dockerClient.createContainerCmd(dockerImageName);
applyConfiguration(createCommand);
containerId = createCommand.exec().getId();
logger().info("Starting container with ID: {}", containerId);
profiler.start("Start container");
dockerClient.startContainerCmd(containerId).exec();
// For all registered output consumers, start following as close to container startup as possible
this.logConsumers.forEach(this::followOutput);
logger().info("Container {} is starting: {}", dockerImageName, containerId);
// Tell subclasses that we're starting
profiler.start("Inspecting container");
containerInfo = dockerClient.inspectContainerCmd(containerId).exec();
containerName = containerInfo.getName();
profiler.start("Call containerIsStarting on subclasses");
containerIsStarting(containerInfo);
// Wait until the container is running (may not be fully started)
profiler.start("Wait until container has started properly, or there's evidence it failed to start.");
if (!this.startupCheckStrategy.waitUntilStartupSuccessful(dockerClient, containerId)) {
// (Exception thrown here will be caught below and wrapped)
throw new IllegalStateException("Container did not start correctly.");
}
profiler.start("Wait until container started properly");
waitUntilContainerStarted();
logger().info("Container {} started", dockerImageName);
containerIsStarted(containerInfo);
} catch (Exception e) {
logger().error("Could not start container", e);
// Log output if startup failed, either due to a container failure or exception (including timeout)
logger().error("Container log output (if any) will follow:");
FrameConsumerResultCallback resultCallback = new FrameConsumerResultCallback();
resultCallback.addConsumer(STDOUT, new Slf4jLogConsumer(logger()));
resultCallback.addConsumer(STDERR, new Slf4jLogConsumer(logger()));
dockerClient.logContainerCmd(containerId).withStdOut(true).withStdErr(true).exec(resultCallback);
// Try to ensure that container log output is shown before proceeding
try {
resultCallback.getCompletionLatch().await(1, TimeUnit.MINUTES);
} catch (InterruptedException ignored) {
// Cannot do anything at this point
}
throw new ContainerLaunchException("Could not create/start container", e);
} finally {
profiler.stop();
}
}
Aggregations