Skip to content

Commit

Permalink
Merge pull request fabric8io#60 from spotify/dxia/private-registry-push2
Browse files Browse the repository at this point in the history
Support auth credentials for private repo push
  • Loading branch information
davidxia committed Apr 9, 2015
2 parents c31a57b + 8af67ee commit 6ba1313
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 2 deletions.
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ element to copy additional files, such as the service's jar file.
</plugins>
</build>


## Usage

You can build an image with the above configurations by running this command.
Expand Down Expand Up @@ -116,6 +115,38 @@ To remove the image named `foobar` run the following command:
For a complete list of configuration options run:
`mvn com.spotify:docker-maven-plugin:<version>:help -Ddetail=true`

### Authenticating with Private Registries

To push to a private Docker image registry that requires authentication, you can put your
credentials in your Maven's global `settings.xml` file as part of the `<servers></servers>` block.

<servers>
<server>
<id>docker-hub</id>
<username>foo</username>
<password>secret-password</password>
</server>
</servers>

Now use the server id in your project `pom.xml`.


<plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>VERSION GOES HERE</version>
<configuration>
[...]
<serverId>docker-hub</serverId>
<registryUrl>https://index.docker.io/v1/</registryUrl>
</configuration>
</plugin>
</plugins>

`<registryUrl></registryUrl>` is optional and defaults to `https://index.docker.io/v1/` in the
Spotify docker-client depedency.

## Releasing

Commits to the master branch will trigger our continuous integration agent to build the jar and
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
<dependency>
<groupId>com.spotify</groupId>
<artifactId>docker-client</artifactId>
<version>2.7.5</version>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>com.typesafe</groupId>
Expand Down
98 changes: 98 additions & 0 deletions src/main/java/com/spotify/docker/AbstractDockerMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@

import com.spotify.docker.client.DefaultDockerClient;
import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.messages.AuthConfig;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.util.xml.Xpp3Dom;

import static com.google.common.base.Strings.isNullOrEmpty;
import static com.spotify.docker.client.DefaultDockerClient.NO_TIMEOUT;
Expand All @@ -42,12 +46,25 @@ abstract class AbstractDockerMojo extends AbstractMojo {
@Component(role = MojoExecution.class)
protected MojoExecution execution;

/**
* The system settings for Maven. This is the instance resulting from
* merging global and user-level settings files.
*/
@Component
private Settings settings;

/**
* URL of the docker host as specified in pom.xml.
*/
@Parameter(property = "dockerHost")
private String dockerHost;

@Parameter(property = "serverId")
private String serverId;

@Parameter(property = "registryUrl")
private String registryUrl;

public void execute() throws MojoExecutionException {
DockerClient client = null;
try {
Expand All @@ -59,6 +76,41 @@ public void execute() throws MojoExecutionException {
builder.uri(dockerHost);
}

if (settings != null) {
final Server server = settings.getServer(serverId);
if (server != null) {
final AuthConfig.Builder authConfigBuilder = AuthConfig.builder();

final String username = server.getUsername();
final String password = server.getPassword();
final String email = getEmail(server);

if (incompleteAuthSettings(username, password, email)) {
throw new MojoExecutionException(
"Incomplete Docker registry authorization credentials. "
+ "Please provide all of username, password, and email or none.");
}

if (!isNullOrEmpty(username)) {
authConfigBuilder.username(username);
}
if (!isNullOrEmpty(email)) {
authConfigBuilder.email(email);
}
if (!isNullOrEmpty(password)) {
authConfigBuilder.password(password);
}
// registryUrl is optional.
// Spotify's docker-client defaults to 'https://index.docker.io/v1/'.
if (!isNullOrEmpty(registryUrl)) {
authConfigBuilder.serverAddress(registryUrl);
}

builder.authConfig(authConfigBuilder.build());
}
}


client = builder.build();
execute(client);
} catch (Exception e) {
Expand All @@ -75,4 +127,50 @@ public void execute() throws MojoExecutionException {
protected String rawDockerHost() {
return dockerHost;
}

/**
* Get the email from the server configuration in <code>~/.m2/settings.xml</code>.
*
* <pre>
* <servers>
* <server>
* <id>my-private-docker-registry</id>
* [...]
* <configuration>
* <email>foo@bar.com</email>
* </configuration>
* </server>
* </servers>
* </pre>
*
* The above <code>settings.xml</code> would return "foo@bar.com".
*
* @param server {@link org.apache.maven.settings.Server}
* @return email string.
*/
private String getEmail(final Server server) {
String email = null;

final Xpp3Dom configuration = (Xpp3Dom) server.getConfiguration();
final Xpp3Dom emailNode = configuration.getChild("email");
if (emailNode != null) {
email = emailNode.getValue();
}

return email;
}

/**
* Checks for incomplete private Docker registry authorization settings.
* @param username Auth username.
* @param password Auth password.
* @param email Auth email.
* @return boolean true if any of the three credentials are present but not all. False otherwise.
*/
private boolean incompleteAuthSettings(final String username, final String password,
final String email) {
return (!isNullOrEmpty(username) || !isNullOrEmpty(password) || !isNullOrEmpty(email))
&& (isNullOrEmpty(username) || isNullOrEmpty(password) || isNullOrEmpty(email));

}
}
13 changes: 13 additions & 0 deletions src/test/java/com/spotify/docker/PushMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,17 @@ public void testPush() throws Exception {
verify(docker).push(eq("busybox"), any(AnsiProgressHandler.class));
}

// TODO (dxia) Figure out how load private-repo-settings.xml
// public void testPushPrivateRepo() throws Exception {
// final File pom = getTestFile("src/test/resources/pom-push-private-repo.xml");
// assertNotNull("Null pom.xml", pom);
// assertTrue("pom.xml does not exist", pom.exists());
//
// final PushMojo mojo = (PushMojo) lookupMojo("push", pom);
// assertNotNull(mojo);
// final DockerClient docker = mock(DockerClient.class);
// mojo.execute();
// verify(docker).push(eq("busybox"), any(AnsiProgressHandler.class));
// }

}
47 changes: 47 additions & 0 deletions src/test/resources/pom-push-private-repo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<name>Docker Maven Plugin Test Pom</name>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.1-SNAPSHOT</version>
<configuration>
<imageName>dxia3/docker-maven-plugin-auth</imageName>
<serverId>docker-hub</serverId>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
17 changes: 17 additions & 0 deletions src/test/resources/private-repo-settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">

<servers>
<server>
<id>docker-hub</id>
<username>dxia3</username>
<password>SxpxdUQA2mvX7oj</password>
<configuration>
<email>dxia+3@spotify.com</email>
</configuration>
</server>
</servers>

</settings>

0 comments on commit 6ba1313

Please sign in to comment.