All Downloads are FREE. Search and download functionalities are using the official Maven repository.

au.net.causal.maven.plugins.boxdb.db.DockerHacks Maven / Gradle / Ivy

There is a newer version: 3.3
Show newest version
package au.net.causal.maven.plugins.boxdb.db;

import io.fabric8.maven.docker.access.DockerAccess;
import io.fabric8.maven.docker.access.DockerAccessException;
import io.fabric8.maven.docker.access.UrlBuilder;
import io.fabric8.maven.docker.access.hc.ApacheHttpClientDelegate;
import io.fabric8.maven.docker.access.hc.DockerAccessWithHcClient;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * Terrible hacks to get additional functionality with the existing docker client from the docker maven plugin.
 */
public class DockerHacks 
{
    /**
     * The opposite of {@link DockerAccess#copyArchive(String, File, String)}, this method creates an archive of all
     * files in a directory in the docker container.  File names in the generated TAR archive will be relative to the
     * target path.
     * 
     * @param docker the docker client.
     * @param containerId the ID of the container to access.  Can be running or stopped.
     * @param archive the TAR archive file to save to.  
     * @param targetPath the absolute path in the container to read from.  All files under this directory are archived.
     *                   
     * @throws DockerAccessException if an error occurs.
     */
    public void copyArchiveFromDocker(DockerAccess docker, String containerId, Path archive, String targetPath) 
    throws DockerAccessException 
    {
        DockerAccessWithHcClient client = (DockerAccessWithHcClient)docker;

        try 
        {
            //We can reuse the URLBuilder for the other copyArchive because the only difference
            //is the HTTP method (GET vs POST)
            Field urlBuilderField = DockerAccessWithHcClient.class.getDeclaredField("urlBuilder");
            urlBuilderField.setAccessible(true);
            UrlBuilder urlBuilder = (UrlBuilder)urlBuilderField.get(client);

            Field delegateField = DockerAccessWithHcClient.class.getDeclaredField("delegate");
            delegateField.setAccessible(true);
            ApacheHttpClientDelegate delegate = (ApacheHttpClientDelegate)delegateField.get(client);

            String url = urlBuilder.copyArchive(containerId, targetPath);
            delegate.get(url, new ResponseHandler() 
            {
                @Override
                public Object handleResponse(HttpResponse response) throws ClientProtocolException, IOException 
                {
                    try (OutputStream os = Files.newOutputStream(archive)) 
                    {
                        response.getEntity().writeTo(os);
                    }
                    return null;
                }
            }, HttpURLConnection.HTTP_OK);
        } 
        catch (ReflectiveOperationException | IOException e) 
        {
            throw new DockerAccessException(e, e.getMessage());
        }
    }
}