Skip to content

Commit

Permalink
Allows use of Maven settings for defining registry credentials. (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
coollog authored Feb 12, 2018
1 parent 85defe6 commit 43d479a
Show file tree
Hide file tree
Showing 27 changed files with 404 additions and 238 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ All notable changes to this project will be documented in this file.
- Simple example `helloworld` project under `examples/` ([#62](https://github.com/google/jib/pull/62))
- Better error messages when pushing an image manifest ([#63](https://github.com/google/jib/pull/63))
- Validates target image configuration ([#63](https://github.com/google/jib/pull/63))
- Configure multiple credential helpers with `credHelpers` ([#68](https://github.com/google/jib/pull/68))
- Configure registry credentials with Maven settings ([#81](https://github.com/google/jib/pull/81))

### Changed
- Configure multiple credential helpers with `credHelpers` ([#68](https://github.com/google/jib/pull/68))
- Removed configuration `credentialHelperName` ([#68](https://github.com/google/jib/pull/68))

### Fixed
- Build failure on Windows ([#74](https://github.com/google/jib/issues/74))
- Infers common credential helper names (for GCR and ECR) ([#64](https://github.com/google/jib/pull/64))
- Cannot use private base image ([#68](https://github.com/google/jib/pull/68))
- Building applications with no resources ([#73](https://github.com/google/jib/pull/73))
- Pushing to registries like Docker Hub and ACR ([#75](https://github.com/google/jib/issues/75))
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ public void testSteps() throws Exception {
SourceFilesConfiguration sourceFilesConfiguration = new TestSourceFilesConfiguration();
BuildConfiguration buildConfiguration =
BuildConfiguration.builder()
.setBaseImageServerUrl("gcr.io")
.setBaseImageName("distroless/java")
.setBaseImageRegistry("gcr.io")
.setBaseImageRepository("distroless/java")
.setBaseImageTag("latest")
.setTargetServerUrl("localhost:5000")
.setTargetImageName("testimage")
.setTargetRegistry("localhost:5000")
.setTargetRepository("testimage")
.setTargetTag("testtag")
.setMainClass("HelloWorld")
.setBuildLogger(new TestBuildLogger())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void testGetRegistryAuthenticator()
RegistryClient registryClient =
new RegistryClient(null, "registry.hub.docker.com", "library/busybox");
RegistryAuthenticator registryAuthenticator = registryClient.getRegistryAuthenticator();
Authorization authorization = registryAuthenticator.authenticate();
Authorization authorization = registryAuthenticator.authenticatePull();

RegistryClient authorizedRegistryClient =
new RegistryClient(authorization, "registry.hub.docker.com", "library/busybox");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class RegistryAuthenticatorIntegrationTest {
public void testAuthenticate() throws RegistryAuthenticationFailedException {
RegistryAuthenticator registryAuthenticator =
RegistryAuthenticators.forDockerHub("library/busybox");
Authorization authorization = registryAuthenticator.authenticate();
Authorization authorization = registryAuthenticator.authenticatePull();

// Checks that some token was received.
Assert.assertTrue(0 < authorization.getToken().length());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,67 +19,52 @@
import com.google.cloud.tools.jib.Timer;
import com.google.cloud.tools.jib.http.Authorization;
import com.google.cloud.tools.jib.registry.RegistryAuthenticationFailedException;
import com.google.cloud.tools.jib.registry.RegistryAuthenticator;
import com.google.cloud.tools.jib.registry.RegistryAuthenticators;
import com.google.cloud.tools.jib.registry.RegistryException;
import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials;
import com.google.common.util.concurrent.ListenableFuture;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;

/** Retrieves credentials to pull from the base image registry. */
/**
* Authenticates pull from the base image registry using Docker Token Authentication.
*
* @see <a
* href="https://docs.docker.com/registry/spec/auth/token/">https://docs.docker.com/registry/spec/auth/token/</a>
*/
class AuthenticatePullStep implements Callable<Authorization> {

private static final String DESCRIPTION = "Authenticating with base image registry";
private static final String DESCRIPTION = "Authenticating pull from %s";

private final BuildConfiguration buildConfiguration;
private final ListenableFuture<RegistryCredentials> registryCredentialsFuture;
private final ListenableFuture<Authorization> registryCredentialsFuture;

AuthenticatePullStep(
BuildConfiguration buildConfiguration,
ListenableFuture<RegistryCredentials> registryCredentialsFuture) {
ListenableFuture<Authorization> registryCredentialsFuture) {
this.buildConfiguration = buildConfiguration;
this.registryCredentialsFuture = registryCredentialsFuture;
}

/** Depends on nothing. */
/** Depends on {@link RetrieveRegistryCredentialsStep}. */
@Override
public Authorization call()
throws RegistryAuthenticationFailedException, IOException, RegistryException,
ExecutionException, InterruptedException {
try (Timer ignored = new Timer(buildConfiguration.getBuildLogger(), DESCRIPTION)) {
return RegistryAuthenticators.forOther(
buildConfiguration.getBaseImageServerUrl(), buildConfiguration.getBaseImageName())
.setAuthorization(getBaseImageAuthorization())
.authenticate();
try (Timer ignored =
new Timer(
buildConfiguration.getBuildLogger(),
String.format(DESCRIPTION, buildConfiguration.getBaseImageRegistry()))) {
Authorization registryCredentials = NonBlockingFutures.get(registryCredentialsFuture);
RegistryAuthenticator registryAuthenticator =
RegistryAuthenticators.forOther(
buildConfiguration.getBaseImageRegistry(),
buildConfiguration.getBaseImageRepository());
if (registryAuthenticator == null) {
return registryCredentials;
}
return registryAuthenticator.setAuthorization(registryCredentials).authenticatePull();
}
}

/** Attempts to retrieve authorization for pulling the base image. */
@Nullable
private Authorization getBaseImageAuthorization()
throws ExecutionException, InterruptedException {
RegistryCredentials registryCredentials = NonBlockingFutures.get(registryCredentialsFuture);
String registry = buildConfiguration.getBaseImageServerUrl();

String credentialHelperSuffix = registryCredentials.getCredentialHelperUsed(registry);
Authorization authorization = registryCredentials.getAuthorization(registry);
if (credentialHelperSuffix == null || authorization == null) {
/*
* If no credentials found, give an info (not warning because in most cases, the base image is
* public and does not need extra credentials) and return null.
*/
buildConfiguration
.getBuildLogger()
.info("No credentials could be retrieved for registry " + registry);
return null;
}

buildConfiguration
.getBuildLogger()
.info(
"Using docker-credential-" + credentialHelperSuffix + " for pulling from " + registry);
return authorization;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,52 +18,56 @@

import com.google.cloud.tools.jib.Timer;
import com.google.cloud.tools.jib.http.Authorization;
import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials;
import com.google.cloud.tools.jib.registry.RegistryAuthenticationFailedException;
import com.google.cloud.tools.jib.registry.RegistryAuthenticator;
import com.google.cloud.tools.jib.registry.RegistryAuthenticators;
import com.google.cloud.tools.jib.registry.RegistryException;
import com.google.common.util.concurrent.ListenableFuture;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;

/** Retrieves credentials to push to a target registry. */
/**
* Authenticates push to a target registry using Docker Token Authentication.
*
* @see <a
* href="https://docs.docker.com/registry/spec/auth/token/">https://docs.docker.com/registry/spec/auth/token/</a>
*/
class AuthenticatePushStep implements Callable<Authorization> {

private static final String DESCRIPTION = "Authenticating with push to %s";

private final BuildConfiguration buildConfiguration;
private final ListenableFuture<RegistryCredentials> registryCredentialsFuture;
private final ListenableFuture<Authorization> registryCredentialsFuture;

AuthenticatePushStep(
BuildConfiguration buildConfiguration,
ListenableFuture<RegistryCredentials> registryCredentialsFuture) {
ListenableFuture<Authorization> registryCredentialsFuture) {
this.buildConfiguration = buildConfiguration;
this.registryCredentialsFuture = registryCredentialsFuture;
}

/** Depends on nothing. */
/** Depends on {@link RetrieveRegistryCredentialsStep}. */
@Override
@Nullable
public Authorization call() throws ExecutionException, InterruptedException {
public Authorization call()
throws ExecutionException, InterruptedException, RegistryAuthenticationFailedException,
IOException, RegistryException {
try (Timer ignored =
new Timer(
buildConfiguration.getBuildLogger(),
String.format(DESCRIPTION, buildConfiguration.getTargetServerUrl()))) {
RegistryCredentials registryCredentials = NonBlockingFutures.get(registryCredentialsFuture);
String registry = buildConfiguration.getTargetServerUrl();

String credentialHelperSuffix = registryCredentials.getCredentialHelperUsed(registry);
Authorization authorization = registryCredentials.getAuthorization(registry);
if (credentialHelperSuffix == null || authorization == null) {
// If no credentials found, give a warning and return null.
buildConfiguration
.getBuildLogger()
.warn("No credentials could be retrieved for registry " + registry);
return null;
String.format(DESCRIPTION, buildConfiguration.getTargetRegistry()))) {
Authorization registryCredentials = NonBlockingFutures.get(registryCredentialsFuture);
RegistryAuthenticator registryAuthenticator =
RegistryAuthenticators.forOther(
buildConfiguration.getTargetRegistry(), buildConfiguration.getTargetRepository());
if (registryAuthenticator == null) {
return registryCredentials;
}
buildConfiguration
.getBuildLogger()
.info(
"Using docker-credential-" + credentialHelperSuffix + " for pushing to " + registry);
return authorization;
return registryAuthenticator
.setAuthorization(NonBlockingFutures.get(registryCredentialsFuture))
.authenticatePush();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ private BlobDescriptor afterBaseImageLayerFuturesFuture()
RegistryClient registryClient =
new RegistryClient(
NonBlockingFutures.get(pushAuthorizationFuture),
buildConfiguration.getTargetServerUrl(),
buildConfiguration.getTargetImageName())
buildConfiguration.getTargetRegistry(),
buildConfiguration.getTargetRepository())
.setTimer(timer);

// Constructs the image.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,23 @@ public class BuildConfiguration {
@VisibleForTesting
enum Fields {
/** The server URL of the registry to pull the base image from. */
BASE_IMAGE_SERVER_URL(true),
BASE_IMAGE_REGISTRY(true),
/** The image name/repository of the base image (also known as the registry namespace). */
BASE_IMAGE_NAME(true),
BASE_IMAGE_REPOSITORY(true),
/** The base image tag. */
BASE_IMAGE_TAG(true),

/** The server URL of the registry to push the built image to. */
TARGET_SERVER_URL(true),
TARGET_REGISTRY(true),
/** The image name/repository of the built image (also known as the registry namespace). */
TARGET_IMAGE_NAME(true),
TARGET_REPOSITORY(true),
/** The image tag of the built image (the part after the colon). */
TARGET_TAG(true),

/** The credential helper names used by {@link RegistryCredentials}. */
CREDENTIAL_HELPER_NAMES(false),
/** Known registry credentials to fallback on. */
KNOWN_REGISTRY_CREDENTIALS(false),

/** The main class to use when running the application. */
MAIN_CLASS(true),
Expand Down Expand Up @@ -74,11 +76,11 @@ public static class Builder {
static final Map<Fields, String> FIELD_DESCRIPTIONS =
new EnumMap<Fields, String>(Fields.class) {
{
put(Fields.BASE_IMAGE_SERVER_URL, "base image registry server URL");
put(Fields.BASE_IMAGE_NAME, "base image name");
put(Fields.BASE_IMAGE_REGISTRY, "base image registry server URL");
put(Fields.BASE_IMAGE_REPOSITORY, "base image name");
put(Fields.BASE_IMAGE_TAG, "base image tag");
put(Fields.TARGET_SERVER_URL, "target registry server URL");
put(Fields.TARGET_IMAGE_NAME, "target image name");
put(Fields.TARGET_REGISTRY, "target registry server URL");
put(Fields.TARGET_REPOSITORY, "target image name");
put(Fields.TARGET_TAG, "target image tag");
put(Fields.CREDENTIAL_HELPER_NAMES, "credential helper names");
put(Fields.MAIN_CLASS, "main class");
Expand All @@ -96,6 +98,7 @@ public static class Builder {
private Builder() {
// Sets default empty values.
values.put(Fields.CREDENTIAL_HELPER_NAMES, Collections.emptyList());
values.put(Fields.KNOWN_REGISTRY_CREDENTIALS, RegistryCredentials.none());
values.put(Fields.JVM_FLAGS, Collections.emptyList());
values.put(Fields.ENVIRONMENT, Collections.emptyMap());
}
Expand All @@ -105,13 +108,13 @@ public Builder setBuildLogger(BuildLogger buildLogger) {
return this;
}

public Builder setBaseImageServerUrl(String baseImageServerUrl) {
values.put(Fields.BASE_IMAGE_SERVER_URL, baseImageServerUrl);
public Builder setBaseImageRegistry(String baseImageServerUrl) {
values.put(Fields.BASE_IMAGE_REGISTRY, baseImageServerUrl);
return this;
}

public Builder setBaseImageName(String baseImageName) {
values.put(Fields.BASE_IMAGE_NAME, baseImageName);
public Builder setBaseImageRepository(String baseImageName) {
values.put(Fields.BASE_IMAGE_REPOSITORY, baseImageName);
return this;
}

Expand All @@ -120,13 +123,13 @@ public Builder setBaseImageTag(String baseImageTag) {
return this;
}

public Builder setTargetServerUrl(String targetServerUrl) {
values.put(Fields.TARGET_SERVER_URL, targetServerUrl);
public Builder setTargetRegistry(String targetServerUrl) {
values.put(Fields.TARGET_REGISTRY, targetServerUrl);
return this;
}

public Builder setTargetImageName(String targetImageName) {
values.put(Fields.TARGET_IMAGE_NAME, targetImageName);
public Builder setTargetRepository(String targetImageName) {
values.put(Fields.TARGET_REPOSITORY, targetImageName);
return this;
}

Expand All @@ -142,6 +145,13 @@ public Builder setCredentialHelperNames(List<String> credentialHelperNames) {
return this;
}

public Builder setKnownRegistryCredentials(RegistryCredentials knownRegistryCredentials) {
if (knownRegistryCredentials != null) {
values.put(Fields.KNOWN_REGISTRY_CREDENTIALS, knownRegistryCredentials);
}
return this;
}

public Builder setMainClass(String mainClass) {
values.put(Fields.MAIN_CLASS, mainClass);
return this;
Expand Down Expand Up @@ -220,30 +230,34 @@ public BuildLogger getBuildLogger() {
return buildLogger;
}

public String getBaseImageServerUrl() {
return getFieldValue(Fields.BASE_IMAGE_SERVER_URL);
public String getBaseImageRegistry() {
return getFieldValue(Fields.BASE_IMAGE_REGISTRY);
}

public String getBaseImageName() {
return getFieldValue(Fields.BASE_IMAGE_NAME);
public String getBaseImageRepository() {
return getFieldValue(Fields.BASE_IMAGE_REPOSITORY);
}

public String getBaseImageTag() {
return getFieldValue(Fields.BASE_IMAGE_TAG);
}

public String getTargetServerUrl() {
return getFieldValue(Fields.TARGET_SERVER_URL);
public String getTargetRegistry() {
return getFieldValue(Fields.TARGET_REGISTRY);
}

public String getTargetImageName() {
return getFieldValue(Fields.TARGET_IMAGE_NAME);
public String getTargetRepository() {
return getFieldValue(Fields.TARGET_REPOSITORY);
}

public String getTargetTag() {
return getFieldValue(Fields.TARGET_TAG);
}

public RegistryCredentials getKnownRegistryCredentials() {
return getFieldValue(Fields.KNOWN_REGISTRY_CREDENTIALS);
}

public List<String> getCredentialHelperNames() {
return getFieldValue(Fields.CREDENTIAL_HELPER_NAMES);
}
Expand Down
Loading

0 comments on commit 43d479a

Please sign in to comment.