Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes using base image from registry that requires token authentication. #549

Merged
merged 2 commits into from
Jul 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.google.cloud.tools.jib.cache.Caches;
import com.google.cloud.tools.jib.frontend.ExposedPortsParser;
import com.google.cloud.tools.jib.image.ImageReference;
import com.google.cloud.tools.jib.image.InvalidImageReferenceException;
import com.google.cloud.tools.jib.registry.LocalRegistry;
import java.io.IOException;
import java.net.URISyntaxException;
Expand All @@ -32,6 +33,7 @@
import java.util.concurrent.ExecutionException;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
Expand All @@ -46,28 +48,28 @@ public class BuildStepsIntegrationTest {

@Rule public TemporaryFolder temporaryCacheDirectory = new TemporaryFolder();

private SourceFilesConfiguration sourceFilesConfiguration;

@Before
public void setUp() throws IOException, URISyntaxException {
sourceFilesConfiguration = new TestSourceFilesConfiguration();
}

@Test
public void testSteps_forBuildToDockerRegistry()
throws IOException, URISyntaxException, InterruptedException, CacheMetadataCorruptedException,
ExecutionException, CacheDirectoryNotOwnedException, CacheDirectoryCreationException {
SourceFilesConfiguration sourceFilesConfiguration = new TestSourceFilesConfiguration();
BuildConfiguration buildConfiguration =
BuildConfiguration.builder(logger)
.setBaseImage(ImageReference.of("gcr.io", "distroless/java", "latest"))
.setTargetImage(ImageReference.of("localhost:5000", "testimage", "testtag"))
.setMainClass("HelloWorld")
.setJavaArguments(Collections.singletonList("An argument."))
.setExposedPorts(
ExposedPortsParser.parse(Arrays.asList("1000", "2000-2002/tcp", "3000/udp")))
.setAllowHttp(true)
.build();

Path cacheDirectory = temporaryCacheDirectory.newFolder().toPath();
throws IOException, InterruptedException, CacheMetadataCorruptedException, ExecutionException,
CacheDirectoryNotOwnedException, CacheDirectoryCreationException {
BuildSteps buildImageSteps =
BuildSteps.forBuildToDockerRegistry(
buildConfiguration,
sourceFilesConfiguration,
new Caches.Initializer(cacheDirectory, false, cacheDirectory, false));
getBuildSteps(
BuildConfiguration.builder(logger)
.setBaseImage(ImageReference.of("gcr.io", "distroless/java", "latest"))
.setTargetImage(ImageReference.of("localhost:5000", "testimage", "testtag"))
.setMainClass("HelloWorld")
.setJavaArguments(Collections.singletonList("An argument."))
.setExposedPorts(
ExposedPortsParser.parse(Arrays.asList("1000", "2000-2002/tcp", "3000/udp")))
.setAllowHttp(true)
.build());

long lastTime = System.nanoTime();
buildImageSteps.run();
Expand All @@ -91,11 +93,31 @@ public void testSteps_forBuildToDockerRegistry()
"Hello, world. An argument.\n", new Command("docker", "run", imageReference).run());
}

@Test
public void testSteps_forBuildToDockerRegistry_dockerHubBaseImage()
throws InvalidImageReferenceException, IOException, InterruptedException, ExecutionException,
CacheDirectoryCreationException, CacheMetadataCorruptedException,
CacheDirectoryNotOwnedException {
getBuildSteps(
BuildConfiguration.builder(logger)
.setBaseImage(ImageReference.parse("openjdk:8-jre-alpine"))
.setTargetImage(ImageReference.of("localhost:5000", "testimage", "testtag"))
.setMainClass("HelloWorld")
.setJavaArguments(Collections.singletonList("An argument."))
.setAllowHttp(true)
.build())
.run();

String imageReference = "localhost:5000/testimage:testtag";
new Command("docker", "pull", imageReference).run();
Assert.assertEquals(
"Hello, world. An argument.\n", new Command("docker", "run", imageReference).run());
}

@Test
public void testSteps_forBuildToDockerDaemon()
throws IOException, URISyntaxException, InterruptedException, CacheMetadataCorruptedException,
ExecutionException, CacheDirectoryNotOwnedException, CacheDirectoryCreationException {
SourceFilesConfiguration sourceFilesConfiguration = new TestSourceFilesConfiguration();
throws IOException, InterruptedException, CacheMetadataCorruptedException, ExecutionException,
CacheDirectoryNotOwnedException, CacheDirectoryCreationException {
BuildConfiguration buildConfiguration =
BuildConfiguration.builder(logger)
.setBaseImage(ImageReference.of("gcr.io", "distroless/java", "latest"))
Expand All @@ -107,13 +129,12 @@ public void testSteps_forBuildToDockerDaemon()
.build();

Path cacheDirectory = temporaryCacheDirectory.newFolder().toPath();
BuildSteps buildDockerSteps =
BuildSteps.forBuildToDockerDaemon(
BuildSteps.forBuildToDockerDaemon(
buildConfiguration,
sourceFilesConfiguration,
new Caches.Initializer(cacheDirectory, false, cacheDirectory, false));
new Caches.Initializer(cacheDirectory, false, cacheDirectory, false))
.run();

buildDockerSteps.run();
Assert.assertThat(
new Command("docker", "inspect", "testdocker").run(),
CoreMatchers.containsString(
Expand All @@ -126,4 +147,12 @@ public void testSteps_forBuildToDockerDaemon()
Assert.assertEquals(
"Hello, world. An argument.\n", new Command("docker", "run", "testdocker").run());
}

private BuildSteps getBuildSteps(BuildConfiguration buildConfiguration) throws IOException {
Path cacheDirectory = temporaryCacheDirectory.newFolder().toPath();
return BuildSteps.forBuildToDockerRegistry(
buildConfiguration,
sourceFilesConfiguration,
new Caches.Initializer(cacheDirectory, false, cacheDirectory, false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.google.cloud.tools.jib.http.Authorization;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;

/** Integration tests for {@link AuthenticationMethodRetriever}. */
Expand All @@ -27,14 +28,15 @@ public class AuthenticationMethodRetrieverIntegrationTest {
public void testGetRegistryAuthenticator()
throws RegistryAuthenticationFailedException, IOException, RegistryException {
RegistryClient registryClient =
RegistryClient.factory("registry.hub.docker.com", "library/busybox")
.newWithAuthorization(null);
RegistryClient.factory("registry.hub.docker.com", "library/busybox").newRegistryClient();
RegistryAuthenticator registryAuthenticator = registryClient.getRegistryAuthenticator();
Assert.assertNotNull(registryAuthenticator);
Authorization authorization = registryAuthenticator.authenticatePull();

RegistryClient authorizedRegistryClient =
RegistryClient.factory("registry.hub.docker.com", "library/busybox")
.newWithAuthorization(authorization);
.setAuthorization(authorization)
.newRegistryClient();
authorizedRegistryClient.pullManifest("latest");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class BlobCheckerIntegrationTest {
@Test
public void testCheck_exists() throws IOException, RegistryException {
RegistryClient registryClient =
RegistryClient.factory("localhost:5000", "busybox").newAllowHttp();
RegistryClient.factory("localhost:5000", "busybox").setAllowHttp(true).newRegistryClient();
V22ManifestTemplate manifestTemplate =
registryClient.pullManifest("latest", V22ManifestTemplate.class);
DescriptorDigest blobDigest = manifestTemplate.getLayers().get(0).getDigest();
Expand All @@ -43,7 +43,7 @@ public void testCheck_exists() throws IOException, RegistryException {
@Test
public void testCheck_doesNotExist() throws IOException, RegistryException, DigestException {
RegistryClient registryClient =
RegistryClient.factory("localhost:5000", "busybox").newAllowHttp();
RegistryClient.factory("localhost:5000", "busybox").setAllowHttp(true).newRegistryClient();
DescriptorDigest fakeBlobDigest =
DescriptorDigest.fromHash(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class BlobPullerIntegrationTest {
public void testPull() throws IOException, RegistryException {
// Pulls the busybox image.
RegistryClient registryClient =
RegistryClient.factory("localhost:5000", "busybox").newAllowHttp();
RegistryClient.factory("localhost:5000", "busybox").setAllowHttp(true).newRegistryClient();
V21ManifestTemplate manifestTemplate =
registryClient.pullManifest("latest", V21ManifestTemplate.class);

Expand All @@ -64,7 +64,9 @@ public void testPull_unknownBlob() throws RegistryException, IOException, Digest

try {
RegistryClient registryClient =
RegistryClient.factory("localhost:5000", "busybox").newAllowHttp();
RegistryClient.factory("localhost:5000", "busybox")
.setAllowHttp(true)
.newRegistryClient();
registryClient.pullBlob(nonexistentDigest, Mockito.mock(OutputStream.class));
Assert.fail("Trying to pull nonexistent blob should have errored");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ public void testPush() throws DigestException, IOException, RegistryException {
"52a9e4d4ba4333ce593707f98564fee1e6d898db0d3602408c0b2a6a424d357c");

RegistryClient registryClient =
RegistryClient.factory("localhost:5000", "testimage").newAllowHttp();
RegistryClient.factory("localhost:5000", "testimage")
.setAllowHttp(true)
.newRegistryClient();
Assert.assertFalse(registryClient.pushBlob(testBlobDigest, testBlob));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class ManifestPullerIntegrationTest {
@Test
public void testPull_v21() throws IOException, RegistryException {
RegistryClient registryClient =
RegistryClient.factory("localhost:5000", "busybox").newAllowHttp();
RegistryClient.factory("localhost:5000", "busybox").setAllowHttp(true).newRegistryClient();
V21ManifestTemplate manifestTemplate =
registryClient.pullManifest("latest", V21ManifestTemplate.class);

Expand All @@ -44,7 +44,7 @@ public void testPull_v21() throws IOException, RegistryException {
@Test
public void testPull_v22() throws IOException, RegistryException {
RegistryClient registryClient =
RegistryClient.factory("gcr.io", "distroless/java").newWithAuthorization(null);
RegistryClient.factory("gcr.io", "distroless/java").newRegistryClient();
ManifestTemplate manifestTemplate = registryClient.pullManifest("latest");

Assert.assertEquals(2, manifestTemplate.getSchemaVersion());
Expand All @@ -56,7 +56,9 @@ public void testPull_v22() throws IOException, RegistryException {
public void testPull_unknownManifest() throws RegistryException, IOException {
try {
RegistryClient registryClient =
RegistryClient.factory("localhost:5000", "busybox").newAllowHttp();
RegistryClient.factory("localhost:5000", "busybox")
.setAllowHttp(true)
.newRegistryClient();
registryClient.pullManifest("nonexistent-tag");
Assert.fail("Trying to pull nonexistent image should have errored");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ public class ManifestPusherIntegrationTest {
@Test
public void testPush_missingBlobs() throws IOException, RegistryException {
RegistryClient registryClient =
RegistryClient.factory("gcr.io", "distroless/java").newWithAuthorization(null);
RegistryClient.factory("gcr.io", "distroless/java").newRegistryClient();
ManifestTemplate manifestTemplate = registryClient.pullManifest("latest");

registryClient = RegistryClient.factory("localhost:5000", "busybox").newAllowHttp();
registryClient =
RegistryClient.factory("localhost:5000", "busybox").setAllowHttp(true).newRegistryClient();
try {
registryClient.pushManifest((V22ManifestTemplate) manifestTemplate, "latest");
Assert.fail("Pushing manifest without its BLOBs should fail");
Expand Down Expand Up @@ -72,7 +73,9 @@ public void testPush() throws DigestException, IOException, RegistryException {

// Pushes the BLOBs.
RegistryClient registryClient =
RegistryClient.factory("localhost:5000", "testimage").newAllowHttp();
RegistryClient.factory("localhost:5000", "testimage")
.setAllowHttp(true)
.newRegistryClient();
Assert.assertFalse(registryClient.pushBlob(testLayerBlobDigest, testLayerBlob));
Assert.assertFalse(
registryClient.pushBlob(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,13 @@ public ListenableFuture<CachedLayer> getFuture() {
public CachedLayer call() throws IOException, RegistryException {
try (Timer ignored =
new Timer(buildConfiguration.getBuildLogger(), String.format(DESCRIPTION, layerDigest))) {
RegistryClient.Factory registryClientFactory =
RegistryClient.factory(
buildConfiguration.getBaseImageRegistry(),
buildConfiguration.getBaseImageRepository());
RegistryClient registryClient =
buildConfiguration.getAllowHttp()
? registryClientFactory.newAllowHttp()
: registryClientFactory.newWithAuthorization(pullAuthorization);
RegistryClient.factory(
buildConfiguration.getBaseImageRegistry(),
buildConfiguration.getBaseImageRepository())
.setAllowHttp(buildConfiguration.getAllowHttp())
.setAuthorization(pullAuthorization)
.newRegistryClient();

// Checks if the layer already exists in the cache.
CachedLayer cachedLayer = new CacheReader(cache).getLayer(layerDigest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
import com.google.cloud.tools.jib.image.json.V21ManifestTemplate;
import com.google.cloud.tools.jib.image.json.V22ManifestTemplate;
import com.google.cloud.tools.jib.json.JsonTemplateMapper;
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.RegistryClient;
import com.google.cloud.tools.jib.registry.RegistryException;
import com.google.cloud.tools.jib.registry.RegistryUnauthorizedException;
Expand Down Expand Up @@ -94,7 +97,7 @@ public ListenableFuture<BaseImageWithAuthorization> getFuture() {
@Override
public BaseImageWithAuthorization call()
throws IOException, RegistryException, LayerPropertyNotFoundException,
LayerCountMismatchException, ExecutionException {
LayerCountMismatchException, ExecutionException, RegistryAuthenticationFailedException {
buildConfiguration
.getBuildLogger()
.lifecycle("Getting base image " + buildConfiguration.getBaseImageReference() + "...");
Expand All @@ -114,8 +117,31 @@ public BaseImageWithAuthorization call()

Authorization registryCredentials =
NonBlockingSteps.get(retrieveBaseRegistryCredentialsStep);
return new BaseImageWithAuthorization(
pullBaseImage(registryCredentials), registryCredentials);

try {
return new BaseImageWithAuthorization(
pullBaseImage(registryCredentials), registryCredentials);

} catch (RegistryUnauthorizedException registryUnauthorizedException) {
// The registry requires us to authenticate using the Docker Token Authentication.
// See https://docs.docker.com/registry/spec/auth/token
RegistryAuthenticator registryAuthenticator =
RegistryAuthenticators.forOther(
buildConfiguration.getBaseImageRegistry(),
buildConfiguration.getBaseImageRepository());
if (registryAuthenticator == null) {
buildConfiguration
.getBuildLogger()
.error(
"Failed to retrieve authentication challenge for registry that required token authentication");
throw registryUnauthorizedException;
}
registryCredentials =
registryAuthenticator.setAuthorization(registryCredentials).authenticatePull();

return new BaseImageWithAuthorization(
pullBaseImage(registryCredentials), registryCredentials);
}
}
}
}
Expand All @@ -134,13 +160,13 @@ public BaseImageWithAuthorization call()
private Image<Layer> pullBaseImage(@Nullable Authorization registryCredentials)
throws IOException, RegistryException, LayerPropertyNotFoundException,
LayerCountMismatchException {
RegistryClient.Factory registryClientFactory =
RegistryClient.factory(
buildConfiguration.getBaseImageRegistry(), buildConfiguration.getBaseImageRepository());
RegistryClient registryClient =
buildConfiguration.getAllowHttp()
? registryClientFactory.newAllowHttp()
: registryClientFactory.newWithAuthorization(registryCredentials);
RegistryClient.factory(
buildConfiguration.getBaseImageRegistry(),
buildConfiguration.getBaseImageRepository())
.setAllowHttp(buildConfiguration.getAllowHttp())
.setAuthorization(registryCredentials)
.newRegistryClient();

ManifestTemplate manifestTemplate =
registryClient.pullManifest(buildConfiguration.getBaseImageTag());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,13 @@ public ListenableFuture<BlobDescriptor> getFuture() {
public BlobDescriptor call() throws IOException, RegistryException, ExecutionException {
try (Timer timer =
new Timer(buildConfiguration.getBuildLogger(), DESCRIPTION + blobDescriptor)) {
RegistryClient.Factory registryClientFactory =
RegistryClient.factory(
buildConfiguration.getTargetImageRegistry(),
buildConfiguration.getTargetImageRepository());
RegistryClient registryClient =
buildConfiguration.getAllowHttp()
? registryClientFactory.newAllowHttp()
: registryClientFactory.newWithAuthorization(
NonBlockingSteps.get(authenticatePushStep));
RegistryClient.factory(
buildConfiguration.getTargetImageRegistry(),
buildConfiguration.getTargetImageRepository())
.setAllowHttp(buildConfiguration.getAllowHttp())
.setAuthorization(NonBlockingSteps.get(authenticatePushStep))
.newRegistryClient();
registryClient.setTimer(timer);

if (registryClient.checkBlob(blobDescriptor.getDigest()) != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,13 @@ private ListenableFuture<Void> afterPushSteps() throws ExecutionException {

private Void afterAllPushed() throws IOException, RegistryException, ExecutionException {
try (Timer ignored = new Timer(buildConfiguration.getBuildLogger(), DESCRIPTION)) {
RegistryClient.Factory registryClientFactory =
RegistryClient.factory(
buildConfiguration.getTargetImageRegistry(),
buildConfiguration.getTargetImageRepository());
RegistryClient registryClient =
buildConfiguration.getAllowHttp()
? registryClientFactory.newAllowHttp()
: registryClientFactory.newWithAuthorization(
NonBlockingSteps.get(authenticatePushStep));
RegistryClient.factory(
buildConfiguration.getTargetImageRegistry(),
buildConfiguration.getTargetImageRepository())
.setAllowHttp(buildConfiguration.getAllowHttp())
.setAuthorization(NonBlockingSteps.get(authenticatePushStep))
.newRegistryClient();

// Constructs the image.
ImageToJsonTranslator imageToJsonTranslator =
Expand Down
Loading