Skip to content

Commit

Permalink
Merge branch 'master' into composev2
Browse files Browse the repository at this point in the history
  • Loading branch information
eddumelendez committed Jul 29, 2022
2 parents 2cdfb5c + 0b374b3 commit deb5f2b
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 20 deletions.
3 changes: 3 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"area/docker-compose":
- core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java
- core/src/main/java/org/testcontainers/containers/DockerComposeFiles.java
"github_actions":
- .github/workflows/*
"gradle-wrapper":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ public class DockerComposeContainer<SELF extends DockerComposeContainer<SELF>>

private final Map<String, WaitAllStrategy> waitStrategyMap = new ConcurrentHashMap<>();

private Duration startupTimeout = Duration.ofMinutes(30);

private final SocatContainer ambassadorContainer = new SocatContainer();

private final Map<String, List<Consumer<OutputFrame>>> logConsumers = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -475,14 +477,15 @@ private String getServiceInstanceName(String serviceName) {
/*
* can have multiple wait strategies for a single container, e.g. if waiting on several ports
* if no wait strategy is defined, the WaitAllStrategy will return immediately.
* The WaitAllStrategy uses a long timeout, because timeouts should be handled by the inner strategies.
* The WaitAllStrategy uses the startup timeout for everything as a global maximum,
* but we expect timeouts to be handled by the inner strategies.
*/
private void addWaitStrategy(String serviceInstanceName, @NonNull WaitStrategy waitStrategy) {
final WaitAllStrategy waitAllStrategy = waitStrategyMap.computeIfAbsent(
serviceInstanceName,
__ -> {
return new WaitAllStrategy(WaitAllStrategy.Mode.WITH_MAXIMUM_OUTER_TIMEOUT)
.withStartupTimeout(Duration.ofMinutes(30));
.withStartupTimeout(startupTimeout);
}
);
waitAllStrategy.withStrategy(waitStrategy);
Expand Down Expand Up @@ -652,6 +655,16 @@ public SELF withRemoveImages(RemoveImages removeImages) {
return self();
}

/**
* Set the maximum startup timeout all the waits set are bounded to.
*
* @return this instance. for chaining
*/
public SELF withStartupTimeout(Duration startupTimeout) {
this.startupTimeout = startupTimeout;
return self();
}

public Optional<ContainerState> getContainerByServiceName(String serviceName) {
return Optional.ofNullable(serviceInstanceMap.get(serviceName));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,11 @@ public boolean test(DockerClientProviderStrategy dockerClientProviderStrategy) {
.findFirst()
.orElseThrow(() -> {
log.error(
"Could not find a valid Docker environment. Please check configuration. Attempted configurations were:"
"Could not find a valid Docker environment. Please check configuration. Attempted configurations were:\n" +
configurationFailures.stream().map(it -> "\t" + it).collect(Collectors.joining("\n")) +
"As no valid configuration was found, execution cannot continue.\n" +
"See https://www.testcontainers.org/on_failure.html for more details."
);
for (String failureMessage : configurationFailures) {
log.error(" " + failureMessage);
}
log.error("As no valid configuration was found, execution cannot continue");

FAIL_FAST_ALWAYS.set(true);
return new IllegalStateException(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package org.testcontainers.containers;

import org.junit.Test;
import org.testcontainers.containers.wait.strategy.Wait;

import java.io.File;
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals;
import static org.rnorth.visibleassertions.VisibleAssertions.assertThrows;

public class DockerComposeContainerWithServicesTest {

Expand Down Expand Up @@ -87,6 +90,28 @@ public void testScaleInComposeFileIsRespected() {
}
}

@Test
public void testStartupTimeoutSetsTheHighestTimeout() {
assertThrows(
"We expect a timeout from the startup timeout",
org.rnorth.ducttape.TimeoutException.class,
() -> {
try (
DockerComposeContainer<?> compose = new DockerComposeContainer<>(SIMPLE_COMPOSE_FILE)
.withServices("redis")
.withStartupTimeout(Duration.ofMillis(1))
.withExposedService(
"redis",
80,
Wait.forListeningPort().withStartupTimeout(Duration.ofMinutes(1))
);
) {
compose.start();
}
}
);
}

private void verifyStartedContainers(final DockerComposeContainer<?> compose, final String... names) {
final List<String> containerNames = compose
.listChildContainers()
Expand Down
1 change: 1 addition & 0 deletions docs/_redirects
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
/usage/database_containers.html /modules/databases/
/usage/neo4j_container.html /modules/databases/neo4j/
/compatibility.html /supported_docker_environment/
/on_failure.html /supported_docker_environment/

# No great 1:1 mapping exists for the following, so redirect to somewhere where at least a sensible sidebar will be shown

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# AWS CodeBuild

To enable access to Docker in AWS CodeBuild, go to `Privileged` section and check
`Enable this flag if you want to build Docker images or want your builds to get elevated privileges`.

This is a sample `buildspec.yml` config:

```yaml
version: 0.2

phases:
install:
runtime-versions:
java: corretto17
build:
commands:
- ./mvnw test
```
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
# CircleCI 2.0
# CircleCI (Cloud, Server v2.x, and Server v3.x)

Your CircleCI configuration should use a dedicated VM for testcontainers to work. You can achieve this by specifying the
executor type in your `.circleci/config.yml` to be `machine` instead of the default `docker` executor ( see [Choosing an Executor Type](https://circleci.com/docs/2.0/executor-types/) for more info ).
Your CircleCI configuration should use a dedicated VM for Testcontainers to work. You can achieve this by specifying the
executor type in your `.circleci/config.yml` to be `machine` instead of the default `docker` executor (see [Choosing an Executor Type](https://circleci.com/docs/2.0/executor-types/) for more info).

Here is a sample CircleCI configuration that does a checkout of a project and runs maven:
Here is a sample CircleCI configuration that does a checkout of a project and runs Maven:

```yml
# Check https://circleci.com/docs/2.0/language-java/ for more details
#
version: 2
machine: true
jobs:
build:
# Check https://circleci.com/docs/executor-intro#linux-vm for more details
machine: true
steps:
- checkout

- run: mvn -B clean install
```
94 changes: 94 additions & 0 deletions docs/supported_docker_environment/continuous_integration/tekton.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Tekton

o enable access to Docker in Tekton, a dind sidecar needs to be added. An example of it can be found
[here](https://github.com/tektoncd/pipeline/blob/main/examples/v1beta1/taskruns/dind-sidecar.yaml)

This is an example

```yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: run-tests
description: Run Tests
spec:
workspaces:
- name: source
steps:
- name: read
image: eclipse-temurin:17.0.3_7-jdk-alpine
workingDir: $(workspaces.source.path)
script: ./mvnw test
volumeMounts:
- mountPath: /var/run/
name: dind-socket
sidecars:
- image: docker:20.10-dind
name: docker
securityContext:
privileged: true
volumeMounts:
- mountPath: /var/lib/docker
name: dind-storage
- mountPath: /var/run/
name: dind-socket
volumes:
- name: dind-storage
emptyDir: { }
- name: dind-socket
emptyDir: { }
---
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: testcontainers-demo
spec:
description: |
This pipeline clones a git repo, run testcontainers.
params:
- name: repo-url
type: string
description: The git repo URL to clone from.
workspaces:
- name: shared-data
description: |
This workspace contains the cloned repo files, so they can be read by the
next task.
tasks:
- name: fetch-source
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-data
params:
- name: url
value: $(params.repo-url)
- name: run-tests
runAfter: ["fetch-source"]
taskRef:
name: run-tests
workspaces:
- name: source
workspace: shared-data
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: testcontainers-demo-run
spec:
pipelineRef:
name: testcontainers-demo
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
params:
- name: repo-url
value: https://github.com/testcontainers/testcontainers-java-repro.git
```
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,13 @@ nav:
- System Requirements:
- supported_docker_environment/index.md
- Continuous Integration:
- supported_docker_environment/continuous_integration/aws_codebuild.md
- supported_docker_environment/continuous_integration/dind_patterns.md
- supported_docker_environment/continuous_integration/circle_ci.md
- supported_docker_environment/continuous_integration/drone.md
- supported_docker_environment/continuous_integration/gitlab_ci.md
- supported_docker_environment/continuous_integration/bitbucket_pipelines.md
- supported_docker_environment/continuous_integration/tekton.md
- supported_docker_environment/windows.md
- supported_docker_environment/logging_config.md
- supported_docker_environment/image_registry_rate_limiting.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ protected void setupCommandAndEnv() {

withCommand("/bin/bash", "-c", standaloneBaseCommand);

final String clusterName = getEnvMap().getOrDefault("PULSAR_PREFIX_clusterName", "standalone");
final String response = String.format("[\"%s\"]", clusterName);

List<WaitStrategy> waitStrategies = new ArrayList<>();
waitStrategies.add(Wait.defaultWaitStrategy());
waitStrategies.add(
Wait
.forHttp(ADMIN_CLUSTERS_ENDPOINT)
.forPort(BROKER_HTTP_PORT)
.forResponsePredicate("[\"standalone\"]"::equals)
Wait.forHttp(ADMIN_CLUSTERS_ENDPOINT).forPort(BROKER_HTTP_PORT).forResponsePredicate(response::equals)
);
if (transactionsEnabled) {
withEnv("PULSAR_PREFIX_transactionCoordinatorEnabled", "true");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ public void envVarsUsage() throws Exception {
}
}

@Test
public void customClusterName() throws Exception {
try (
PulsarContainer pulsar = new PulsarContainer(PULSAR_IMAGE)
.withEnv("PULSAR_PREFIX_clusterName", "tc-cluster");
) {
pulsar.start();
testPulsarFunctionality(pulsar.getPulsarBrokerUrl());
}
}

@Test
public void shouldNotEnableFunctionsWorkerByDefault() throws Exception {
try (PulsarContainer pulsar = new PulsarContainer(PULSAR_IMAGE)) {
Expand Down

0 comments on commit deb5f2b

Please sign in to comment.