Package com.kpelykh.docker.client

Source Code of com.kpelykh.docker.client.DockerClient

package com.kpelykh.docker.client;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Preconditions;
import com.kpelykh.docker.client.model.*;
import com.kpelykh.docker.client.utils.CompressArchiveUtil;
import com.kpelykh.docker.client.utils.JsonClientFilter;
import com.sun.jersey.api.client.*;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.client.apache4.ApacheHttpClient4;
import com.sun.jersey.client.apache4.ApacheHttpClient4Handler;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

import static org.apache.commons.io.IOUtils.closeQuietly;

/**
* @author Konstantin Pelykh (kpelykh@gmail.com)
*/
public class DockerClient {

  private static final Logger LOGGER = LoggerFactory.getLogger(DockerClient.class);

    private Client client;
  private String restEndpointUrl;
  private AuthConfig authConfig;

  public DockerClient() throws DockerException {
    this(Config.createConfig());
  }

  public DockerClient(String serverUrl) throws DockerException {
        this(configWithServerUrl(serverUrl));
    }

  public DockerClient(String serverUrl, String version) throws DockerException {
    this(configWithServerUrlAndVersion(serverUrl, version));
  }

  private static Config configWithServerUrl(String serverUrl) throws DockerException {
    final Config c = Config.createConfig();
    c.url = URI.create(serverUrl);
    return c;
  }

  private static Config configWithServerUrlAndVersion(String serverUrl, String version) throws DockerException {
        final Config c = configWithServerUrl(serverUrl);
    c.version = version;
        return c;
    }

