Skip to content

Commit

Permalink
Fix fabric8io#1060: Smarter API version handling
Browse files Browse the repository at this point in the history
Send a test request to the Daemon, and check whether it succeeds. In the return response
there's a header Api-Version: which holds the actual Docker daemon version. If this test
request because of a too low version, we can just pick up that version and use it as
minimal version for us.
  • Loading branch information
rohanKanojia committed Oct 16, 2018
1 parent e0d8286 commit 8ac0815
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ private static String encode(String param) {
}
}

private String stripSlash(String url) {
public static String stripSlash(String url) {
String ret = url;
while (ret.endsWith("/")) {
ret = ret.substring(0, ret.length() - 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.google.gson.JsonObject;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
Expand Down Expand Up @@ -58,6 +59,8 @@
import io.fabric8.maven.docker.util.ImageName;
import io.fabric8.maven.docker.util.Logger;
import io.fabric8.maven.docker.util.Timestamp;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;

import static java.net.HttpURLConnection.HTTP_CREATED;
import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
Expand Down Expand Up @@ -105,26 +108,25 @@ public class DockerAccessWithHcClient implements DockerAccess {
* @param log a log handler for printing out logging information
* @paran usePool whether to use a connection bool or not
*/
public DockerAccessWithHcClient(String apiVersion,
String baseUrl,
public DockerAccessWithHcClient(String baseUrl,
String certPath,
int maxConnections,
Logger log) throws IOException {
this.log = log;
URI uri = URI.create(baseUrl);
if (uri.getScheme() == null) {
throw new IllegalArgumentException("The docker access url '" + baseUrl + "' must contain a schema tcp://, unix:// or npipe://");
}
if (uri.getScheme().equalsIgnoreCase("unix")) {
this.delegate = createHttpClient(new UnixSocketClientBuilder(uri.getPath(), maxConnections, log));
this.urlBuilder = new UrlBuilder(UNIX_URL, apiVersion);
baseUrl = UNIX_URL;
} else if (uri.getScheme().equalsIgnoreCase("npipe")) {
this.delegate = createHttpClient(new NamedPipeClientBuilder(uri.getPath(), maxConnections, log), false);
this.urlBuilder = new UrlBuilder(NPIPE_URL, apiVersion);
this.delegate = createHttpClient(new NamedPipeClientBuilder(uri.getPath(), maxConnections, log), false);
baseUrl = NPIPE_URL;
} else {
this.delegate = createHttpClient(new HttpClientBuilder(isSSL(baseUrl) ? certPath : null, maxConnections));
this.urlBuilder = new UrlBuilder(baseUrl, apiVersion);
}
this.urlBuilder = new UrlBuilder(baseUrl, "v" + fetchApiVersionFromServer(UrlBuilder.stripSlash(baseUrl), this.delegate));
this.log = log;
}

/** {@inheritDoc} */
Expand Down Expand Up @@ -685,7 +687,7 @@ private void logRemoveResponse(JsonArray logElements) {
}
}

private boolean isSSL(String url) {
private static boolean isSSL(String url) {
return url != null && url.toLowerCase().startsWith("https");
}

Expand All @@ -707,4 +709,13 @@ public Object handleResponse(HttpResponse response) throws IOException {
return null;
}
}

public String fetchApiVersionFromServer(String baseUrl, ApacheHttpClientDelegate delegate) throws IOException {
HttpGet get = new HttpGet(baseUrl + "/version");
get.addHeader(HttpHeaders.ACCEPT, "*/*");
get.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
CloseableHttpResponse response = delegate.getHttpClient().execute(get);

return response.getFirstHeader("Api-Version") != null ? response.getFirstHeader("Api-Version").getValue() : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public DockerAccess createDockerAccess(DockerAccessContext dockerAccessContext)
DockerConnectionDetector.ConnectionParameter connectionParam =
dockerConnectionDetector.detectConnectionParameter(dockerAccessContext.getDockerHost(), dockerAccessContext.getCertPath());
String version = dockerAccessContext.getMinimalApiVersion() != null ? dockerAccessContext.getMinimalApiVersion() : API_VERSION;
DockerAccess access = new DockerAccessWithHcClient("v" + version, connectionParam.getUrl(),
DockerAccess access = new DockerAccessWithHcClient(connectionParam.getUrl(),
connectionParam.getCertPath(),
dockerAccessContext.getMaxConnections(),
dockerAccessContext.getLog());
Expand Down
3 changes: 1 addition & 2 deletions src/test/java/integration/DockerAccessIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import io.fabric8.maven.docker.config.Arguments;
import io.fabric8.maven.docker.config.DockerMachineConfiguration;
import io.fabric8.maven.docker.model.Container.PortBinding;
import io.fabric8.maven.docker.service.DockerAccessFactory;
import io.fabric8.maven.docker.util.AnsiLogger;
import io.fabric8.maven.docker.util.Logger;

Expand Down Expand Up @@ -110,7 +109,7 @@ public void testLoadImage() throws DockerAccessException {
private DockerAccessWithHcClient createClient(String baseUrl, Logger logger) {
try {
String certPath = createDockerConnectionDetector(logger).detectConnectionParameter(null,null).getCertPath();
return new DockerAccessWithHcClient("v" + DockerAccessFactory.API_VERSION, baseUrl, certPath, 20, logger);
return new DockerAccessWithHcClient(baseUrl, certPath, 20, logger);
} catch (@SuppressWarnings("unused") IOException e) {
// not using ssl, so not going to happen
logger.error(e.getMessage());
Expand Down
3 changes: 1 addition & 2 deletions src/test/java/integration/DockerAccessWinIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import io.fabric8.maven.docker.access.hc.DockerAccessWithHcClient;
import io.fabric8.maven.docker.config.Arguments;
import io.fabric8.maven.docker.model.Container.PortBinding;
import io.fabric8.maven.docker.service.DockerAccessFactory;
import io.fabric8.maven.docker.util.AnsiLogger;
import io.fabric8.maven.docker.util.Logger;

Expand Down Expand Up @@ -98,7 +97,7 @@ public void testPullStartStopRemove() throws DockerAccessException {
private DockerAccessWithHcClient createClient(String baseUrl, Logger logger) {
try {
String certPath = createDockerConnectionDetector(logger).detectConnectionParameter(null, null).getCertPath();
return new DockerAccessWithHcClient("v" + DockerAccessFactory.API_VERSION, baseUrl, certPath, 1, logger);
return new DockerAccessWithHcClient(baseUrl, certPath, 1, logger);
} catch (@SuppressWarnings("unused") IOException e) {
// not using ssl, so not going to happen
logger.error(e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class DockerAccessWithHcClientTest {

@Before
public void setup() throws IOException {
client = new DockerAccessWithHcClient("v1.20", "tcp://1.2.3.4:2375", null, 1, mockLogger) {
client = new DockerAccessWithHcClient("tcp://1.2.3.4:2375", null, 1, mockLogger) {
@Override
ApacheHttpClientDelegate createHttpClient(ClientBuilder builder) throws IOException {
return mockDelegate;
Expand Down

0 comments on commit 8ac0815

Please sign in to comment.