<commit_before>package org.jboss.pnc.environment.docker;

import org.jboss.pnc.common.Configuration;
import org.jboss.pnc.common.json.ConfigurationParseException;
import org.jboss.pnc.common.json.moduleconfig.DockerEnvironmentDriverModuleConfig;
import org.jboss.pnc.common.util.HttpUtils;
import org.jboss.pnc.model.BuildType;
import org.jboss.pnc.model.Environment;
import org.jboss.pnc.model.OperationalSystem;
import org.jboss.pnc.spi.environment.EnvironmentDriver;
import org.jboss.pnc.spi.environment.StartedEnvironment;
import org.jboss.pnc.spi.environment.exception.EnvironmentDriverException;
import org.jboss.pnc.spi.repositorymanager.model.RepositorySession;
import org.jclouds.ContextBuilder;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.docker.DockerApi;
import org.jclouds.docker.domain.Config;
import org.jclouds.docker.domain.Container;
import org.jclouds.docker.domain.HostConfig;
import org.jclouds.docker.features.RemoteApi;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.io.Payloads;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.ssh.SshClient;
import org.jclouds.sshj.SshjSshClient;
import org.jclouds.sshj.config.SshjSshClientModule;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

import java.io.InputStream;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.HostAndPort;
import com.google.inject.Module;
import com.jcraft.jsch.agentproxy.Connector;

/**
 * Implementation of environment driver, which uses Docker to run environments
 * 
 * @author <NAME> &lt;<EMAIL>&gt;
 *
 */
@ApplicationScoped
public class DockerEnvironmentDriver implements EnvironmentDriver {

