Search in sources :

Example 1 with FrameConsumerResultCallback

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);
}
Also used : FrameConsumerResultCallback(org.testcontainers.containers.output.FrameConsumerResultCallback) OutputFrame(org.testcontainers.containers.output.OutputFrame) LogContainerCmd(com.github.dockerjava.api.command.LogContainerCmd)

Example 2 with FrameConsumerResultCallback

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;
}
Also used : FrameConsumerResultCallback(org.testcontainers.containers.output.FrameConsumerResultCallback) ExecCreateCmdResponse(com.github.dockerjava.api.command.ExecCreateCmdResponse) DockerClient(com.github.dockerjava.api.DockerClient) ToStringConsumer(org.testcontainers.containers.output.ToStringConsumer)

Example 3 with FrameConsumerResultCallback

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();
    }
}
Also used : CreateContainerCmd(com.github.dockerjava.api.command.CreateContainerCmd) FrameConsumerResultCallback(org.testcontainers.containers.output.FrameConsumerResultCallback) Slf4jLogConsumer(org.testcontainers.containers.output.Slf4jLogConsumer) IOException(java.io.IOException)

Aggregations

FrameConsumerResultCallback (org.testcontainers.containers.output.FrameConsumerResultCallback)3 DockerClient (com.github.dockerjava.api.DockerClient)1 CreateContainerCmd (com.github.dockerjava.api.command.CreateContainerCmd)1 ExecCreateCmdResponse (com.github.dockerjava.api.command.ExecCreateCmdResponse)1 LogContainerCmd (com.github.dockerjava.api.command.LogContainerCmd)1 IOException (java.io.IOException)1 OutputFrame (org.testcontainers.containers.output.OutputFrame)1 Slf4jLogConsumer (org.testcontainers.containers.output.Slf4jLogConsumer)1 ToStringConsumer (org.testcontainers.containers.output.ToStringConsumer)1