Tolerate Successfully built being found in response other than last

Different versions of Docker produce different responses when building
and tagging an image. On CI, a response with a stream like
"Successfully built 185991ffe24a" followed by a response with a
stream like "Successfully tagged spring-boot-it/centos:6.9-a23bced6"
is received. By default, for the building of an image to be considered
successful, the Docker Java client requires the stream for the last
response item to contain "Successfully built". This means that, on the
CI server, it incorrectly believes that the building of the tagged
image has failed.

This commit uses a custom BuildImageResultCallback that doesn't
require the last response to be the one that has a stream containing
"Successfully built". Instead, it looks back through the error-free
responses (newest to oldest) looking for one with a stream containing
"Successfully built".
This commit is contained in:
Andy Wilkinson 2017-06-03 13:00:15 +01:00
parent 0270ccafa5
commit 31ff7f1846

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
@ -32,7 +33,9 @@ import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.DockerClientException;
import com.github.dockerjava.api.command.DockerCmd;
import com.github.dockerjava.api.model.BuildResponseItem;
import com.github.dockerjava.api.model.Frame;
import com.github.dockerjava.core.CompressArchiveUtil;
import com.github.dockerjava.core.DockerClientBuilder;
@ -257,10 +260,58 @@ public class SysVinitLaunchScriptIT {
}
private String buildImage(DockerClient docker) {
BuildImageResultCallback resultCallback = new BuildImageResultCallback();
String dockerfile = "src/test/resources/conf/" + this.os + "/" + this.version
+ "/Dockerfile";
String tag = "spring-boot-it/" + this.os.toLowerCase() + ":" + this.version;
BuildImageResultCallback resultCallback = new BuildImageResultCallback() {
private List<BuildResponseItem> items = new ArrayList<BuildResponseItem>();
@Override
public void onNext(BuildResponseItem item) {
super.onNext(item);
this.items.add(item);
}
@Override
public String awaitImageId() {
try {
awaitCompletion();
}
catch (InterruptedException ex) {
throw new DockerClientException(
"Interrupted while waiting for image id", ex);
}
return getImageId();
}
@SuppressWarnings("deprecation")
private String getImageId() {
if (this.items.isEmpty()) {
throw new DockerClientException("Could not build image");
}
String imageId = extractImageId();
if (imageId == null) {
throw new DockerClientException("Could not build image: "
+ this.items.get(this.items.size() - 1).getError());
}
return imageId;
}
private String extractImageId() {
Collections.reverse(this.items);
for (BuildResponseItem item : this.items) {
if (item.isErrorIndicated() || item.getStream() == null) {
return null;
}
if (item.getStream().contains("Successfully built")) {
return item.getStream().replace("Successfully built", "").trim();
}
}
return null;
}
};
docker.buildImageCmd(new File(dockerfile)).withTag(tag).exec(resultCallback);
String imageId = resultCallback.awaitImageId();
return imageId;