Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
JENKINS-48674: downloads image for newer version from download.docker…
….com
  • Loading branch information
denisa committed Jan 4, 2018
1 parent b34c6f3 commit 00a18c2
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 26 deletions.
Expand Up @@ -34,10 +34,14 @@
import hudson.tools.ToolInstallation;
import hudson.tools.ToolInstaller;
import hudson.tools.ToolInstallerDescriptor;
import hudson.util.VersionNumber;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import jenkins.security.MasterToSlaveCallable;
import org.kohsuke.stapler.DataBoundConstructor;
Expand Down Expand Up @@ -68,7 +72,7 @@ public FilePath performInstallation(ToolInstallation toolInstallation, @Nonnull
}
String os = nodeChannel.call(new FindArch());

final URL url = new URL("https://get.docker.com/builds/"+os+"/docker-"+version);
final URL url = getDockerImageUrl(os, version);
FilePath install = preferredLocation(tool, node);

// (simplified) copy/paste from FilePath as hudson.FilePath.installIfNecessaryFrom do assume the URL points to be a zip/tar archive
Expand Down Expand Up @@ -142,6 +146,27 @@ public FilePath performInstallation(ToolInstallation toolInstallation, @Nonnull
return install;
}

static URL getDockerImageUrl(String os, String version) throws MalformedURLException {
if (parseVersion(version).isNewerThan(parseVersion("17.05.0-ce")))
return new URL("https://download.docker.com/" + os + "/docker-" + version);

String osName="";
if (os.startsWith("linux")) osName = "Linux";
if (os.startsWith("win")) osName = "Windows";
if (os.startsWith("mac")) osName = "Darwin";
return new URL("https://get.docker.com/builds/" + osName + os.substring(os.lastIndexOf("/")) + "/docker-" + version);
}

private static VersionNumber parseVersion(String version) {
// any version that sorts before 17.05.0-ce
if (version.equals("latest")) return new VersionNumber("0");

final Matcher matcher = Pattern.compile("(\\d+\\.\\d+\\.\\d+).*").matcher(version);
if (matcher.matches()) return new VersionNumber(matcher.group(1));

throw new IllegalArgumentException("Failed to parse version " + version);
}

