private Docker docker() { return new Docker(this.dockerExecutable()); }
private void removeContainers(Collection<String> containerNames) throws IOException, InterruptedException { try { docker.rm(containerNames); } catch (DockerExecutionException e) { // there are cases such as in CircleCI where 'docker rm' returns a non-0 exit code and "fails", // but container is still effectively removed as far as conflict resolution is concerned. Because // of this, be permissive and do not fail task even if 'rm' fails. log.debug("docker rm failed, but continuing execution", e); } }
private static void removeNetworks(DockerCompose dockerCompose, Docker docker) throws IOException, InterruptedException { dockerCompose.down(); docker.pruneNetworks(); } }
public static Version version() throws IOException, InterruptedException { return new Docker(DockerExecutable.builder().dockerConfiguration(DockerMachine.localMachine().build()).build()) .configuredVersion(); }
@Test public void call_docker_network_ls() throws IOException, InterruptedException { String lsOutput = "0.0.0.0:7000->7000/tcp"; when(executedProcess.getInputStream()).thenReturn(toInputStream(lsOutput)); assertThat(docker.listNetworks(), is(lsOutput)); verify(executor).execute("network", "ls"); }
public State state() throws IOException, InterruptedException { String id = dockerCompose.id(this).orElse(null); if (id == null) { return State.DOWN; } return docker.state(id); }
@Test public void understand_old_version_format() throws IOException, InterruptedException { when(executedProcess.getInputStream()).thenReturn(toInputStream("Docker version 1.7.2")); Version version = docker.configuredVersion(); assertThat(version, is(Version.valueOf("1.7.2"))); }
public void dockerComposeRuleWaitsUntilHealthcheckPasses() throws ExecutionException, IOException, InterruptedException, TimeoutException { assumeThat("docker version", Docker.version(), new GreaterOrEqual<>(Version.forIntegers(1, 12, 0))); assumeThat("docker-compose version", DockerCompose.version(), new GreaterOrEqual<>(Version.forIntegers(1, 10, 0)));
@Test public void clean_up_created_networks_when_shutting_down() throws Exception { Set<String> networksBeforeRun = parseLinesFromOutputString(rule.docker().listNetworks()); rule.before(); assertThat(parseLinesFromOutputString(rule.docker().listNetworks()), is(not(networksBeforeRun))); rule.after(); assertThat(parseLinesFromOutputString(rule.docker().listNetworks()), is(networksBeforeRun)); }
@SuppressWarnings("unchecked") @Test public void be_able_to_save_logs_to_a_directory_while_containers_are_running() throws IOException, InterruptedException { File logLocation = logFolder.newFolder(); DockerComposeRule loggingComposition = DockerComposeRule.builder() .docker(mockDocker) .dockerCompose(dockerCompose) .files(mockFiles) .machine(machine) .saveLogsTo(logLocation.getAbsolutePath()) .build(); when(dockerCompose.services()).thenReturn(ImmutableList.of("db")); when(dockerCompose.id(any())).thenReturn(Optional.of("abcde")); when(mockDocker.state("abcde")).thenReturn(State.HEALTHY); CountDownLatch latch = new CountDownLatch(1); when(dockerCompose.writeLogs(eq("db"), any(OutputStream.class))).thenAnswer(args -> { OutputStream outputStream = (OutputStream) args.getArguments()[1]; IOUtils.write("db log", outputStream); latch.countDown(); return true; }); loggingComposition.before(); assertThat(latch.await(1, TimeUnit.SECONDS), is(true)); loggingComposition.after(); assertThat(logLocation.listFiles(), arrayContaining(fileWithName("db.log"))); assertThat(new File(logLocation, "db.log"), is(fileContainingString("db log"))); }
@Test public void understand_new_version_format() throws IOException, InterruptedException { when(executedProcess.getInputStream()).thenReturn(toInputStream("Docker version 17.03.1-ce")); Version version = docker.configuredVersion(); assertThat(version, is(Version.valueOf("17.3.1"))); } }
/** * This test is not currently enabled in Circle as it does not provide a sufficiently recent version of docker-compose. * * @see <a href="https://github.com/palantir/docker-compose-rule/issues/156">Issue #156</a> */ @Test public void testStateChanges_withHealthCheck() throws IOException, InterruptedException { assumeThat("docker version", Docker.version(), new GreaterOrEqual<>(Version.forIntegers(1, 12, 0))); assumeThat("docker-compose version", DockerCompose.version(), new GreaterOrEqual<>(Version.forIntegers(1, 10, 0))); DockerCompose dockerCompose = new DefaultDockerCompose( DockerComposeFiles.from("src/test/resources/native-healthcheck.yaml"), dockerMachine, ProjectName.random()); // The withHealthcheck service's healthcheck checks every 100ms whether the file "healthy" exists Container container = new Container("withHealthcheck", docker, dockerCompose); assertEquals(State.DOWN, container.state()); container.up(); assertEquals(State.UNHEALTHY, container.state()); dockerCompose.exec(noOptions(), "withHealthcheck", arguments("touch", "healthy")); wait.until(container::state, equalTo(State.HEALTHY)); dockerCompose.exec(noOptions(), "withHealthcheck", arguments("rm", "healthy")); wait.until(container::state, equalTo(State.UNHEALTHY)); container.kill(); assertEquals(State.DOWN, container.state()); } }
private void removeContainers(Collection<String> containerNames) throws IOException, InterruptedException { try { docker.rm(containerNames); } catch (DockerExecutionException e) { // there are cases such as in CircleCI where 'docker rm' returns a non-0 exit code and "fails", // but container is still effectively removed as far as conflict resolution is concerned. Because // of this, be permissive and do not fail task even if 'rm' fails. log.debug("docker rm failed, but continuing execution", e); } }
private Docker docker(ExtensionContext.Store store, Compose compose) { return getOrBuild(Docker.class, store, compose, () -> { DockerExecutable dockerExecutable = dockerExecutable(store, compose); return new Docker(dockerExecutable); }); }
@Override public void shutdown(DockerCompose dockerCompose, Docker docker) throws IOException, InterruptedException { log.debug("Killing docker-compose cluster"); dockerCompose.kill(); log.debug("Downing docker-compose cluster"); dockerCompose.down(); log.debug("docker-compose cluster killed"); docker.pruneNetworks(); log.debug("Networks pruned"); } }
private void removeContainers(Collection<String> containerNames) throws IOException, InterruptedException { try { docker.rm(containerNames); } catch (DockerExecutionException e) { // there are cases such as in CircleCI where 'docker rm' returns a non-0 exit code and "fails", // but container is still effectively removed as far as conflict resolution is concerned. Because // of this, be permissive and do not fail task even if 'rm' fails. log.debug("docker rm failed, but continuing execution", e); } }
@Value.Default public Docker docker() { return new Docker(dockerExecutable()); }
@Override public void shutdown(DockerCompose dockerCompose, Docker docker) throws IOException, InterruptedException { List<ContainerName> runningContainers = dockerCompose.ps(); log.info("Shutting down {}", runningContainers.stream().map(ContainerName::semanticName).collect(toList())); if (removeContainersCatchingErrors(docker, runningContainers)) { return; } log.debug("First shutdown attempted failed due to btrfs volume error... retrying"); if (removeContainersCatchingErrors(docker, runningContainers)) { return; } log.warn("Couldn't shut down containers due to btrfs volume error, " + "see https://circleci.com/docs/docker-btrfs-error/ for more info."); log.info("Pruning networks"); docker.pruneNetworks(); }
public void rm(Collection<String> containerNames) throws IOException, InterruptedException { rm(containerNames.toArray(new String[containerNames.size()])); }
@Value.Default public Docker docker() { return new Docker(dockerExecutable()); }