    private static final Logger logger = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());

    @Inject
    private Generator generator;

    @Inject
    private ConfigurationBuilder configBuilder;

    @Inject
    private DockerInitializationMonitor dockerInitMonitor;

    private ComputeServiceContext dockerContext;

    private RemoteApi dockerClient;

    /** User in running environment to which we can connect with SSH */
    private String containerUser;

    /** Password of user to which we can connect with SSH */
    private String containerUserPsswd;

    /** Connection URL to Docker control port */
    private String dockerEndpoint;

    /** ID of docker image */
    private String dockerImageId;

    private String dockerIp;

    private String containerFirewallAllowedDestinations;

    /**
     * States of creating Docker container
     * 
     * @author <NAME> &lt;<EMAIL>&gt;
     *
     */
    private enum BuildContainerState {
        NOT_BUILT,
        BUILT,
        STARTED,
    }

    /**
     * Only workaround for CDI constructor parameter injection
     */
    @Deprecated
    public DockerEnvironmentDriver() {
    }

    /**
     * Loads configuration, prepares connection to Docker daemon
     * 
     * @throws ConfigurationParseException Thrown if configuration cannot be obtained
     */
    @Inject
    public DockerEnvironmentDriver(Configuration configuration) throws ConfigurationParseException {
        DockerEnvironmentDriverModuleConfig config =
                configuration.getModuleConfig(DockerEnvironmentDriverModuleConfig.class);

        dockerIp = config.getIp();
        dockerEndpoint = "http://" + dockerIp + ":2375";
        containerUser = config.getInContainerUser();
        containerUserPsswd = config.getInContainerUserPassword();
        dockerImageId = config.getDockerImageId();
        containerFirewallAllowedDestinations = config.getFirewallAllowedDestinations();

        dockerContext = ContextBuilder.newBuilder("docker")
                .endpoint(dockerEndpoint)
                .credentials(containerUser, containerUserPsswd)
                .modules(ImmutableSet.<Module> of(new SLF4JLoggingModule(),
                        new SshjSshClientModule()))
                .buildView(ComputeServiceContext.class);
        dockerClient = dockerContext.unwrapApi(DockerApi.class).getRemoteApi();
    }

    @Override
    public StartedEnvironment buildEnvironment(Environment buildEnvironment,
            RepositorySession repositorySession) throws EnvironmentDriverException {
        if (!canBuildEnvironment(buildEnvironment))
            throw new UnsupportedOperationException(
                    "DockerEnvironmentDriver currently provides support only for Linux enviroments on Docker.");

        String containerId = generator.generateContainerId();
        BuildContainerState buildContainerState = BuildContainerState.NOT_BUILT;

        logger.info("Trying to start Docker container...");
        int sshPort, jenkinsPort;
        try {
            Container createdContainer = dockerClient.createContainer(
                    containerId,
                    Config.builder()
                            .imageId(dockerImageId)
                            .env(prepareEnvVariables())
                            .build());
            buildContainerState = BuildContainerState.BUILT;

            dockerClient.startContainer(containerId,
                    HostConfig.builder()
                            .publishAllPorts(true)
                            .privileged(true)
                            .build());
            buildContainerState = BuildContainerState.STARTED;

            Map<String, HostPortMapping> containerPortMappings =
                    getContainerPortMappings(createdContainer.getId());
            // Find out, which ports are opened for SSH and Jenkins
            sshPort = getSshPort(containerPortMappings);
            jenkinsPort = getJenkinsPort(containerPortMappings);

            copyFileToContainer(sshPort, "/root/.m2/settings.xml",
                    configBuilder.createMavenConfig(repositorySession.getConnectionInfo()
                            .getDependencyUrl(),
                            repositorySession.getConnectionInfo().getDeployUrl()), null);
<commit_msg>Add debug logging to Docker env driver.<commit_after>package org.jboss.pnc.environment.docker;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.HostAndPort;
import com.google.inject.Module;
import com.jcraft.jsch.agentproxy.Connector;
import org.jboss.pnc.common.Configuration;
import org.jboss.pnc.common.json.ConfigurationParseException;
import org.jboss.pnc.common.json.moduleconfig.DockerEnvironmentDriverModuleConfig;
import org.jboss.pnc.common.util.HttpUtils;
import org.jboss.pnc.model.BuildType;
import org.jboss.pnc.model.Environment;
import org.jboss.pnc.model.OperationalSystem;
import org.jboss.pnc.spi.environment.EnvironmentDriver;
import org.jboss.pnc.spi.environment.StartedEnvironment;
import org.jboss.pnc.spi.environment.exception.EnvironmentDriverException;
import org.jboss.pnc.spi.repositorymanager.model.RepositorySession;
import org.jclouds.ContextBuilder;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.docker.DockerApi;
import org.jclouds.docker.domain.Config;
import org.jclouds.docker.domain.Container;
import org.jclouds.docker.domain.HostConfig;
import org.jclouds.docker.features.RemoteApi;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.io.Payloads;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.ssh.SshClient;
import org.jclouds.sshj.SshjSshClient;
import org.jclouds.sshj.config.SshjSshClientModule;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.io.InputStream;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

/**
 * Implementation of environment driver, which uses Docker to run environments
 * 
 * @author <NAME> &lt;<EMAIL>&gt;
 *
 */
@ApplicationScoped
public class DockerEnvironmentDriver implements EnvironmentDriver {

    private static final Logger logger = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());

    @Inject
    private Generator generator;

    @Inject
    private ConfigurationBuilder configBuilder;

    @Inject
    private DockerInitializationMonitor dockerInitMonitor;

    private ComputeServiceContext dockerContext;

    private RemoteApi dockerClient;

    /** User in running environment to which we can connect with SSH */
    private String containerUser;

    /** Password of user to which we can connect with SSH */
    private String containerUserPsswd;

    /** Connection URL to Docker control port */
    private String dockerEndpoint;

    /** ID of docker image */
    private String dockerImageId;

    private String dockerIp;

    private String containerFirewallAllowedDestinations;

    /**
     * States of creating Docker container
     * 
     * @author <NAME> &lt;<EMAIL>&gt;
     *
     */
    private enum BuildContainerState {
        NOT_BUILT,
        BUILT,
        STARTED,
    }

    /**
     * Only workaround for CDI constructor parameter injection
     */
    @Deprecated
    public DockerEnvironmentDriver() {
    }

    /**
     * Loads configuration, prepares connection to Docker daemon
     * 
     * @throws ConfigurationParseException Thrown if configuration cannot be obtained
     */
    @Inject
    public DockerEnvironmentDriver(Configuration configuration) throws ConfigurationParseException {
        DockerEnvironmentDriverModuleConfig config =
                configuration.getModuleConfig(DockerEnvironmentDriverModuleConfig.class);

        dockerIp = config.getIp();
        dockerEndpoint = "http://" + dockerIp + ":2375";
        containerUser = config.getInContainerUser();
        containerUserPsswd = config.getInContainerUserPassword();
        dockerImageId = config.getDockerImageId();
        containerFirewallAllowedDestinations = config.getFirewallAllowedDestinations();

        dockerContext = ContextBuilder.newBuilder("docker")
                .endpoint(dockerEndpoint)
                .credentials(containerUser, containerUserPsswd)
                .modules(ImmutableSet.<Module> of(new SLF4JLoggingModule(),
                        new SshjSshClientModule()))
                .buildView(ComputeServiceContext.class);
        dockerClient = dockerContext.unwrapApi(DockerApi.class).getRemoteApi();
    }

    @Override
    public StartedEnvironment buildEnvironment(Environment buildEnvironment,
            RepositorySession repositorySession) throws EnvironmentDriverException {
        if (!canBuildEnvironment(buildEnvironment))
            throw new UnsupportedOperationException(
                    "DockerEnvironmentDriver currently provides support only for Linux enviroments on Docker.");

        String containerId = generator.generateContainerId();
        BuildContainerState buildContainerState = BuildContainerState.NOT_BUILT;

        logger.info("Trying to start Docker container...");
        int sshPort, jenkinsPort;
        try {
            Config config = Config.builder()
                    .imageId(dockerImageId)
                    .env(prepareEnvVariables())
                    .build();
            logger.fine("Creating docker container with config: " + config);
            Container createdContainer = dockerClient.createContainer(containerId, config);
            buildContainerState = BuildContainerState.BUILT;

            dockerClient.startContainer(containerId,
                    HostConfig.builder()
                            .publishAllPorts(true)
                            .privileged(true)
                            .build());
            buildContainerState = BuildContainerState.STARTED;

            Map<String, HostPortMapping> containerPortMappings =
                    getContainerPortMappings(createdContainer.getId());
            // Find out, which ports are opened for SSH and Jenkins
            sshPort = getSshPort(containerPortMappings);
            jenkinsPort = getJenkinsPort(containerPortMappings);

            copyFileToContainer(sshPort, "/root/.m2/settings.xml",
                    configBuilder.createMavenConfig(repositorySession.getConnectionInfo()
                            .getDependencyUrl(),
                            repositorySession.getConnectionInfo().getDeployUrl()), null);

{'fraction_non_alphanumeric': 0.08326926034138091, 'fraction_numerical': 0.0012302014454866985, 'mean_word_length': 3.185006435006435, 'pattern_counts': {'":': 2, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6277885', 'n_tokens_mistral': 3504, 'n_tokens_neox': 3284, 'n_words': 682}