@Extension
public static class DescriptorImpl extends ToolInstallerDescriptor<DockerToolInstaller> {

Expand All @@ -162,9 +187,9 @@ private static class FindArch extends MasterToSlaveCallable<String,IOException>
public String call() throws IOException {
String os = System.getProperty("os.name").toLowerCase();
String arch = System.getProperty("os.arch").contains("64") ? "x86_64" : "i386";
if (os.contains("linux")) return "Linux/" + arch;
if (os.contains("windows")) return "Windows/" + arch;
if (os.contains("mac")) return "Darwin/" + arch;
if (os.contains("linux")) return "linux/static/stable/" + arch;
if (os.contains("windows")) return "win/static/stable/" + arch;
if (os.contains("mac")) return "mac/static/stable/" + arch;
throw new IOException("Failed to determine OS architecture " + os + ":" + arch);
}

Expand Down
Expand Up @@ -31,6 +31,7 @@
import hudson.util.StreamTaskListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import org.apache.commons.io.output.TeeOutputStream;
Expand All @@ -47,7 +48,24 @@ public class DockerToolInstallerTest {
@Rule
public JenkinsRule r = new JenkinsRule();

@Issue({"JENKINS-36082", "JENKINS-32790"})
@Issue({"JENKINS-48674"})
@Test
public void testImageUrl() throws MalformedURLException {
assertEquals(new URL("https://get.docker.com/builds/Linux/x86_64/docker-1.10.0"), DockerToolInstaller.getDockerImageUrl("linux/static/stable/x86_64", "1.10.0"));
assertEquals(new URL("https://get.docker.com/builds/Windows/x86_64/docker-1.10.0"), DockerToolInstaller.getDockerImageUrl("win/static/stable/x86_64","1.10.0"));
assertEquals(new URL("https://get.docker.com/builds/Darwin/x86_64/docker-1.10.0"), DockerToolInstaller.getDockerImageUrl("mac/static/stable/x86_64","1.10.0"));
assertEquals(new URL("https://get.docker.com/builds/Linux/x86_64/docker-17.05.0-ce"), DockerToolInstaller.getDockerImageUrl("linux/static/stable/x86_64", "17.05.0-ce"));
assertEquals(new URL("https://get.docker.com/builds/Windows/x86_64/docker-17.05.0-ce"), DockerToolInstaller.getDockerImageUrl("win/static/stable/x86_64","17.05.0-ce"));
assertEquals(new URL("https://get.docker.com/builds/Darwin/x86_64/docker-17.05.0-ce"), DockerToolInstaller.getDockerImageUrl("mac/static/stable/x86_64","17.05.0-ce"));
assertEquals(new URL("https://get.docker.com/builds/Linux/x86_64/docker-latest"), DockerToolInstaller.getDockerImageUrl("linux/static/stable/x86_64", "latest"));
assertEquals(new URL("https://get.docker.com/builds/Windows/x86_64/docker-latest"), DockerToolInstaller.getDockerImageUrl("win/static/stable/x86_64","latest"));
assertEquals(new URL("https://get.docker.com/builds/Darwin/x86_64/docker-latest"), DockerToolInstaller.getDockerImageUrl("mac/static/stable/x86_64","latest"));
assertEquals(new URL("https://download.docker.com/linux/static/stable/x86_64/docker-17.09.0-ce"), DockerToolInstaller.getDockerImageUrl("linux/static/stable/x86_64", "17.09.0-ce"));
assertEquals(new URL("https://download.docker.com/win/static/stable/x86_64/docker-17.09.0-ce"), DockerToolInstaller.getDockerImageUrl("win/static/stable/x86_64","17.09.0-ce"));
assertEquals(new URL("https://download.docker.com/mac/static/stable/x86_64/docker-17.09.0-ce"), DockerToolInstaller.getDockerImageUrl("mac/static/stable/x86_64","17.09.0-ce"));
}

@Issue({"JENKINS-36082", "JENKINS-32790", "JENKINS-48674"})
@Test
public void smokes() throws Exception {
Assume.assumeFalse(Functions.isWindows());
Expand All @@ -56,35 +74,40 @@ public void smokes() throws Exception {
} catch (IOException x) {
Assume.assumeNoException("Cannot contact get.docker.com, perhaps test machine is not online", x);
}
try {
new URL("https://download.docker.com/").openStream().close();
} catch (IOException x) {
Assume.assumeNoException("Cannot contact download.docker.com, perhaps test machine is not online", x);
}
r.jenkins.getDescriptorByType(DockerTool.DescriptorImpl.class).setInstallations(
new DockerTool("latest", "", Collections.singletonList(new InstallSourceProperty(Collections.singletonList(new DockerToolInstaller("", "latest"))))),
new DockerTool("1.10.0", "", Collections.singletonList(new InstallSourceProperty(Collections.singletonList(new DockerToolInstaller("", "1.10.0"))))));
new DockerTool("1.10.0", "", Collections.singletonList(new InstallSourceProperty(Collections.singletonList(new DockerToolInstaller("", "1.10.0"))))),
new DockerTool("17.09.1-ce", "", Collections.singletonList(new InstallSourceProperty(Collections.singletonList(new DockerToolInstaller("", "17.09.1-ce.tgz"))))));
DumbSlave slave = r.createOnlineSlave();
FilePath toolDir = slave.getRootPath().child("tools/org.jenkinsci.plugins.docker.commons.tools.DockerTool");
FilePath exe10 = toolDir.child("1.10.0/bin/docker");

FilePath exe10 = downloadDocker(slave, toolDir, "1.10.0");
FilePath exeLatest = downloadDocker(slave, toolDir, "latest");
FilePath exe17 = downloadDocker(slave, toolDir, "17.09.1-ce");

assertThat("we do not have any extra files in here", toolDir.list("**"), arrayContainingInAnyOrder(exe10, toolDir.child("1.10.0/.timestamp"), exeLatest, toolDir.child("latest/.timestamp"), exe17, toolDir.child("17.09.1-ce/.timestamp")));
}

private FilePath downloadDocker(DumbSlave slave, FilePath toolDir, String version) throws IOException, InterruptedException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
TaskListener l = new StreamTaskListener(new TeeOutputStream(baos, System.err));
// Download 1.10.0 for first time:
assertEquals(exe10.getRemote(), DockerTool.getExecutable("1.10.0", slave, l, null));
assertTrue(exe10.exists());
assertThat(baos.toString(), containsString(Messages.DockerToolInstaller_downloading_docker_client_("1.10.0")));
// Next time we do not need to download:
baos.reset();
assertEquals(exe10.getRemote(), DockerTool.getExecutable("1.10.0", slave, l, null));
assertTrue(exe10.exists());
assertThat(baos.toString(), not(containsString(Messages.DockerToolInstaller_downloading_docker_client_("1.10.0"))));
// Download latest for the first time:
baos.reset();
FilePath exeLatest = toolDir.child("latest/bin/docker");
assertEquals(exeLatest.getRemote(), DockerTool.getExecutable("latest", slave, l, null));
assertTrue(exeLatest.exists());
assertThat(baos.toString(), containsString(Messages.DockerToolInstaller_downloading_docker_client_("latest")));

FilePath exe = toolDir.child(version+"/bin/docker");
// Download for first time:
assertEquals(exe.getRemote(), DockerTool.getExecutable(version, slave, l, null));
assertTrue(exe.exists());
assertThat(baos.toString(), containsString(Messages.DockerToolInstaller_downloading_docker_client_(version)));
// Next time we do not need to download:
baos.reset();
assertEquals(exeLatest.getRemote(), DockerTool.getExecutable("latest", slave, l, null));
assertTrue(exeLatest.exists());
assertThat(baos.toString(), not(containsString(Messages.DockerToolInstaller_downloading_docker_client_("latest"))));
assertThat("we do not have any extra files in here", toolDir.list("**"), arrayContainingInAnyOrder(exe10, toolDir.child("1.10.0/.timestamp"), exeLatest, toolDir.child("latest/.timestamp")));
assertEquals(exe.getRemote(), DockerTool.getExecutable(version, slave, l, null));
assertTrue(exe.exists());
assertThat(baos.toString(), not(containsString(Messages.DockerToolInstaller_downloading_docker_client_(version))));
return exe;
}

}

0 comments on commit 00a18c2

Please sign in to comment.