@Override protected void waitUntilReady() { try { Unreliables.retryUntilTrue((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, waitStrategyTarget::isHealthy); } catch (TimeoutException e) { throw new ContainerLaunchException("Timed out waiting for container to become healthy"); } } }
protected void doStart() { try { configure(); logger().debug("Starting container: {}", getDockerImageName()); logger().debug("Trying to start container: {}", image.get()); AtomicInteger attempt = new AtomicInteger(0); Unreliables.retryUntilSuccess(startupAttempts, () -> { logger().debug("Trying to start container: {} (attempt {}/{})", image.get(), attempt.incrementAndGet(), startupAttempts); tryStart(); return true; }); } catch (Exception e) { throw new ContainerLaunchException("Container startup failed", e); } }
throw new ContainerLaunchException(String.format( "Timed out waiting for URL to be accessible (%s should return HTTP %s)", uri, statusCodes.isEmpty() ? HttpURLConnection.HTTP_OK : statusCodes));
@Override protected void waitUntilReady() { WaitingConsumer waitingConsumer = new WaitingConsumer(); LogUtils.followOutput(DockerClientFactory.instance().client(), waitStrategyTarget.getContainerId(), waitingConsumer); Predicate<OutputFrame> waitPredicate = outputFrame -> // (?s) enables line terminator matching (equivalent to Pattern.DOTALL) outputFrame.getUtf8String().matches("(?s)" + regEx); try { waitingConsumer.waitUntil(waitPredicate, startupTimeout.getSeconds(), TimeUnit.SECONDS, times); } catch (TimeoutException e) { throw new ContainerLaunchException("Timed out waiting for log output matching '" + regEx + "'"); } }
throw new ContainerLaunchException("Local Docker Compose not found. Is " + COMPOSE_EXECUTABLE + " on the PATH?"); throw new ContainerLaunchException("Local Docker Compose exited abnormally with code " + e.getExitValue() + " whilst running command: " + cmd); throw new ContainerLaunchException("Error running local Docker Compose command: " + cmd, e);
@Override protected void waitUntilReady() { // execute select version query until success or timeout try { retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { getRateLimiter().doWhenReady(() -> { try (DatabaseDelegate databaseDelegate = getDatabaseDelegate()) { databaseDelegate.execute(SELECT_VERSION_QUERY, "", 1, false, false); } }); return true; }); } catch (TimeoutException e) { throw new ContainerLaunchException(TIMEOUT_ERROR); } }
@Override protected void waitUntilContainerStarted() { // Repeatedly try and open a connection to the DB and execute a test query logger().info("Waiting for database connection to become available at {} using query '{}'", getJdbcUrl(), getTestQueryString()); Unreliables.retryUntilSuccess(getStartupTimeoutSeconds(), TimeUnit.SECONDS, () -> { if (!isRunning()) { throw new ContainerLaunchException("Container failed to start"); } try (Connection connection = createConnection("")) { boolean success = connection.createStatement().execute(JdbcDatabaseContainer.this.getTestQueryString()); if (success) { logger().info("Obtained a connection to container ({})", JdbcDatabaseContainer.this.getJdbcUrl()); return null; } else { throw new SQLException("Failed to execute test query"); } } }); }
@Override protected void waitUntilReady() { log.info("Waiting for {} seconds for QUERY service", startupTimeout.getSeconds()); // try to connect to the URL try { retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { getRateLimiter().doWhenReady(() -> { GetClusterConfigResponse clusterConfig = bucket.core() .<GetClusterConfigResponse>send(new GetClusterConfigRequest()) .toBlocking().single(); boolean queryServiceEnabled = clusterConfig.config() .bucketConfig(bucket.name()) .serviceEnabled(ServiceType.QUERY); if (!queryServiceEnabled) { throw new ContainerLaunchException("Query service not ready yet"); } }); return true; }); } catch (TimeoutException e) { throw new ContainerLaunchException("Timed out waiting for QUERY service"); } } }
@Override protected void waitUntilReady() { try { Unreliables.retryUntilTrue((int) startupTimeout.toMillis(), TimeUnit.MILLISECONDS, () -> { CountDownLatch latch = new CountDownLatch(1); FrameConsumerResultCallback callback = new FrameConsumerResultCallback() { @Override public void onNext(Frame frame) { if (frame != null && new String(frame.getPayload()).contains("Connected")) { latch.countDown(); } } }; try ( Closeable __ = dockerClient.logContainerCmd(containerId) .withFollowStream(true) .withSince(0) .withStdErr(true) .exec(callback) ) { return latch.await(1, TimeUnit.SECONDS); } }); } catch (TimeoutException e) { throw new ContainerLaunchException("Timed out waiting for log output", e); } } });
@Override protected void waitUntilReady() { final Set<Integer> externalLivenessCheckPorts = getLivenessCheckPorts(); if (externalLivenessCheckPorts.isEmpty()) { log.debug("Liveness check ports of {} is empty. Not waiting.", waitStrategyTarget.getContainerInfo().getName()); return; } @SuppressWarnings("unchecked") List<Integer> exposedPorts = waitStrategyTarget.getExposedPorts(); final Set<Integer> internalPorts = getInternalPorts(externalLivenessCheckPorts, exposedPorts); Callable<Boolean> internalCheck = new InternalCommandPortListeningCheck(waitStrategyTarget, internalPorts); Callable<Boolean> externalCheck = new ExternalPortListeningCheck(waitStrategyTarget, externalLivenessCheckPorts); try { Unreliables.retryUntilTrue((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> getRateLimiter().getWhenReady(() -> internalCheck.call() && externalCheck.call())); } catch (TimeoutException e) { throw new ContainerLaunchException("Timed out waiting for container port to open (" + waitStrategyTarget.getContainerIpAddress() + " ports: " + externalLivenessCheckPorts + " should be listening)"); } }
@Override protected void configure() { optionallyMapResourceParameterAsVolume(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME, "/etc/mysql/conf.d", "mariadb-default-conf"); addExposedPort(MARIADB_PORT); addEnv("MYSQL_DATABASE", databaseName); addEnv("MYSQL_USER", username); if (password != null && !password.isEmpty()) { addEnv("MYSQL_PASSWORD", password); addEnv("MYSQL_ROOT_PASSWORD", password); } else if (MARIADB_ROOT_USER.equalsIgnoreCase(username)) { addEnv("MYSQL_ALLOW_EMPTY_PASSWORD", "yes"); } else { throw new ContainerLaunchException("Empty password can be used only with the root user"); } setStartupAttempts(3); }
throw new ContainerLaunchException("Aborting attempt to link to container " + linkableContainer.getContainerName() + " as it is not running");
@Override protected void configure() { optionallyMapResourceParameterAsVolume(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME, "/etc/mysql/conf.d", "mysql-default-conf"); addExposedPort(MYSQL_PORT); addEnv("MYSQL_DATABASE", databaseName); addEnv("MYSQL_USER", username); if (password != null && !password.isEmpty()) { addEnv("MYSQL_PASSWORD", password); addEnv("MYSQL_ROOT_PASSWORD", password); } else if (MYSQL_ROOT_USER.equalsIgnoreCase(username)) { addEnv("MYSQL_ALLOW_EMPTY_PASSWORD", "yes"); } else { throw new ContainerLaunchException("Empty password can be used only with the root user"); } setStartupAttempts(3); }
@Override public void invoke() { super.start(); this.followOutput(new Slf4jLogConsumer(logger())); // wait for the compose container to stop, which should only happen after it has spawned all the service containers logger().info("Docker Compose container is running for command: {}", Joiner.on(" ").join(this.getCommandParts())); while (this.isRunning()) { logger().trace("Compose container is still running"); Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS); } logger().info("Docker Compose has finished running"); AuditLogger.doComposeLog(this.getCommandParts(), this.getEnv()); final Integer exitCode = this.dockerClient.inspectContainerCmd(containerId) .exec() .getState() .getExitCode(); if (exitCode == null || exitCode != 0) { throw new ContainerLaunchException( "Containerised Docker Compose exited abnormally with code " + exitCode + " whilst running command: " + StringUtils.join(this.getCommandParts(), ' ')); } } }
throw new ContainerLaunchException("Could not create/start container", e);
private static Path createDataDirectory(String name) { try { return Files.createTempDirectory("jetcd_test_" + name + "_"); } catch (IOException e) { throw new ContainerLaunchException("Error creating data directory", e); } }
private static Path createDataDirectory(String name) { try { return Files.createTempDirectory("jetcd_test_" + name + "_"); } catch (IOException e) { throw new ContainerLaunchException("Error creating data directory", e); } }
private static Path createDataDirectory(String name) { try { return Files.createTempDirectory("jetcd_test_" + name + "_"); } catch (IOException e) { throw new ContainerLaunchException("Error creating data directory", e); } }
private void setDataDirectoryPermissions(String permissions) { try { this.container.execInContainer("chmod", permissions, "-R", ETCD_DATA_DIR); } catch (Exception e) { throw new ContainerLaunchException("Error changing permission to etcd data directory", e); } }
private void setDataDirectoryPermissions(String permissions) { try { this.container.execInContainer("chmod", permissions, "-R", ETCD_DATA_DIR); } catch (Exception e) { throw new ContainerLaunchException("Error changing permission to etcd data directory", e); } }