    private DockerClient(Config config) {
    restEndpointUrl = config.url + "/v" + config.version;
    ClientConfig clientConfig = new DefaultClientConfig();
    //clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);

    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", config.url.getPort(), PlainSocketFactory.getSocketFactory()));
    schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));

    PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);
    // Increase max total connection
    cm.setMaxTotal(1000);
    // Increase default max connection per route
    cm.setDefaultMaxPerRoute(1000);

    HttpClient httpClient = new DefaultHttpClient(cm);
    client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig);

    client.setReadTimeout(10000);
    //Experimental support for unix sockets:
    //client = new UnixSocketClient(clientConfig);

    client.addFilter(new JsonClientFilter());
    client.addFilter(new LoggingFilter());
  }

  public void setCredentials(String username, String password, String email) {
    if (username == null) {
      throw new IllegalArgumentException("username is null");
    }
    if (password == null) {
      throw new IllegalArgumentException("password is null");
    }
    if (email == null) {
      throw new IllegalArgumentException("email is null");
    }
    authConfig = new AuthConfig();
    authConfig.setUsername(username);
    authConfig.setPassword(password);
    authConfig.setEmail(email);
  }

  /**
   * Authenticate with the server, useful for checking authentication.
   */
  public void auth() throws DockerException {
    try {
      client.resource(restEndpointUrl + "/auth")
          .header("Content-Type", MediaType.APPLICATION_JSON)
          .accept(MediaType.APPLICATION_JSON)
          .post(authConfig());
    } catch (UniformInterfaceException e) {
      throw new DockerException(e);
    }
  }

  private String registryAuth() throws DockerException {
    try {
      return Base64.encodeBase64String(new ObjectMapper().writeValueAsString(authConfig()).getBytes());
    } catch (IOException e) {
      throw new DockerException(e);
    }
  }

    public AuthConfig authConfig() throws DockerException {
        return authConfig != null
                ? authConfig
                : authConfigFromProperties();
    }

    private static AuthConfig authConfigFromProperties() throws DockerException {
        final AuthConfig a = new AuthConfig();

        a.setUsername(Config.createConfig().username);
        a.setPassword(Config.createConfig().password);
        a.setEmail(Config.createConfig().email);

        if (a.getUsername() == null) {throw new IllegalStateException("username is null");}
        if (a.getPassword() == null) {throw new IllegalStateException("password is null");}
        if (a.getEmail() == null) {throw new IllegalStateException("email is null");}

        return a;
    }


    /**
   * * MISC API
   * *
   */

  public Info info() throws DockerException {
    WebResource webResource = client.resource(restEndpointUrl + "/info");

    try {
      LOGGER.trace("GET: {}", webResource);
      return webResource.accept(MediaType.APPLICATION_JSON).get(Info.class);
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error.", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }


  public Version version() throws DockerException {
    WebResource webResource = client.resource(restEndpointUrl + "/version");

    try {
      LOGGER.trace("GET: {}", webResource);
      return webResource.accept(MediaType.APPLICATION_JSON).get(Version.class);
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error.", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }


  /**
   * * IMAGE API
   * *
   */

  public ClientResponse pull(String repository) throws DockerException {
    return this.pull(repository, null, null);
  }

  public ClientResponse pull(String repository, String tag) throws DockerException {
    return this.pull(repository, tag, null);
  }

  public ClientResponse pull(String repository, String tag, String registry) throws DockerException {
    Preconditions.checkNotNull(repository, "Repository was not specified");

    if (StringUtils.countMatches(repository, ":") == 1) {
      String repositoryTag[] = StringUtils.split(repository, ':');
      repository = repositoryTag[0];
      tag = repositoryTag[1];

    }

    MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    params.add("tag", tag);
    params.add("fromImage", repository);
    params.add("registry", registry);

    WebResource webResource = client.resource(restEndpointUrl + "/images/create").queryParams(params);

    try {
      LOGGER.trace("POST: {}", webResource);
      return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class);
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error.", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }
 
 
 

  /**
   * @return The output slurped into a string.
   */
  public static String asString(ClientResponse response) throws IOException {

    StringWriter out = new StringWriter();
    try {
      LineIterator itr = IOUtils.lineIterator(
          response.getEntityInputStream(), "UTF-8");
      while (itr.hasNext()) {
        String line = itr.next();
        out.write(line + (itr.hasNext() ? "\n" : ""));
      }
    } finally {
      closeQuietly(response.getEntityInputStream());
    }
    return out.toString();
  }

  /**
   * Push the latest image to the repository.
   *
   * @param name The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null.
   */
  public ClientResponse push(final String name) throws DockerException {
    if (name == null) {
      throw new IllegalArgumentException("name is null");
    }
    try {
      final String registryAuth = registryAuth();
      return client.resource(restEndpointUrl + "/images/" + name(name) + "/push")
          .header("X-Registry-Auth", registryAuth)
          .accept(MediaType.APPLICATION_JSON)
          .post(ClientResponse.class);
    } catch (UniformInterfaceException e) {
      throw new DockerException(e);
    }
  }

  private String name(String name) {
    return name.contains("/") ? name : authConfig.getUsername();
  }

  /**
   * Create an image by importing the given stream of a tar file.
   *
   * @param repository  the repository to import to
   * @param tag         any tag for this image
   * @param imageStream the InputStream of the tar file
   * @return an {@link ImageCreateResponse} containing the id of the imported image
   * @throws DockerException if the import fails for some reason.
   */
  public ImageCreateResponse importImage(String repository, String tag, InputStream imageStream) throws DockerException {
    Preconditions.checkNotNull(repository, "Repository was not specified");
    Preconditions.checkNotNull(imageStream, "imageStream was not provided");

    MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    params.add("repo", repository);
    params.add("tag", tag);
    params.add("fromSrc", "-");

    WebResource webResource = client.resource(restEndpointUrl + "/images/create").queryParams(params);

    try {
      LOGGER.trace("POST: {}", webResource);
      return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ImageCreateResponse.class, imageStream);

    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error.", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }

  public List<SearchItem> search(String search) throws DockerException {
    WebResource webResource = client.resource(restEndpointUrl + "/images/search").queryParam("term", search);
    try {
      return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<List<SearchItem>>() {
      });
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error.", exception);
      } else {
        throw new DockerException(exception);
      }
    }

  }

  /**
   * Remove an image, deleting any tags it might have.
   */
  public void removeImage(String imageId) throws DockerException {
    Preconditions.checkState(!StringUtils.isEmpty(imageId), "Image ID can't be empty");

    try {
      WebResource webResource = client.resource(restEndpointUrl + "/images/" + imageId)
          .queryParam("force", "true");
      LOGGER.trace("DELETE: {}", webResource);
      webResource.delete();
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 204) {
        //no error
        LOGGER.trace("Successfully removed image " + imageId);
      } else if (exception.getResponse().getStatus() == 404) {
        LOGGER.warn("{} no such image", imageId);
      } else if (exception.getResponse().getStatus() == 409) {
        throw new DockerException("Conflict");
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error.", exception);
      } else {
        throw new DockerException(exception);
      }
    }

  }

  public void removeImages(List<String> images) throws DockerException {
    Preconditions.checkNotNull(images, "List of images can't be null");

    for (String imageId : images) {
      removeImage(imageId);
    }
  }

  public String getVizImages() throws DockerException {
    WebResource webResource = client.resource(restEndpointUrl + "/images/viz");

    try {
      LOGGER.trace("GET: {}", webResource);
      String response = webResource.get(String.class);
      LOGGER.trace("Response: {}", response);

      return response;
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 400) {
        throw new DockerException("bad parameter");
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }


  public List<Image> getImages() throws DockerException {
    return this.getImages(null, false);
  }

  public List<Image> getImages(boolean allContainers) throws DockerException {
    return this.getImages(null, allContainers);
  }

  public List<Image> getImages(String name) throws DockerException {
    return this.getImages(name, false);
  }

  public List<Image> getImages(String name, boolean allImages) throws DockerException {

    MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    params.add("filter", name);
    params.add("all", allImages ? "1" : "0");

    WebResource webResource = client.resource(restEndpointUrl + "/images/json").queryParams(params);

    try {
      LOGGER.trace("GET: {}", webResource);
      List<Image> images = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<List<Image>>() {
      });
      LOGGER.trace("Response: {}", images);
      return images;
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 400) {
        throw new DockerException("bad parameter");
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException();
      }
    }

  }

  public ImageInspectResponse inspectImage(String imageId) throws DockerException, NotFoundException {

    WebResource webResource = client.resource(restEndpointUrl + String.format("/images/%s/json", imageId));

    try {
      LOGGER.trace("GET: {}", webResource);
      return webResource.accept(MediaType.APPLICATION_JSON).get(ImageInspectResponse.class);
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        throw new NotFoundException(String.format("No such image %s", imageId));
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }

  /**
   * * CONTAINER API
   * *
   */

  public List<Container> listContainers(boolean allContainers) {
    return this.listContainers(allContainers, false, -1, false, null, null);
  }

  public List<Container> listContainers(boolean allContainers, boolean latest) {
    return this.listContainers(allContainers, latest, -1, false, null, null);
  }

  public List<Container> listContainers(boolean allContainers, boolean latest, int limit) {
    return this.listContainers(allContainers, latest, limit, false, null, null);
  }

  public List<Container> listContainers(boolean allContainers, boolean latest, int limit, boolean showSize) {
    return this.listContainers(allContainers, latest, limit, showSize, null, null);
  }

  public List<Container> listContainers(boolean allContainers, boolean latest, int limit, boolean showSize, String since) {
    return this.listContainers(allContainers, latest, limit, false, since, null);
  }

  public List<Container> listContainers(boolean allContainers, boolean latest, int limit, boolean showSize, String since, String before) {

    MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    params.add("limit", latest ? "1" : String.valueOf(limit));
    params.add("all", allContainers ? "1" : "0");
    params.add("since", since);
    params.add("before", before);
    params.add("size", showSize ? "1" : "0");

    WebResource webResource = client.resource(restEndpointUrl + "/containers/json").queryParams(params);
    LOGGER.trace("GET: {}", webResource);
    List<Container> containers = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<List<Container>>() {
    });
    LOGGER.trace("Response: {}", containers);

    return containers;
  }

  public ContainerCreateResponse createContainer(ContainerConfig config) throws DockerException {
    return createContainer(config, null);
  }

  public ContainerCreateResponse createContainer(ContainerConfig config, String name) throws DockerException, NotFoundException {

    MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    if (name != null) {
      params.add("name", name);
    }
    WebResource webResource = client.resource(restEndpointUrl + "/containers/create").queryParams(params);

    try {
      LOGGER.trace("POST: {} ", webResource);
      return webResource.accept(MediaType.APPLICATION_JSON)
          .type(MediaType.APPLICATION_JSON)
          .post(ContainerCreateResponse.class, config);
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        throw new NotFoundException(String.format("%s is an unrecognized image. Please pull the image first.", config.getImage()));
      } else if (exception.getResponse().getStatus() == 406) {
        throw new DockerException("impossible to attach (container not running)");
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }

  }

  public void startContainer(String containerId) throws DockerException {
    this.startContainer(containerId, null);
  }

  public void startContainer(String containerId, HostConfig hostConfig) throws DockerException, NotFoundException {

    WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId));

    try {
      LOGGER.trace("POST: {}", webResource);
      Builder builder = webResource.accept(MediaType.TEXT_PLAIN);
      if (hostConfig != null) {
        builder.type(MediaType.APPLICATION_JSON).post(hostConfig);
      } else {
        builder.post((HostConfig) null);
      }
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        throw new NotFoundException(String.format("No such container %s", containerId));
      } else if (exception.getResponse().getStatus() == 204) {
        //no error
        LOGGER.trace("Successfully started container {}", containerId);
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }

  public ContainerInspectResponse inspectContainer(String containerId) throws DockerException, NotFoundException {

    WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/json", containerId));

    try {
      LOGGER.trace("GET: {}", webResource);
      return webResource.accept(MediaType.APPLICATION_JSON).get(ContainerInspectResponse.class);
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        throw new NotFoundException(String.format("No such container %s", containerId));
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }


  public void removeContainer(String container) throws DockerException {
    this.removeContainer(container, false);
  }

  public void removeContainer(String containerId, boolean removeVolumes) throws DockerException {
    Preconditions.checkState(!StringUtils.isEmpty(containerId), "Container ID can't be empty");

    WebResource webResource = client.resource(restEndpointUrl + "/containers/" + containerId).queryParam("v", removeVolumes ? "1" : "0");

    try {
      LOGGER.trace("DELETE: {}", webResource);
      String response = webResource.accept(MediaType.APPLICATION_JSON).delete(String.class);
      LOGGER.trace("Response: {}", response);
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 204) {
        //no error
        LOGGER.trace("Successfully removed container " + containerId);
      } else if (exception.getResponse().getStatus() == 400) {
        throw new DockerException("bad parameter");
      } else if (exception.getResponse().getStatus() == 404) {
        // should really throw a NotFoundException instead of silently ignoring the problem
        LOGGER.warn(String.format("%s is an unrecognized container.", containerId));
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }


  public void removeContainers(List<String> containers, boolean removeVolumes) throws DockerException {
    Preconditions.checkNotNull(containers, "List of containers can't be null");

    for (String containerId : containers) {
      removeContainer(containerId, removeVolumes);
    }
  }

  public int waitContainer(String containerId) throws DockerException, NotFoundException {
    WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/wait", containerId));

    try {
      LOGGER.trace("POST: {}", webResource);
      ObjectNode ObjectNode = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(ObjectNode.class);
            return ObjectNode.get("StatusCode").asInt();
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        throw new NotFoundException(String.format("No such container %s", containerId));
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    } catch (Exception e) {
      throw new DockerException(e);
    }
  }


  public ClientResponse logContainer(String containerId) throws DockerException {
    return logContainer(containerId, false);
  }

  public ClientResponse logContainerStream(String containerId) throws DockerException {
    return logContainer(containerId, true);
  }

  private ClientResponse logContainer(String containerId, boolean stream) throws DockerException, NotFoundException {
    MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    params.add("logs", "1");
    params.add("stdout", "1");
    params.add("stderr", "1");
    if (stream) {
      params.add("stream", "1"); // this parameter keeps stream open indefinitely
    }

    WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/attach", containerId))
        .queryParams(params);

    try {
      LOGGER.trace("POST: {}", webResource);
      return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class, params);
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 400) {
        throw new DockerException("bad parameter");
      } else if (exception.getResponse().getStatus() == 404) {
        throw new NotFoundException(String.format("No such container %s", containerId));
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }

  public ClientResponse copyFile(String containerId, String resource) throws DockerException {
    CopyConfig copyConfig = new CopyConfig();
    copyConfig.setResource(resource);

    WebResource webResource =
        client.resource(restEndpointUrl + String.format("/containers/%s/copy", containerId));

    try {
      LOGGER.trace("POST: " + webResource.toString());
      WebResource.Builder builder =
          webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).type("application/json");

      return builder.post(ClientResponse.class, copyConfig.toString());
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 400) {
        throw new DockerException("bad parameter");
      } else if (exception.getResponse().getStatus() == 404) {
        throw new DockerException(String.format("No such container %s", containerId));
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }

  public List<ChangeLog> containerDiff(String containerId) throws DockerException, NotFoundException {

    WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId));

    try {
      LOGGER.trace("GET: {}", webResource);
      return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<List<ChangeLog>>() {
      });
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        throw new NotFoundException(String.format("No such container %s", containerId));
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }


  public void stopContainer(String containerId) throws DockerException {
    this.stopContainer(containerId, 10);
  }

  public void stopContainer(String containerId, int timeout) throws DockerException {

    WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/stop", containerId))
        .queryParam("t", String.valueOf(timeout));


    try {
      LOGGER.trace("POST: {}", webResource);
      webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post();
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        LOGGER.warn("No such container {}", containerId);
      } else if (exception.getResponse().getStatus() == 204) {
        //no error
        LOGGER.trace("Successfully stopped container {}", containerId);
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }

  public void kill(String containerId) throws DockerException {
    WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/kill", containerId));

    try {
      LOGGER.trace("POST: {}", webResource);
      webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post();
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        LOGGER.warn("No such container {}", containerId);
      } else if (exception.getResponse().getStatus() == 204) {
        //no error
        LOGGER.trace("Successfully killed container {}", containerId);
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }

  public void restart(String containerId, int timeout) throws DockerException, NotFoundException {
    WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/restart", containerId));

    try {
      LOGGER.trace("POST: {}", webResource);
      webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post();
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        throw new NotFoundException(String.format("No such container %s", containerId));
      } else if (exception.getResponse().getStatus() == 204) {
        //no error
        LOGGER.trace("Successfully restarted container {}", containerId);
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    }
  }

  public String commit(CommitConfig commitConfig) throws DockerException, NotFoundException {
    Preconditions.checkNotNull(commitConfig.getContainer(), "Container ID was not specified");

    MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    params.add("container", commitConfig.getContainer());
    params.add("repo", commitConfig.getRepo());
    params.add("tag", commitConfig.getTag());
    params.add("m", commitConfig.getMessage());
    params.add("author", commitConfig.getAuthor());
    params.add("run", commitConfig.getRun());

    WebResource webResource = client.resource(restEndpointUrl + "/commit").queryParams(params);

    try {
      LOGGER.trace("POST: {}", webResource);
      ObjectNode ObjectNode = webResource.accept("application/vnd.docker.raw-stream").post(ObjectNode.class, params);
            return ObjectNode.get("Id").asText();
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 404) {
        throw new NotFoundException(String.format("No such container %s", commitConfig.getContainer()));
      } else if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    } catch (Exception e) {
      throw new DockerException(e);
    }
  }


  public ClientResponse build(File dockerFolder) throws DockerException {
    return this.build(dockerFolder, null);
  }

  public ClientResponse build(File dockerFolder, String tag) throws DockerException {
    return this.build(dockerFolder, tag, false);
  }
 
  private static boolean isFileResource(String resource)  {
        URI uri;
    try {
      uri = new URI(resource);
    } catch (URISyntaxException e) {
      throw new RuntimeException(e);
    }
        return uri.getScheme() == null || "file".equals(uri.getScheme());
    }

  public ClientResponse build(File dockerFolder, String tag, boolean noCache) throws DockerException {
    return build(dockerFolder, tag, noCache ? EnumSet.of(BuildFlag.NO_CACHE) : EnumSet.noneOf(BuildFlag.class));
  }

  public ClientResponse build(File dockerFolder, String tag, Set <BuildFlag> flags) throws DockerException {
    Preconditions.checkNotNull(dockerFolder, "Folder is null");
    Preconditions.checkArgument(dockerFolder.exists(), "Folder %s doesn't exist", dockerFolder);
    Preconditions.checkNotNull(flags, "flags is null");
    Preconditions.checkState(new File(dockerFolder, "Dockerfile").exists(), "Dockerfile doesn't exist in " + dockerFolder);

    //We need to use Jersey HttpClient here, since ApacheHttpClient4 will not add boundary filed to
    //Content-Type: multipart/form-data; boundary=Boundary_1_372491238_1372806136625

    MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    params.add("t", tag);
    for (BuildFlag flag : flags) {
      switch (flag) {
        case NO_CACHE:
          params.add("nocache", "true");
          break;
        case REMOVE_INTERMEDIATE_IMAGES:
          params.add("rm", "true");
          break;
        default:
          throw new IllegalArgumentException("unexpected flag " + flag);
      }
    }

    // ARCHIVE TAR
    String archiveNameWithOutExtension = UUID.randomUUID().toString();

    File dockerFolderTar = null;

    try {
      File dockerFile = new File(dockerFolder, "Dockerfile");
      List<String> dockerFileContent = FileUtils.readLines(dockerFile);

      if (dockerFileContent.size() <= 0) {
        throw new DockerException(String.format("Dockerfile %s is empty", dockerFile));
      }

      List<File> filesToAdd = new ArrayList<File>();
      filesToAdd.add(dockerFile);

      for (String cmd : dockerFileContent) {
        if (StringUtils.startsWithIgnoreCase(cmd.trim(), "ADD")) {
          String addArgs[] = StringUtils.split(cmd, " \t");
          if (addArgs.length != 3) {
            throw new DockerException(String.format("Wrong format on line [%s]", cmd));
          }

          String resource = addArgs[1];
         
          if(isFileResource(resource)) {
            File src = new File(resource);
            if (!src.isAbsolute()) {
              src = new File(dockerFolder, resource).getCanonicalFile();
            } else {
              throw new DockerException(String.format("Source file %s must be relative to %s", src, dockerFolder));
            }

            if (!src.exists()) {
              throw new DockerException(String.format("Source file %s doesn't exist", src));
            }
            if (src.isDirectory()) {
              filesToAdd.addAll(FileUtils.listFiles(src, null, true));
            } else {
              filesToAdd.add(src);
            }
          }
        }
      }

      dockerFolderTar = CompressArchiveUtil.archiveTARFiles(dockerFolder, filesToAdd, archiveNameWithOutExtension);

    } catch (IOException ex) {
      FileUtils.deleteQuietly(dockerFolderTar);
      throw new DockerException("Error occurred while preparing Docker context folder.", ex);
    }

    WebResource webResource = client.resource(restEndpointUrl + "/build").queryParams(params);

    try {
      LOGGER.trace("POST: {}", webResource);
      return webResource
          .type("application/tar")
          .accept(MediaType.TEXT_PLAIN)
          .post(ClientResponse.class, FileUtils.openInputStream(dockerFolderTar));
    } catch (UniformInterfaceException exception) {
      if (exception.getResponse().getStatus() == 500) {
        throw new DockerException("Server error", exception);
      } else {
        throw new DockerException(exception);
      }
    } catch (IOException e) {
      throw new DockerException(e);
    } finally {
      FileUtils.deleteQuietly(dockerFolderTar);
    }
  }
}
TOP

Related Classes of com.kpelykh.docker.client.DockerClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.