au.net.causal.maven.plugins.boxdb.db.DockerHacks Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of boxdb-maven-plugin Show documentation
Show all versions of boxdb-maven-plugin Show documentation
Maven plugin to start databases using Docker and VMs
package au.net.causal.maven.plugins.boxdb.db;
import com.google.common.collect.ImmutableSet;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
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.ApacheHttpClientDelegate.HttpBodyAndStatus;
import io.fabric8.maven.docker.access.hc.DockerAccessWithHcClient;
import io.fabric8.maven.docker.util.JsonFactory;
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.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
/**
* Terrible hacks to get additional functionality with the existing docker client from the docker maven plugin.
*/
public class DockerHacks
{
/**
* Retrieves details about a local Docker image.
*
* @param docker the docker client.
* @param imageName the name of the image to get details of.
*
* @return details of the image, or null if the image does not exist.
*
* @throws DockerAccessException if an error occurs.
*/
public ImageDetails inspectImage(DockerAccess docker, String imageName)
throws DockerAccessException
{
DockerAccessWithHcClient client = (DockerAccessWithHcClient)docker;
try
{
Method inspectImageMethod = DockerAccessWithHcClient.class.getDeclaredMethod("inspectImage", String.class);
inspectImageMethod.setAccessible(true);
HttpBodyAndStatus response = (HttpBodyAndStatus)inspectImageMethod.invoke(client, imageName);
if (response.getStatusCode() == HTTP_NOT_FOUND)
return null;
JsonObject imageDetails = JsonFactory.newJsonObject(response.getBody());
JsonPrimitive fullImageIdPrim = imageDetails.getAsJsonPrimitive("Id");
if (fullImageIdPrim == null)
throw new DockerAccessException("Id property not found in image");
String fullImageId = fullImageIdPrim.getAsString();
//Also save the digests, might not have any though
JsonArray repoDigestsJson = imageDetails.getAsJsonArray("RepoDigests");
Set repoDigests;
if (repoDigestsJson == null)
repoDigests = ImmutableSet.of();
else
{
ImmutableSet.Builder rdb = ImmutableSet.builder();
for (JsonElement repoDigest : repoDigestsJson)
{
rdb.add(repoDigest.getAsString());
}
repoDigests = rdb.build();
}
return new ImageDetails(fullImageId, repoDigests);
}
catch (ReflectiveOperationException e)
{
throw new DockerAccessException(e, e.getMessage());
}
}
/**
* 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