diff --git a/README.md b/README.md index 51ac433c9..6060cb978 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,13 @@ Developer forum for [docker-java](https://groups.google.com/forum/?hl=de#!forum/ * Maven 3.0.5 * Docker daemon running -The Maven build includes integration tests which are using a localhost instance of Docker and require manual setup. Make sure you have a local Docker daemon running and then provide your https://registry.hub.docker.com/account/login/ information via system properties: +If you need SSL, then you'll need to put your `*.pem` file into `~/.docker/`, if you're using boot2docker, do this: + + $ ln -s /Users/alex.collins/.boot2docker/certs/boot2docker-vm .docker - $ mvn clean install -Ddocker.io.username=... -Ddocker.io.password=... -Ddocker.io.email=... +Build and run integration tests as follows: -_If your Docker server is remote, add its URL like this: `-Ddocker.io.url=https://...:2376`._ + $ mvn clean install If you do not have access to a Docker server or just want to execute the build quickly, you can run the build without the integration tests: @@ -79,9 +81,10 @@ There are a couple of configuration items, all of which have sensible defaults: * `url` The Docker URL, e.g. `https://localhost:2376`. * `version` The API version, e.g. `1.15`. -* `username` Your repository username (required to push containers). -* `password` Your repository password. -* `email` Your repository email. +* `username` Your registry username (required to push containers). +* `password` Your registry password. +* `email` Your registry email. +* `serverAddress` Your registry's address. * `dockerCertPath` Path to the docker certs. There are three ways to configure, in descending order of precedence: @@ -95,6 +98,7 @@ In your application, e.g. .withUsername("dockeruser") .withPassword("ilovedocker") .withEmail("dockeruser@github.com") + .withServerAddress("https://index.docker.io/v1/") .withDockerCertPath("/home/user/.docker") .build(); DockerClient docker = DockerClientBuilder.getInstance(config).build(); @@ -106,6 +110,7 @@ In your application, e.g. docker.io.username=dockeruser docker.io.password=ilovedocker docker.io.email=dockeruser@github.com + docker.io.serverAddress=https://index.docker.io/v1/ docker.io.dockerCertPath=/home/user/.docker diff --git a/src/main/java/com/github/dockerjava/api/command/AuthCmd.java b/src/main/java/com/github/dockerjava/api/command/AuthCmd.java index f71a132be..3c5922583 100644 --- a/src/main/java/com/github/dockerjava/api/command/AuthCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/AuthCmd.java @@ -2,22 +2,28 @@ import com.github.dockerjava.api.UnauthorizedException; import com.github.dockerjava.api.model.AuthConfig; +import com.github.dockerjava.api.model.AuthResponse; /** * * Authenticate with the server, useful for checking authentication. * */ -public interface AuthCmd extends DockerCmd { +public interface AuthCmd extends DockerCmd { public AuthConfig getAuthConfig(); public AuthCmd withAuthConfig(AuthConfig authConfig); - + + /** + * @return The status. Based on it's value you may mean you need to authorise your account, e.g.: + * "Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it." + * @throws UnauthorizedException If you're not authorised (e.g. bad password). + */ @Override - public Void exec() throws UnauthorizedException; + public AuthResponse exec() throws UnauthorizedException; - public static interface Exec extends DockerCmdExec { + public static interface Exec extends DockerCmdExec { } } \ No newline at end of file diff --git a/src/main/java/com/github/dockerjava/api/command/PullImageCmd.java b/src/main/java/com/github/dockerjava/api/command/PullImageCmd.java index f938542da..27d5b978a 100644 --- a/src/main/java/com/github/dockerjava/api/command/PullImageCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/PullImageCmd.java @@ -1,5 +1,7 @@ package com.github.dockerjava.api.command; +import com.github.dockerjava.api.model.AuthConfig; + import java.io.InputStream; /** @@ -15,13 +17,17 @@ public interface PullImageCmd extends DockerCmd{ public String getRegistry(); - public PullImageCmd withRepository(String repository); + public AuthConfig getAuthConfig(); + + public PullImageCmd withRepository(String repository); public PullImageCmd withTag(String tag); public PullImageCmd withRegistry(String registry); - - public static interface Exec extends DockerCmdExec { + + public PullImageCmd withAuthConfig(AuthConfig authConfig); + + public static interface Exec extends DockerCmdExec { } } \ No newline at end of file diff --git a/src/main/java/com/github/dockerjava/api/model/AuthConfig.java b/src/main/java/com/github/dockerjava/api/model/AuthConfig.java index 7212d8234..d7f0deab3 100644 --- a/src/main/java/com/github/dockerjava/api/model/AuthConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/AuthConfig.java @@ -3,8 +3,15 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class AuthConfig { - - @JsonProperty + + /** + * For backwards compatibility. Make sure you update the properties if you change this. + * + * @see /docker.io.properties + */ + public static final String DEFAULT_SERVER_ADDRESS = "https://index.docker.io/v1/"; + + @JsonProperty private String username; @JsonProperty @@ -14,7 +21,7 @@ public class AuthConfig { private String email; @JsonProperty("serveraddress") - private String serverAddress = "https://index.docker.io/v1/"; + private String serverAddress = DEFAULT_SERVER_ADDRESS; public String getUsername() { return username; diff --git a/src/main/java/com/github/dockerjava/api/model/AuthResponse.java b/src/main/java/com/github/dockerjava/api/model/AuthResponse.java new file mode 100644 index 000000000..cb5d9df80 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/AuthResponse.java @@ -0,0 +1,12 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AuthResponse { + @JsonProperty("Status") + private String status; + + public String getStatus() { + return status; + } +} diff --git a/src/main/java/com/github/dockerjava/api/model/ErrorDetail.java b/src/main/java/com/github/dockerjava/api/model/ErrorDetail.java new file mode 100644 index 000000000..8abffe6c4 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/ErrorDetail.java @@ -0,0 +1,12 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ErrorDetail { + @JsonProperty + private String message; + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/com/github/dockerjava/api/model/ErrorResponse.java b/src/main/java/com/github/dockerjava/api/model/ErrorResponse.java new file mode 100644 index 000000000..87d9b0d7f --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/ErrorResponse.java @@ -0,0 +1,18 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ErrorResponse { + @JsonProperty + private ErrorDetail errorDetail; + @JsonProperty + private String error; + + public ErrorDetail getErrorDetail() { + return errorDetail; + } + + public String getError() { + return error; + } +} diff --git a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java index c12585a54..9f1694b5e 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java @@ -18,6 +18,7 @@ public class DockerClientConfig { private static final String DOCKER_IO_USERNAME_PROPERTY = "docker.io.username"; private static final String DOCKER_IO_PASSWORD_PROPERTY = "docker.io.password"; private static final String DOCKER_IO_EMAIL_PROPERTY = "docker.io.email"; + private static final String DOCKER_IO_SERVER_ADDRESS_PROPERTY = "docker.io.serverAddress"; private static final String DOCKER_IO_READ_TIMEOUT_PROPERTY = "docker.io.readTimeout"; // this is really confusing, as there are two ways to spell it private static final String DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY = "docker.io.enableLoggingFilter"; @@ -31,22 +32,24 @@ public class DockerClientConfig { .put("DOCKER_USERNAME", DOCKER_IO_USERNAME_PROPERTY) .put("DOCKER_PASSWORD", DOCKER_IO_PASSWORD_PROPERTY) .put("DOCKER_EMAIL", DOCKER_IO_EMAIL_PROPERTY) + .put("DOCKER_SERVER_ADDRESS", DOCKER_IO_SERVER_ADDRESS_PROPERTY) .put("DOCKER_READ_TIMEOUT", DOCKER_IO_READ_TIMEOUT_PROPERTY) .put("DOCKER_LOGGING_FILTER_ENABLED", DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY) .put(DOCKER_CERT_PATH_PROPERTY, DOCKER_IO_DOCKER_CERT_PATH_PROPERTY) .build(); private static final String DOCKER_IO_PROPERTIES_PROPERTY = "docker.io.properties"; private final URI uri; - private final String version, username, password, email, dockerCertPath; + private final String version, username, password, email, serverAddress, dockerCertPath; private final Integer readTimeout; private final boolean loggingFilterEnabled; - DockerClientConfig(URI uri, String version, String username, String password, String email, String dockerCertPath, Integer readTimeout, boolean loggingFilterEnabled) { + DockerClientConfig(URI uri, String version, String username, String password, String email, String serverAddress, String dockerCertPath, Integer readTimeout, boolean loggingFilterEnabled) { this.uri = uri; this.version = version; this.username = username; this.password = password; this.email = email; + this.serverAddress = serverAddress; this.dockerCertPath = dockerCertPath; this.readTimeout = readTimeout; this.loggingFilterEnabled = loggingFilterEnabled; @@ -146,6 +149,7 @@ private static Properties overrideDockerPropertiesWithSystemProperties(Propertie DOCKER_IO_USERNAME_PROPERTY, DOCKER_IO_PASSWORD_PROPERTY, DOCKER_IO_EMAIL_PROPERTY, + DOCKER_IO_SERVER_ADDRESS_PROPERTY, DOCKER_IO_READ_TIMEOUT_PROPERTY, DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY, DOCKER_IO_DOCKER_CERT_PATH_PROPERTY, @@ -192,6 +196,10 @@ public String getEmail() { return email; } + public String getServerAddress() { + return serverAddress; + } + public Integer getReadTimeout() { return readTimeout; } @@ -217,6 +225,8 @@ public boolean equals(Object o) { if (email != null ? !email.equals(that.email) : that.email != null) return false; if (password != null ? !password.equals(that.password) : that.password != null) return false; if (readTimeout != null ? !readTimeout.equals(that.readTimeout) : that.readTimeout != null) return false; + if (serverAddress != null ? !serverAddress.equals(that.serverAddress) : that.serverAddress != null) + return false; if (uri != null ? !uri.equals(that.uri) : that.uri != null) return false; if (username != null ? !username.equals(that.username) : that.username != null) return false; if (version != null ? !version.equals(that.version) : that.version != null) return false; @@ -231,6 +241,7 @@ public int hashCode() { result = 31 * result + (username != null ? username.hashCode() : 0); result = 31 * result + (password != null ? password.hashCode() : 0); result = 31 * result + (email != null ? email.hashCode() : 0); + result = 31 * result + (serverAddress != null ? serverAddress.hashCode() : 0); result = 31 * result + (dockerCertPath != null ? dockerCertPath.hashCode() : 0); result = 31 * result + (readTimeout != null ? readTimeout.hashCode() : 0); result = 31 * result + (loggingFilterEnabled ? 1 : 0); @@ -245,6 +256,7 @@ public String toString() { ", username='" + username + '\'' + ", password='" + password + '\'' + ", email='" + email + '\'' + + ", serverAddress='" + serverAddress + '\'' + ", dockerCertPath='" + dockerCertPath + '\'' + ", readTimeout=" + readTimeout + ", loggingFilterEnabled=" + loggingFilterEnabled + @@ -253,7 +265,7 @@ public String toString() { public static class DockerClientConfigBuilder { private URI uri; - private String version, username, password, email, dockerCertPath; + private String version, username, password, email, serverAddress, dockerCertPath; private Integer readTimeout; private boolean loggingFilterEnabled; @@ -269,6 +281,7 @@ public DockerClientConfigBuilder withProperties(Properties p) { .withUsername(p.getProperty(DOCKER_IO_USERNAME_PROPERTY)) .withPassword(p.getProperty(DOCKER_IO_PASSWORD_PROPERTY)) .withEmail(p.getProperty(DOCKER_IO_EMAIL_PROPERTY)) + .withServerAddress(p.getProperty(DOCKER_IO_SERVER_ADDRESS_PROPERTY)) .withReadTimeout(Integer.valueOf(p.getProperty(DOCKER_IO_READ_TIMEOUT_PROPERTY, "0"))) .withLoggingFilter(Boolean.valueOf(p.getProperty(DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY, "true"))) .withDockerCertPath(p.getProperty(DOCKER_IO_DOCKER_CERT_PATH_PROPERTY)); @@ -300,6 +313,11 @@ public final DockerClientConfigBuilder withEmail(String email) { return this; } + public DockerClientConfigBuilder withServerAddress(String serverAddress) { + this.serverAddress = serverAddress; + return this; + } + public final DockerClientConfigBuilder withReadTimeout(Integer readTimeout) { this.readTimeout = readTimeout; return this; @@ -322,6 +340,7 @@ public DockerClientConfig build() { username, password, email, + serverAddress, dockerCertPath, readTimeout, loggingFilterEnabled diff --git a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java index 5dfb4c13f..2630d26d4 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java @@ -71,14 +71,14 @@ private DockerCmdExecFactory getDockerCmdExecFactory() { public AuthConfig authConfig() { checkNotNull(dockerClientConfig.getUsername(), "Configured username is null."); - checkNotNull(dockerClientConfig.getPassword(), "Configured password is null."); - checkNotNull(dockerClientConfig.getEmail(), "Configured email is null."); + checkNotNull(dockerClientConfig.getServerAddress(), "Configured serverAddress is null."); AuthConfig authConfig = new AuthConfig(); authConfig.setUsername(dockerClientConfig.getUsername()); authConfig.setPassword(dockerClientConfig.getPassword()); authConfig.setEmail(dockerClientConfig.getEmail()); - // TODO Make the registry address configurable + authConfig.setServerAddress(dockerClientConfig.getServerAddress()); + return authConfig; } diff --git a/src/main/java/com/github/dockerjava/core/command/AuthCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/AuthCmdImpl.java index 259333e5b..0da0da3c3 100644 --- a/src/main/java/com/github/dockerjava/core/command/AuthCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/AuthCmdImpl.java @@ -3,24 +3,25 @@ import com.github.dockerjava.api.UnauthorizedException; import com.github.dockerjava.api.command.AuthCmd; import com.github.dockerjava.api.model.AuthConfig; +import com.github.dockerjava.api.model.AuthResponse; /** * * Authenticate with the server, useful for checking authentication. * */ -public class AuthCmdImpl extends AbstrAuthCfgDockerCmd implements AuthCmd { +public class AuthCmdImpl extends AbstrAuthCfgDockerCmd implements AuthCmd { public AuthCmdImpl(AuthCmd.Exec exec, AuthConfig authConfig) { super(exec); withAuthConfig(authConfig); } - + @Override - public Void exec() throws UnauthorizedException { + public AuthResponse exec() throws UnauthorizedException { return super.exec(); } - + @Override public String toString() { return "authenticate using " + this.getAuthConfig(); diff --git a/src/main/java/com/github/dockerjava/core/command/PullImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/PullImageCmdImpl.java index b0ec02514..ed045878d 100644 --- a/src/main/java/com/github/dockerjava/core/command/PullImageCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/PullImageCmdImpl.java @@ -1,11 +1,11 @@ package com.github.dockerjava.core.command; -import java.io.InputStream; - import com.github.dockerjava.api.command.PullImageCmd; - +import com.github.dockerjava.api.model.AuthConfig; import com.google.common.base.Preconditions; +import java.io.InputStream; + /** * * Pull image from repository. @@ -13,7 +13,8 @@ */ public class PullImageCmdImpl extends AbstrDockerCmd implements PullImageCmd { - private String repository, tag, registry; + private String repository, tag, registry; + private AuthConfig authConfig; public PullImageCmdImpl(PullImageCmd.Exec exec, String repository) { super(exec); @@ -35,6 +36,10 @@ public String getRegistry() { return registry; } + public AuthConfig getAuthConfig() { + return authConfig; + } + @Override public PullImageCmd withRepository(String repository) { Preconditions.checkNotNull(repository, "repository was not specified"); @@ -56,6 +61,13 @@ public PullImageCmd withRegistry(String registry) { return this; } + @Override + public PullImageCmd withAuthConfig(AuthConfig authConfig) { + Preconditions.checkNotNull(authConfig, "authConfig was not specified"); + this.authConfig = authConfig; + return this; + } + @Override public String toString() { return new StringBuilder("pull ") diff --git a/src/main/java/com/github/dockerjava/jaxrs/AuthCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/AuthCmdExec.java index d73487bb8..3552d9742 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/AuthCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/AuthCmdExec.java @@ -1,18 +1,18 @@ package com.github.dockerjava.jaxrs; -import static javax.ws.rs.client.Entity.entity; +import com.github.dockerjava.api.UnauthorizedException; +import com.github.dockerjava.api.command.AuthCmd; +import com.github.dockerjava.api.model.AuthResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.github.dockerjava.api.UnauthorizedException; -import com.github.dockerjava.api.command.AuthCmd; +import static javax.ws.rs.client.Entity.entity; -public class AuthCmdExec extends AbstrDockerCmdExec implements AuthCmd.Exec { +public class AuthCmdExec extends AbstrDockerCmdExec implements AuthCmd.Exec { private static final Logger LOGGER = LoggerFactory .getLogger(AuthCmdExec.class); @@ -22,16 +22,18 @@ public AuthCmdExec(WebTarget baseResource) { } @Override - protected Void execute(AuthCmd command) { + protected AuthResponse execute(AuthCmd command) { WebTarget webResource = getBaseResource().path("/auth"); LOGGER.trace("POST: {}", webResource); - Response response = webResource.request().accept(MediaType.APPLICATION_JSON).post(entity(command.getAuthConfig(), MediaType.APPLICATION_JSON)); + Response response = webResource + .request() + .accept(MediaType.APPLICATION_JSON).post(entity(command.getAuthConfig(), MediaType.APPLICATION_JSON)); if(response.getStatus() == 401) { throw new UnauthorizedException("Unauthorized"); - }; - - return null; + } + + return response.readEntity(AuthResponse.class); } } diff --git a/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java index 4ac190be4..dea72f429 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/PullImageCmdExec.java @@ -1,17 +1,17 @@ package com.github.dockerjava.jaxrs; -import static javax.ws.rs.client.Entity.entity; - -import java.io.InputStream; +import com.github.dockerjava.api.command.PullImageCmd; +import com.github.dockerjava.api.model.AuthConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import javax.ws.rs.client.Invocation; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.io.InputStream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.github.dockerjava.api.command.PullImageCmd; +import static javax.ws.rs.client.Entity.entity; public class PullImageCmdExec extends AbstrDockerCmdExec implements PullImageCmd.Exec { @@ -27,11 +27,19 @@ protected InputStream execute(PullImageCmd command) { .queryParam("tag", command.getTag()) .queryParam("fromImage", command.getRepository()) .queryParam("registry", command.getRegistry()); - + LOGGER.trace("POST: {}", webResource); - return webResource.request() + return resourceWithOptionalAuthConfig(command, webResource.request()) .accept(MediaType.APPLICATION_OCTET_STREAM_TYPE) .post(entity(Response.class, MediaType.APPLICATION_JSON)).readEntity(InputStream.class); } + private Invocation.Builder resourceWithOptionalAuthConfig(PullImageCmd command, Invocation.Builder request) { + AuthConfig authConfig = command.getAuthConfig(); + if (authConfig != null) { + request = request.header("X-Registry-Auth", registryAuth(authConfig)); + } + return request; + } + } diff --git a/src/main/resources/docker.io.properties b/src/main/resources/docker.io.properties index f4d699537..2188cff37 100644 --- a/src/main/resources/docker.io.properties +++ b/src/main/resources/docker.io.properties @@ -1,4 +1,5 @@ docker.io.url=https://localhost:2376 -docker.io.version=1.15 docker.io.enableLoggingFilter=true -docker.io.dockerCertPath=${user.home}/.docker \ No newline at end of file +docker.io.dockerCertPath=${user.home}/.docker +docker.io.username=${user.name} +docker.io.serverAddress=https://index.docker.io/v1/ \ No newline at end of file diff --git a/src/test/java/com/github/dockerjava/api/model/AuthConfigTest.java b/src/test/java/com/github/dockerjava/api/model/AuthConfigTest.java new file mode 100644 index 000000000..1ed618ed7 --- /dev/null +++ b/src/test/java/com/github/dockerjava/api/model/AuthConfigTest.java @@ -0,0 +1,31 @@ +package com.github.dockerjava.api.model; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +public class AuthConfigTest { + + private AuthConfig authConfig; + + @BeforeMethod + public void setUp() throws Exception { + authConfig = new AuthConfig(); + authConfig.setEmail("foo"); + authConfig.setPassword("bar"); + authConfig.setServerAddress("baz"); + authConfig.setUsername("qux"); + } + + @Test + public void string() throws Exception { + assertEquals(authConfig.toString(), + "AuthConfig{username='qux', password='bar', email='foo', serverAddress='baz'}"); + } + + @Test + public void defaultServerAddress() throws Exception { + assertEquals(new AuthConfig().getServerAddress(), "https://index.docker.io/v1/"); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java index 385508b68..2e94f2302 100644 --- a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java +++ b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java @@ -1,12 +1,10 @@ package com.github.dockerjava.client; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; -import java.lang.reflect.Method; -import java.net.DatagramSocket; -import java.net.ServerSocket; - +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.DockerException; +import com.github.dockerjava.core.DockerClientBuilder; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.core.TestDockerCmdExecFactory; import org.apache.commons.io.IOUtils; import org.apache.commons.io.LineIterator; import org.slf4j.Logger; @@ -14,24 +12,27 @@ import org.testng.Assert; import org.testng.ITestResult; -import com.github.dockerjava.api.DockerClient; -import com.github.dockerjava.api.DockerException; -import com.github.dockerjava.core.DockerClientBuilder; -import com.github.dockerjava.core.TestDockerCmdExecFactory; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.lang.reflect.Method; +import java.net.DatagramSocket; +import java.net.ServerSocket; public abstract class AbstractDockerClientTest extends Assert { public static final Logger LOG = LoggerFactory .getLogger(AbstractDockerClientTest.class); - - protected DockerClient dockerClient; + public static final String DOCKER_JAVA = "dockerjava"; + + protected DockerClient dockerClient; protected TestDockerCmdExecFactory dockerCmdExecFactory = new TestDockerCmdExecFactory(DockerClientBuilder.getDefaultDockerCmdExecFactory()); public void beforeTest() { LOG.info("======================= BEFORETEST ======================="); LOG.info("Connecting to Docker server"); - dockerClient = DockerClientBuilder.getInstance() + dockerClient = DockerClientBuilder.getInstance(config()) .withDockerCmdExecFactory(dockerCmdExecFactory) .build(); @@ -45,7 +46,21 @@ public void beforeTest() { LOG.info("======================= END OF BEFORETEST =======================\n\n"); } - public void afterTest() { + private DockerClientConfig config() { + return config(null); + } + + protected DockerClientConfig config(String password) { + DockerClientConfig.DockerClientConfigBuilder builder = DockerClientConfig.createDefaultConfigBuilder() + .withServerAddress("https://index.docker.io/v1/"); + if (password!=null) { + builder = builder.withPassword(password); + } + return builder + .build(); + } + + public void afterTest() { LOG.info("======================= END OF AFTERTEST ======================="); } diff --git a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java b/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java index b0747e68e..f14640b07 100644 --- a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java +++ b/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java @@ -1,5 +1,6 @@ package com.github.dockerjava.core; +import com.github.dockerjava.api.model.AuthConfig; import org.testng.annotations.Test; import java.net.URI; @@ -15,12 +16,12 @@ public class DockerClientConfigTest { public static final DockerClientConfig EXAMPLE_CONFIG = newExampleConfig(); private static DockerClientConfig newExampleConfig() { - return new DockerClientConfig(URI.create("http://foo"), "bar", "baz", "qux", "blam", "flim", 877, false); + return new DockerClientConfig(URI.create("http://foo"), "bar", "baz", "qux", "blam", "wham", "flim", 877, false); } @Test public void string() throws Exception { - assertEquals("DockerClientConfig{uri=http://foo, version='bar', username='baz', password='qux', email='blam', dockerCertPath='flim', readTimeout=877, loggingFilterEnabled=false}", + assertEquals("DockerClientConfig{uri=http://foo, version='bar', username='baz', password='qux', email='blam', serverAddress='wham', dockerCertPath='flim', readTimeout=877, loggingFilterEnabled=false}", EXAMPLE_CONFIG.toString()); } @@ -33,7 +34,7 @@ public void equals() throws Exception { public void environmentDockerHost() throws Exception { // given docker host in env - Map env = new HashMap(System.getenv()); + Map env = new HashMap(); env.put("DOCKER_HOST", "tcp://baz:8768"); // when you build a config @@ -69,6 +70,7 @@ public void environment() throws Exception { env.put("DOCKER_USERNAME", "baz"); env.put("DOCKER_PASSWORD", "qux"); env.put("DOCKER_EMAIL", "blam"); + env.put("DOCKER_SERVER_ADDRESS", "wham"); env.put("DOCKER_CERT_PATH", "flim"); env.put("DOCKER_READ_TIMEOUT", "877"); env.put("DOCKER_LOGGING_FILTER_ENABLED", "false"); @@ -89,6 +91,7 @@ public void defaults() throws Exception { // given default cert path Properties systemProperties = new Properties(); + systemProperties.setProperty("user.name", "someUserName"); systemProperties.setProperty("user.home", "someHomeDir"); // when you build config @@ -96,7 +99,9 @@ public void defaults() throws Exception { // then the cert path is as expected assertEquals(config.getUri(), URI.create("https://localhost:2376")); - assertEquals(config.getVersion(), "1.15"); + assertEquals(config.getUsername(), "someUserName"); + assertEquals(config.getServerAddress(), AuthConfig.DEFAULT_SERVER_ADDRESS); + assertEquals(config.getVersion(), null); assertEquals(config.isLoggingFilterEnabled(), true); assertEquals(config.getDockerCertPath(), "someHomeDir/.docker"); } @@ -111,6 +116,7 @@ public void systemProperties() throws Exception { systemProperties.setProperty("docker.io.username", "baz"); systemProperties.setProperty("docker.io.password", "qux"); systemProperties.setProperty("docker.io.email", "blam"); + systemProperties.setProperty("docker.io.serverAddress", "wham"); systemProperties.setProperty("docker.io.dockerCertPath", "flim"); systemProperties.setProperty("docker.io.readTimeout", "877"); systemProperties.setProperty("docker.io.enableLoggingFilter", "false"); diff --git a/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java b/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java new file mode 100644 index 000000000..da1d7f8e4 --- /dev/null +++ b/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java @@ -0,0 +1,36 @@ +package com.github.dockerjava.core; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.AssertJUnit.fail; + +public class DockerClientImplTest { + + @Test + public void configuredInstanceAuthConfig() throws Exception { + // given a config with null serverAddress + DockerClientConfig dockerClientConfig = new DockerClientConfig(null, null, "", "", "", null, null, 0, false); + DockerClientImpl dockerClient = DockerClientImpl.getInstance(dockerClientConfig); + + // when we get the auth config + try { + dockerClient.authConfig(); + fail(); + } catch (NullPointerException e) { + // then we get a NPE with expected message + assertEquals(e.getMessage(), "Configured serverAddress is null."); + } + } + + @Test + public void defaultInstanceAuthConfig() throws Exception { + // given a default client + DockerClientImpl dockerClient = DockerClientImpl.getInstance(); + + // when we get the auth config + dockerClient.authConfig(); + + // then we do not get an exception + } +} \ No newline at end of file diff --git a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java index 3c03b1b43..950111497 100644 --- a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java @@ -1,20 +1,14 @@ package com.github.dockerjava.core.command; -import java.lang.reflect.Method; - -import org.testng.ITestResult; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; - -import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.DockerException; import com.github.dockerjava.api.UnauthorizedException; +import com.github.dockerjava.api.model.AuthResponse; import com.github.dockerjava.client.AbstractDockerClientTest; import com.github.dockerjava.core.DockerClientBuilder; -import com.github.dockerjava.core.DockerClientConfig; +import org.testng.ITestResult; +import org.testng.annotations.*; + +import java.lang.reflect.Method; @Test(groups = "integration") public class AuthCmdImplTest extends AbstractDockerClientTest { @@ -41,19 +35,19 @@ public void afterMethod(ITestResult result) { @Test public void testAuth() throws Exception { - dockerClient.authCmd().exec(); - } + AuthResponse response = dockerClient.authCmd().exec(); + + assertEquals(response.getStatus(), "Login Succeeded"); + } @Test public void testAuthInvalid() throws Exception { - DockerClientConfig config = DockerClientConfig.createDefaultConfigBuilder().withPassword("garbage").build(); - DockerClient client = DockerClientBuilder.getInstance(config).withDockerCmdExecFactory(dockerCmdExecFactory).build(); - - try { - client.authCmd().exec(); + + try { + DockerClientBuilder.getInstance(config("garbage")).build().authCmd().exec(); fail("Expected a UnauthorizedException caused by a bad password."); } catch (UnauthorizedException e) { - + assertEquals(e.getMessage(), "Wrong login/password, please try again\n"); } } } diff --git a/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java index 84af9e72d..461bf6945 100644 --- a/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/PullImageCmdImplTest.java @@ -1,32 +1,33 @@ package com.github.dockerjava.core.command; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.lessThanOrEqualTo; -import static org.hamcrest.Matchers.notNullValue; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; - -import org.testng.ITestResult; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; - import com.github.dockerjava.api.DockerException; import com.github.dockerjava.api.InternalServerErrorException; import com.github.dockerjava.api.NotFoundException; import com.github.dockerjava.api.command.InspectImageResponse; +import com.github.dockerjava.api.command.PullImageCmd; import com.github.dockerjava.api.model.Info; import com.github.dockerjava.client.AbstractDockerClientTest; +import org.testng.ITestResult; +import org.testng.annotations.*; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; @Test(groups = "integration") public class PullImageCmdImplTest extends AbstractDockerClientTest { - @BeforeTest + private static final PullImageCmd.Exec NOP_EXEC = new PullImageCmd.Exec() { + @Override + public InputStream exec(PullImageCmd command) { + return null; + } + }; + + @BeforeTest public void beforeTest() throws DockerException { super.beforeTest(); } @@ -46,7 +47,18 @@ public void afterMethod(ITestResult result) { super.afterMethod(result); } - @Test + @Test + public void nullAuthConfig() throws Exception { + PullImageCmdImpl pullImageCmd = new PullImageCmdImpl(NOP_EXEC, ""); + try { + pullImageCmd.withAuthConfig(null); + fail(); + } catch (Exception e) { + assertEquals(e.getMessage(), "authConfig was not specified"); + } + } + + @Test public void testPullImage() throws DockerException, IOException { Info info = dockerClient.infoCmd().exec(); LOG.info("Client info: {}", info.toString()); diff --git a/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java index b12ac4ec2..2e2c9134d 100644 --- a/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/PushImageCmdImplTest.java @@ -1,24 +1,17 @@ package com.github.dockerjava.core.command; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.isEmptyString; -import static org.hamcrest.Matchers.not; - -import java.lang.reflect.Method; - +import com.github.dockerjava.api.DockerException; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.client.AbstractDockerClientTest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.ITestResult; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; +import org.testng.annotations.*; -import com.github.dockerjava.api.DockerException; -import com.github.dockerjava.api.command.CreateContainerResponse; -import com.github.dockerjava.client.AbstractDockerClientTest; +import java.lang.reflect.Method; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; @Test(groups = "integration") public class PushImageCmdImplTest extends AbstractDockerClientTest { @@ -58,12 +51,13 @@ public void pushLatest() throws Exception { assertThat(container.getId(), not(isEmptyString())); - LOG.info("Commiting container: {}", container.toString()); + LOG.info("Committing container: {}", container.toString()); String imageId = dockerClient.commitCmd(container.getId()).withRepository(username + "/busybox").exec(); // we have to block until image is pushed asString(dockerClient.pushImageCmd(username + "/busybox").exec()); + LOG.info("Removing image: {}", imageId); dockerClient.removeImageCmd(imageId).exec(); String response = asString(dockerClient.pullImageCmd(username + "/busybox").exec());