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

Do not fall back to HTTP for connection timeout #1949

Merged
merged 2 commits into from
Sep 4, 2019
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 @@ -165,26 +165,6 @@ public StepsRunner registryPushSteps() {
return this;
}

private void addRetrievalSteps(boolean layersRequiredLocally) {
ImageConfiguration baseImageConfiguration = buildConfiguration.getBaseImageConfiguration();

if (baseImageConfiguration.getTarPath().isPresent()) {
// If tarPath is present, a TarImage was used
results.tarPath = Futures.immediateFuture(baseImageConfiguration.getTarPath().get());
stepsToRun.add(this::extractTar);

} else if (baseImageConfiguration.getDockerClient().isPresent()) {
// If dockerClient is present, a DockerDaemonImage was used
stepsToRun.add(this::saveDocker);
stepsToRun.add(this::extractTar);

} else {
// Otherwise default to RegistryImage
stepsToRun.add(this::pullBaseImage);
stepsToRun.add(() -> obtainBaseImageLayers(layersRequiredLocally));
}
}

public BuildResult run() throws ExecutionException, InterruptedException {
Preconditions.checkNotNull(rootProgressDescription);

Expand All @@ -205,6 +185,26 @@ public BuildResult run() throws ExecutionException, InterruptedException {
}
}

private void addRetrievalSteps(boolean layersRequiredLocally) {
ImageConfiguration baseImageConfiguration = buildConfiguration.getBaseImageConfiguration();

if (baseImageConfiguration.getTarPath().isPresent()) {
// If tarPath is present, a TarImage was used
results.tarPath = Futures.immediateFuture(baseImageConfiguration.getTarPath().get());
stepsToRun.add(this::extractTar);

} else if (baseImageConfiguration.getDockerClient().isPresent()) {
// If dockerClient is present, a DockerDaemonImage was used
stepsToRun.add(this::saveDocker);
stepsToRun.add(this::extractTar);

} else {
// Otherwise default to RegistryImage
stepsToRun.add(this::pullBaseImage);
stepsToRun.add(() -> obtainBaseImageLayers(layersRequiredLocally));
}
}

private void retrieveTargetRegistryCredentials() {
ProgressEventDispatcher.Factory childProgressDispatcherFactory =
Verify.verifyNotNull(rootProgressDispatcher).newChildProducer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ private T callWithAllowInsecureRegistryHandling(URL url) throws IOException, Reg
return handleUnverifiableServerException(url);

} catch (ConnectException ex) {
// It is observed that Open/Oracle JDKs sometimes throw SocketTimeoutException but other times
// ConnectException for connection timeout. (Could be a JDK bug.) Note SocketTimeoutException
// does not extend ConnectException (or vice versa), and we want to be consistent to error out
// on timeouts: https://github.com/GoogleContainerTools/jib/issues/1895#issuecomment-527544094
if (ex.getMessage() != null && ex.getMessage().contains("timed out")) {
throw ex;
}

if (allowInsecureRegistries && isHttpsProtocol(url) && url.getPort() == -1) {
// Fall back to HTTP only if "url" had no port specified (i.e., we tried the default HTTPS
// port 443) and we could not connect to 443. It's worth trying port 80.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,26 @@ public void testCall_insecureCallerOnNonListeningServerAndPortSpecified()
Mockito.verifyNoMoreInteractions(mockInsecureConnectionFactory);
}

@Test
public void testCall_timeoutFromConnectException() throws IOException, RegistryException {
ConnectException mockConnectException = Mockito.mock(ConnectException.class);
Mockito.when(mockConnectException.getMessage()).thenReturn("Connection timed out");
Mockito.when(mockConnection.send(Mockito.eq("httpMethod"), Mockito.any()))
.thenThrow(mockConnectException) // server times out on 443
.thenReturn(mockResponse); // respond when connected through 80

try {
RegistryEndpointCaller<String> insecureEndpointCaller =
createRegistryEndpointCaller(true, -1);
insecureEndpointCaller.call();
Assert.fail("Should not fall back to HTTP if timed out even for ConnectionException");

} catch (ConnectException ex) {
Assert.assertSame(mockConnectException, ex);
Mockito.verify(mockConnection).send(Mockito.anyString(), Mockito.any());
}
}

@Test
public void testCall_noHttpResponse() throws IOException, RegistryException {
NoHttpResponseException mockNoHttpResponseException =
Expand Down