From aacfa303d61847e1951c4ee493722c08dbabcb8f Mon Sep 17 00:00:00 2001 From: Liam Cark Date: Thu, 20 Apr 2017 20:48:30 +0200 Subject: [PATCH] Raise docker client version to easy dev setup on mac os Moved the docker exception to a different package. Reimplemented the MockedLogStream. Move volumes to appropriate spot in new api version The version bump resulted in a bunch of dependency conflicts. Ranging from guava to jackson versions. In the end the solution is the shaded spotify jar, with an updated version of rest easy that excludes a few conflicting dependencies. --- build-server/pom.xml | 27 ++++++++-- .../tudelft/ewi/build/BuildServerModule.java | 2 +- .../ewi/build/builds/BuildManager.java | 8 ++- .../ewi/build/jaxrs/BuildsResource.java | 4 +- .../src/main/resources/config.properties | 1 + .../docker/client/MockedLogStream.java | 44 ++++++++++----- .../ewi/build/builds/BuildManagerTest.java | 53 ++++++++++--------- pom.xml | 27 +++++++--- 8 files changed, 114 insertions(+), 52 deletions(-) diff --git a/build-server/pom.xml b/build-server/pom.xml index 29a0b72..3fec514 100644 --- a/build-server/pom.xml +++ b/build-server/pom.xml @@ -27,13 +27,32 @@ jetty-webapp ${jetty.version} + + + javax.ejb + ejb-api + 3.0 + + + org.jboss.resteasy + resteasy-client + ${resteasy.version} + + + slf4j-simple + org.slf4j + + + + - + - com.spotify - docker-client - 2.7.19 + com.spotify + docker-client + shaded + 8.3.2 org.eclipse.jgit diff --git a/build-server/src/main/java/nl/tudelft/ewi/build/BuildServerModule.java b/build-server/src/main/java/nl/tudelft/ewi/build/BuildServerModule.java index c1638ed..7d44333 100644 --- a/build-server/src/main/java/nl/tudelft/ewi/build/BuildServerModule.java +++ b/build-server/src/main/java/nl/tudelft/ewi/build/BuildServerModule.java @@ -44,7 +44,7 @@ public ObjectMapper get() { }); bind(DockerClient.class).toInstance(DefaultDockerClient.fromEnv() - .readTimeoutMillis(DefaultDockerClient.NO_TIMEOUT) + .readTimeoutMillis(0) .build()); findResourcesWith(Path.class); diff --git a/build-server/src/main/java/nl/tudelft/ewi/build/builds/BuildManager.java b/build-server/src/main/java/nl/tudelft/ewi/build/builds/BuildManager.java index 9004500..5c754e9 100644 --- a/build-server/src/main/java/nl/tudelft/ewi/build/builds/BuildManager.java +++ b/build-server/src/main/java/nl/tudelft/ewi/build/builds/BuildManager.java @@ -9,8 +9,8 @@ import com.google.inject.Singleton; import com.spotify.docker.client.DockerClient; import com.spotify.docker.client.DockerClient.AttachParameter; -import com.spotify.docker.client.DockerException; import com.spotify.docker.client.LogStream; +import com.spotify.docker.client.exceptions.DockerException; import com.spotify.docker.client.messages.ContainerConfig; import com.spotify.docker.client.messages.ContainerCreation; import com.spotify.docker.client.messages.ContainerExit; @@ -268,7 +268,10 @@ public ContainerExit call() throws Exception { BuildInstruction buildInstruction = buildRequest.getInstruction(); buildInstructionInterpreter.runPluginBefores(buildInstruction, stagingDirectory); + final HostConfig hostConfig = HostConfig.builder().binds(volume).build(); + ContainerConfig.Builder configBuilder = ContainerConfig.builder() + .hostConfig(hostConfig) .image(buildInstructionInterpreter.getImage(buildInstruction)) .cmd(buildInstructionInterpreter.getCommand(buildInstruction).split(" ")) .user(config.getDockerUser()) @@ -283,7 +286,8 @@ public ContainerExit call() throws Exception { id = creation.id(); containerId.set(id); log.info("Starting container {}", id); - dockerClient.startContainer(id, HostConfig.builder().binds(volume).build()); + dockerClient.startContainer(id); + } catch (DockerException | InterruptedException e) { logger.println("[FATAL] Failed to provision build environment"); diff --git a/build-server/src/main/java/nl/tudelft/ewi/build/jaxrs/BuildsResource.java b/build-server/src/main/java/nl/tudelft/ewi/build/jaxrs/BuildsResource.java index 4b16dcb..8ae2e5d 100644 --- a/build-server/src/main/java/nl/tudelft/ewi/build/jaxrs/BuildsResource.java +++ b/build-server/src/main/java/nl/tudelft/ewi/build/jaxrs/BuildsResource.java @@ -13,7 +13,6 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation.Builder; import javax.ws.rs.core.MediaType; @@ -21,6 +20,7 @@ import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.StatusType; +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import org.jboss.resteasy.util.Base64; import com.google.common.base.Strings; @@ -72,7 +72,7 @@ public void onSuccess(BuildResult result) { log.info("Returning build results to callback URL: {}", buildRequest.getCallbackUrl()); for (int i = 0; i <= 4; i++) { - Client client = ClientBuilder.newClient(); + Client client = new ResteasyClientBuilder().build(); try { Response response = prepareCallback(client).post( Entity.json(result)); diff --git a/build-server/src/main/resources/config.properties b/build-server/src/main/resources/config.properties index 84ff336..b58d8c9 100644 --- a/build-server/src/main/resources/config.properties +++ b/build-server/src/main/resources/config.properties @@ -2,6 +2,7 @@ authorization.client-id = MichaelLaptop authorization.client-secret = t2hLCXVE docker.max-containers = 3 + docker.staging-directory = /workspace docker.working-directory = /workspace docker.user = root diff --git a/build-server/src/test/java/com/spotify/docker/client/MockedLogStream.java b/build-server/src/test/java/com/spotify/docker/client/MockedLogStream.java index 174b976..e828665 100644 --- a/build-server/src/test/java/com/spotify/docker/client/MockedLogStream.java +++ b/build-server/src/test/java/com/spotify/docker/client/MockedLogStream.java @@ -1,36 +1,54 @@ package com.spotify.docker.client; +import java.io.IOException; +import java.io.OutputStream; import java.util.LinkedList; import java.util.Queue; import org.apache.commons.io.input.NullInputStream; -public class MockedLogStream extends LogStream { +public class MockedLogStream implements LogStream { private final Queue logMessages; public MockedLogStream() { - super(new NullInputStream(0)); this.logMessages = new LinkedList(); } + public void addMessage(final LogMessage message) { + logMessages.add(message); + } @Override - protected LogMessage computeNext() { - if (logMessages.isEmpty()) - return endOfData(); - return logMessages.remove(); + public String readFully() { + return ""; } - public void addMessage(final LogMessage message) { - logMessages.add(message); + @Override + public void attach(OutputStream stdout, OutputStream stderr) throws IOException { + } - + + @Override + public void attach(OutputStream stdout, OutputStream stderr, boolean closeAtEof) throws IOException { + + } + @Override public void close() { - try { - super.close(); - } - catch (Throwable t) {} } + @Override + public boolean hasNext() { + return !logMessages.isEmpty(); + } + + @Override + public LogMessage next() { + return logMessages.remove(); + } + + @Override + public void remove() { + + } } diff --git a/build-server/src/test/java/nl/tudelft/ewi/build/builds/BuildManagerTest.java b/build-server/src/test/java/nl/tudelft/ewi/build/builds/BuildManagerTest.java index a9827d7..6c5654f 100644 --- a/build-server/src/test/java/nl/tudelft/ewi/build/builds/BuildManagerTest.java +++ b/build-server/src/test/java/nl/tudelft/ewi/build/builds/BuildManagerTest.java @@ -4,8 +4,9 @@ import com.google.common.io.Files; import com.spotify.docker.client.DockerClient; import com.spotify.docker.client.DockerClient.AttachParameter; -import com.spotify.docker.client.DockerException; + import com.spotify.docker.client.MockedLogStream; +import com.spotify.docker.client.exceptions.DockerException; import com.spotify.docker.client.messages.ContainerConfig; import com.spotify.docker.client.messages.ContainerCreation; import com.spotify.docker.client.messages.ContainerExit; @@ -56,11 +57,15 @@ public class BuildManagerTest { public static final int CONCURRENT_JOBS = 3; - @Mock private Config config; - @Mock private DockerClient dockerClient; - @InjectMocks private MavenBuildInstructionInterpreter mavenBuildInstructionInterpreter; - @Mock private GitStagingDirectoryPreparer gitStagingDirectoryPreparer; - + @Mock + private Config config; + @Mock + private DockerClient dockerClient; + @InjectMocks + private MavenBuildInstructionInterpreter mavenBuildInstructionInterpreter; + @Mock + private GitStagingDirectoryPreparer gitStagingDirectoryPreparer; + private BuildManager manager; private static File stagingDirectory; @@ -75,18 +80,18 @@ public static void createTempDir() { public void setUp() throws DockerException, InterruptedException { when(config.getMaximumConcurrentJobs()).thenReturn(CONCURRENT_JOBS); when(config.getStagingDirectory()).thenReturn(stagingDirectory.getAbsolutePath()); - + when(dockerClient.createContainer(Mockito.any(ContainerConfig.class), Mockito.anyString())) - .thenReturn(new ContainerCreation(UUID.randomUUID().toString())); + .thenReturn(ContainerCreation.builder().id(UUID.randomUUID().toString()).build()); when(dockerClient.attachContainer(Mockito.anyString(), Mockito.anyVararg())) .thenReturn(new MockedLogStream()); - when(dockerClient.waitContainer(Mockito.anyString())).thenReturn(new ContainerExit(0)); - + when(dockerClient.waitContainer(Mockito.anyString())).thenReturn(ContainerExit.create(0)); + manager = new BuildManager(config, dockerClient, new StagingDirectoryPreparerRegistry(gitStagingDirectoryPreparer), new BuildInstructionInterpreterRegistry(mavenBuildInstructionInterpreter)); } - + @After public void tearDown() { manager.lifeCycleStopping(null); @@ -133,7 +138,7 @@ public void testThatJobCanBeScheduledWhenCapacityIsRestored() throws Interrupted for (int i = 0; i < CONCURRENT_JOBS; i++) { uuid = manager.schedule(createRequest()).getUUID(); } - + assertNotNull(uuid); manager.killBuild(uuid); assertNotNull(manager.schedule(createRequest())); @@ -144,21 +149,21 @@ public void testThatJobCanBeScheduledWhenCapacityIsRestoredThroughTermination() for (int i = 0; i < CONCURRENT_JOBS - 1; i++) { manager.schedule(createRequest()); } - + UUID scheduled = manager.schedule(createRequest()).getUUID(); assertNotNull(scheduled); - + Thread.sleep(100); assertNotNull(scheduled); } - + @Test public void waitForABuild() throws InterruptedException, ExecutionException { Build result = manager.schedule(createRequest()); log.info("Result : {}", result.get()); } - - @Test(timeout=2000) // kill test after 2 seconds + + @Test(timeout = 2000) // kill test after 2 seconds public void testBuildWithTimeout() throws DockerException, InterruptedException, ExecutionException { BuildRequest buildRequest = createRequest(); buildRequest.setTimeout(1); // timeout 1 second @@ -177,7 +182,7 @@ private void setContainerExitDuration(final long duration) throws DockerExceptio public ContainerExit answer(InvocationOnMock invocation) throws Throwable { Thread.sleep(duration); // sleep 20 seconds - return new ContainerExit(0); + return ContainerExit.create(0); } }); @@ -187,7 +192,7 @@ public ContainerExit answer(InvocationOnMock invocation) public void testOldRequestSupport() throws Exception { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModules(new MappingModule()); - try(InputStream in = BuildManagerTest.class.getResourceAsStream("/build-requests/java-maven-old.json")) { + try (InputStream in = BuildManagerTest.class.getResourceAsStream("/build-requests/java-maven-old.json")) { BuildRequest request = objectMapper.readValue(in, BuildRequest.class); Build resultFuture = manager.schedule(request); BuildResult result = resultFuture.get(); @@ -199,24 +204,24 @@ public void testOldRequestSupport() throws Exception { public void testNewRequestSupport() throws Exception { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModules(new MappingModule()); - try(InputStream in = BuildManagerTest.class.getResourceAsStream("/build-requests/java-maven-new.json")) { + try (InputStream in = BuildManagerTest.class.getResourceAsStream("/build-requests/java-maven-new.json")) { BuildRequest request = objectMapper.readValue(in, BuildRequest.class); Build resultFuture = manager.schedule(request); BuildResult result = resultFuture.get(); assertEquals(Status.SUCCEEDED, result.getStatus()); } } - + private BuildRequest createRequest() { GitSource source = new GitSource(); source.setBranchName("master"); source.setRepositoryUrl("https://github.com/devhub-tud/build-server.git"); source.setCommitId("2625eaf9b476dd158ad5f9cad3d5137f3b111ea7"); - + MavenBuildInstruction instruction = new MavenBuildInstruction(); - instruction.setPhases(new String[] { "package" }); + instruction.setPhases(new String[]{"package"}); instruction.setWithDisplay(true); - + BuildRequest request = new BuildRequest(); request.setSource(source); request.setInstruction(instruction); diff --git a/pom.xml b/pom.xml index 3c15014..de1d564 100644 --- a/pom.xml +++ b/pom.xml @@ -7,15 +7,15 @@ pom - 1.7 - 1.7 + 1.8 + 1.8 UTF-8 UTF-8 3.0 4.2.7.Final - 2.3.0 - 3.0.4.Final + 2.6.3 + 3.0.19.Final 1.7.5 @@ -48,7 +48,22 @@ org.jboss.resteasy resteasy-hibernatevalidator-provider ${resteasy.version} + + + + org.jboss.weld.se + weld-se + + + + + + javax.enterprise + cdi-api + 1.2 + + com.fasterxml.jackson.datatype jackson-datatype-guava @@ -103,7 +118,7 @@ org.reflections reflections - 0.9.8 + 0.9.9 org.projectlombok @@ -113,7 +128,7 @@ com.google.guava guava - 15.0 + 18.0