@Test public void call_up_only_once_if_successful() throws IOException, InterruptedException { ConflictingContainerRemovingDockerCompose conflictingContainerRemovingDockerCompose = new ConflictingContainerRemovingDockerCompose(dockerCompose, docker); conflictingContainerRemovingDockerCompose.up(); verify(dockerCompose, times(1)).up(); verifyZeroInteractions(docker); }
@Override public void up() throws IOException, InterruptedException { for (int currRetryAttempt = 0; currRetryAttempt <= retryAttempts; currRetryAttempt++) { try { getDockerCompose().up(); return; } catch (DockerExecutionException e) { Set<String> conflictingContainerNames = getConflictingContainerNames(e.getMessage()); if (conflictingContainerNames.isEmpty()) { // failed due to reason other than conflicting containers, so re-throw throw e; } log.debug("docker-compose up failed due to container name conflicts (container names: {}). " + "Removing containers and attempting docker-compose up again (attempt {}).", conflictingContainerNames, currRetryAttempt + 1); removeContainers(conflictingContainerNames); } } throw new DockerExecutionException("docker-compose up failed"); }
@Test public void parse_container_names_from_error_message_since_v13() { String conflictingContainer = "conflictingContainer"; ConflictingContainerRemovingDockerCompose conflictingContainerRemovingDockerCompose = new ConflictingContainerRemovingDockerCompose(dockerCompose, docker); Set<String> conflictingContainerNames = conflictingContainerRemovingDockerCompose .getConflictingContainerNames("The container name \"" + conflictingContainer + "\" is already in use"); assertEquals(ImmutableSet.of(conflictingContainer), conflictingContainerNames); }
@Override public void before() throws IOException, InterruptedException { log.debug("Starting docker-compose cluster"); dockerCompose().build(); DockerCompose upDockerCompose = dockerCompose(); if (removeConflictingContainersOnStartup()) { upDockerCompose = new ConflictingContainerRemovingDockerCompose(upDockerCompose, docker()); } upDockerCompose.up(); logCollector().startCollecting(dockerCompose()); log.debug("Waiting for services"); clusterWaits().forEach(clusterWait -> clusterWait.waitUntilReady(containers())); log.debug("docker-compose cluster started"); }
@Test public void parse_container_names_from_error_message() { String conflictingContainer = "conflictingContainer"; ConflictingContainerRemovingDockerCompose conflictingContainerRemovingDockerCompose = new ConflictingContainerRemovingDockerCompose(dockerCompose, docker); Set<String> conflictingContainerNames = conflictingContainerRemovingDockerCompose .getConflictingContainerNames("The name \"" + conflictingContainer + "\" is already in use"); assertEquals(ImmutableSet.of(conflictingContainer), conflictingContainerNames); }
@Override public void before() throws IOException, InterruptedException { log.debug("Starting docker-compose cluster"); dockerCompose().build(); DockerCompose upDockerCompose = dockerCompose(); if (removeConflictingContainersOnStartup()) { upDockerCompose = new ConflictingContainerRemovingDockerCompose(upDockerCompose, docker()); } upDockerCompose.up(); logCollector().startCollecting(dockerCompose()); log.debug("Waiting for services"); clusterWaits().forEach(clusterWait -> clusterWait.waitUntilReady(containers())); log.debug("docker-compose cluster started"); }
@Override public void up() throws IOException, InterruptedException { for (int currRetryAttempt = 0; currRetryAttempt <= retryAttempts; currRetryAttempt++) { try { getDockerCompose().up(); return; } catch (DockerExecutionException e) { Set<String> conflictingContainerNames = getConflictingContainerNames(e.getMessage()); if (conflictingContainerNames.isEmpty()) { // failed due to reason other than conflicting containers, so re-throw throw e; } log.debug("docker-compose up failed due to container name conflicts (container names: {}). " + "Removing containers and attempting docker-compose up again (attempt {}).", conflictingContainerNames, currRetryAttempt + 1); removeContainers(conflictingContainerNames); } } throw new DockerExecutionException("docker-compose up failed"); }
@Test public void call_rm_and_retry_up_if_conflicting_containers_exist() throws IOException, InterruptedException { String conflictingContainer = "conflictingContainer"; doThrow(new DockerExecutionException("The name \"" + conflictingContainer + "\" is already in use")) .doNothing() .when(dockerCompose).up(); ConflictingContainerRemovingDockerCompose conflictingContainerRemovingDockerCompose = new ConflictingContainerRemovingDockerCompose(dockerCompose, docker); conflictingContainerRemovingDockerCompose.up(); verify(dockerCompose, times(2)).up(); verify(docker).rm(ImmutableSet.of(conflictingContainer)); }
@Test public void require_retry_attempts_to_be_at_least_1() { exception.expect(IllegalArgumentException.class); exception.expectMessage("retryAttempts must be at least 1, was 0"); new ConflictingContainerRemovingDockerCompose(dockerCompose, docker, 0); }
@Override public void up() throws IOException, InterruptedException { for (int currRetryAttempt = 0; currRetryAttempt <= retryAttempts; currRetryAttempt++) { try { getDockerCompose().up(); return; } catch (DockerExecutionException e) { Set<String> conflictingContainerNames = getConflictingContainerNames(e.getMessage()); if (conflictingContainerNames.isEmpty()) { // failed due to reason other than conflicting containers, so re-throw throw e; } log.debug("docker-compose up failed due to container name conflicts (container names: {}). " + "Removing containers and attempting docker-compose up again (attempt {}).", conflictingContainerNames, currRetryAttempt + 1); removeContainers(conflictingContainerNames); } } throw new DockerExecutionException("docker-compose up failed"); }
@Test public void throw_exception_if_retry_attempts_exceeded() throws IOException, InterruptedException { String conflictingContainer = "conflictingContainer"; doThrow(new DockerExecutionException("The name \"" + conflictingContainer + "\" is already in use")) .when(dockerCompose).up(); exception.expect(DockerExecutionException.class); exception.expectMessage("docker-compose up failed"); ConflictingContainerRemovingDockerCompose conflictingContainerRemovingDockerCompose = new ConflictingContainerRemovingDockerCompose(dockerCompose, docker); conflictingContainerRemovingDockerCompose.up(); }
@Override public void before() throws IOException, InterruptedException { log.debug("Starting docker-compose cluster"); if (pullOnStartup()) { dockerCompose().pull(); } dockerCompose().build(); DockerCompose upDockerCompose = dockerCompose(); if (removeConflictingContainersOnStartup()) { upDockerCompose = new ConflictingContainerRemovingDockerCompose(upDockerCompose, docker()); } upDockerCompose.up(); logCollector().startCollecting(dockerCompose()); log.debug("Waiting for services"); new ClusterWait(ClusterHealthCheck.nativeHealthChecks(), nativeServiceHealthCheckTimeout()) .waitUntilReady(containers()); clusterWaits().forEach(clusterWait -> clusterWait.waitUntilReady(containers())); log.debug("docker-compose cluster started"); }
@Test public void ignore_docker_execution_exceptions_in_rm() throws IOException, InterruptedException { String conflictingContainer = "conflictingContainer"; doThrow(new DockerExecutionException("The name \"" + conflictingContainer + "\" is already in use")) .doNothing() .when(dockerCompose).up(); doThrow(DockerExecutionException.class).when(docker).rm(anySetOf(String.class)); ConflictingContainerRemovingDockerCompose conflictingContainerRemovingDockerCompose = new ConflictingContainerRemovingDockerCompose(dockerCompose, docker); conflictingContainerRemovingDockerCompose.up(); verify(dockerCompose, times(2)).up(); verify(docker).rm(ImmutableSet.of(conflictingContainer)); }
@Test public void retry_specified_number_of_times() throws IOException, InterruptedException { String conflictingContainer = "conflictingContainer"; DockerExecutionException dockerException = new DockerExecutionException( "The name \"" + conflictingContainer + "\" is already in use"); doThrow(dockerException) .doThrow(dockerException) .doNothing() .when(dockerCompose).up(); ConflictingContainerRemovingDockerCompose conflictingContainerRemovingDockerCompose = new ConflictingContainerRemovingDockerCompose(dockerCompose, docker, 3); conflictingContainerRemovingDockerCompose.up(); verify(dockerCompose, times(3)).up(); verify(docker, times(2)).rm(ImmutableSet.of(conflictingContainer)); }
@Test public void fail_on_non_docker_execution_exceptions_in_rm() throws IOException, InterruptedException { String conflictingContainer = "conflictingContainer"; doThrow(new DockerExecutionException("The name \"" + conflictingContainer + "\" is already in use")) .doNothing() .when(dockerCompose).up(); doThrow(RuntimeException.class).when(docker).rm(anySetOf(String.class)); exception.expect(RuntimeException.class); ConflictingContainerRemovingDockerCompose conflictingContainerRemovingDockerCompose = new ConflictingContainerRemovingDockerCompose(dockerCompose, docker); conflictingContainerRemovingDockerCompose.up(); }