Skip to content

Commit 23478fa

Browse files
authored
Relocate modules (#607)
## General * Docs update referring to new location of modules * Update copyright and thanks * Add tests for pulling various permutations of image registry/name/tag * Include pointers to latest versions available through Maven Central ## MariaDB * Relocate MariaDB module into main testcontainers-java repository Also enable parallel running of Jdbc Driver tests for speed reasons ## Oracle XE * Relocate Oracle XE module into main testcontainers-java repository Also enable use of sha256 hashes instead of image tags, for situations where image tags are not easily pinnable * Extend pull/startup timeout for Oracle container * Change rate limiter usage to prevent excessive connection creation Intended to eliminate `ORA-12516, TNS:listener could not find available handler` error * Add getConnectTimeoutSeconds as a separate timeout for JDBC containers to establish a JDBC connection ## Localstack * Relocate Localstack module into main testcontainers-java repository * Use latest localstack image ## Dynalite * Relocate Dynalite module into main testcontainers-java repository * Migrate dynalite image to quay.io ## MS SQL Server * Relocate MS SQL Server module into main testcontainers-java repository * Introduce assertion for license acceptance, e.g. for the SQL Server EULA ## Vault * Relocate Vault module into main testcontainers-java repository
1 parent 37456ae commit 23478fa

File tree

60 files changed

+2098
-90
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2098
-90
lines changed

.github/CODEOWNERS

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Each line is a file pattern followed by one or more owners.
2+
3+
# These owners will be the default reviewers for everything in
4+
# the repo.
5+
6+
* @rnorth @bsideup @kiview
7+
8+
# The last matching pattern takes the most
9+
# precedence.
10+
11+
# Contributed modules can have different reviewers
12+
13+
modules/mssqlserver/ @StefanHufschmidt @rnorth @bsideup @kiview
14+
modules/vault/ @mikeoswald @rnorth @bsideup @kiview

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ See [LICENSE](LICENSE).
1616

1717
Copyright (c) 2015, 2016 Richard North and other authors.
1818

19-
See [AUTHORS](AUTHORS) for contributors.
19+
MS SQL Server module is (c) 2017 - 2019 G DATA Software AG and other authors.
20+
21+
Hashicorp Vault module is (c) 2017 Capital One Services, LLC and other authors.
22+
23+
See [AUTHORS](AUTHORS) for all contributors.

circle.yml

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,24 @@ jobs:
44
core:
55
steps:
66
- checkout
7-
- run: ./gradlew testcontainers:check
7+
- run:
8+
command: ./gradlew testcontainers:check
9+
- run:
10+
name: Save test results
11+
command: |
12+
mkdir -p ~/junit/
13+
find . -type f -regex ".*/build/test-results/.*xml" -exec cp {} ~/junit/ \;
14+
when: always
15+
- store_test_results:
16+
path: ~/junit
17+
modules-no-jdbc-test-no-selenium:
18+
steps:
19+
- checkout
20+
- run:
21+
command: ./gradlew check -x testcontainers:check -x selenium:check -x jdbc-test:check
22+
environment:
23+
# Oracle JDBC drivers require a timezone to be set
24+
TZ: "/usr/share/zoneinfo/ETC/UTC"
825
- run:
926
name: Save test results
1027
command: |
@@ -13,10 +30,14 @@ jobs:
1330
when: always
1431
- store_test_results:
1532
path: ~/junit
16-
modules:
33+
modules-jdbc-test:
1734
steps:
1835
- checkout
19-
- run: ./gradlew check -x testcontainers:check -x selenium:check
36+
- run:
37+
command: ./gradlew jdbc-test:check
38+
environment:
39+
# Oracle JDBC drivers require a timezone to be set
40+
TZ: "/usr/share/zoneinfo/ETC/UTC"
2041
- run:
2142
name: Save test results
2243
command: |
@@ -28,7 +49,8 @@ jobs:
2849
selenium:
2950
steps:
3051
- checkout
31-
- run: ./gradlew selenium:check
52+
- run:
53+
command: ./gradlew selenium:check
3254
- run:
3355
name: Save test results
3456
command: |
@@ -43,5 +65,6 @@ workflows:
4365
test_all:
4466
jobs:
4567
- core
46-
- modules
68+
- modules-no-jdbc-test-no-selenium
69+
- modules-jdbc-test
4770
- selenium

core/src/main/java/org/testcontainers/containers/GenericContainer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ public String getDockerImageName() {
838838
try {
839839
return image.get();
840840
} catch (Exception e) {
841-
throw new ContainerFetchException("Can't get Docker image name from " + image, e);
841+
throw new ContainerFetchException("Can't get Docker image: " + image, e);
842842
}
843843
}
844844

core/src/main/java/org/testcontainers/images/RemoteDockerImage.java

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.github.dockerjava.api.model.Image;
77
import com.github.dockerjava.core.command.PullImageResultCallback;
88
import lombok.NonNull;
9+
import lombok.ToString;
910
import org.slf4j.Logger;
1011
import org.slf4j.profiler.Profiler;
1112
import org.testcontainers.DockerClientFactory;
@@ -14,30 +15,32 @@
1415
import org.testcontainers.utility.DockerLoggerFactory;
1516
import org.testcontainers.utility.LazyFuture;
1617

17-
import java.util.Collections;
1818
import java.util.HashSet;
1919
import java.util.List;
20+
import java.util.Objects;
2021
import java.util.Set;
22+
import java.util.stream.Collectors;
23+
import java.util.stream.Stream;
2124

25+
@ToString
2226
public class RemoteDockerImage extends LazyFuture<String> {
2327

24-
public static final Set<String> AVAILABLE_IMAGE_NAME_CACHE = new HashSet<>();
28+
public static final Set<DockerImageName> AVAILABLE_IMAGE_NAME_CACHE = new HashSet<>();
2529

26-
private final String dockerImageName;
30+
private DockerImageName imageName;
2731

2832
public RemoteDockerImage(String dockerImageName) {
29-
DockerImageName.validate(dockerImageName);
30-
this.dockerImageName = dockerImageName;
33+
imageName = new DockerImageName(dockerImageName);
3134
}
3235

3336
public RemoteDockerImage(@NonNull String repository, @NonNull String tag) {
34-
this.dockerImageName = repository + ":" + tag;
37+
imageName = new DockerImageName(repository, tag);
3538
}
3639

3740
@Override
3841
protected final String resolve() {
3942
Profiler profiler = new Profiler("Rule creation - prefetch image");
40-
Logger logger = DockerLoggerFactory.getLogger(dockerImageName);
43+
Logger logger = DockerLoggerFactory.getLogger(imageName.toString());
4144
profiler.setLogger(logger);
4245

4346
Profiler nested = profiler.startNested("Obtaining client");
@@ -48,58 +51,64 @@ protected final String resolve() {
4851
profiler.start("Check local images");
4952

5053
int attempts = 0;
54+
DockerClientException lastException = null;
5155
while (true) {
5256
// Does our cache already know the image?
53-
if (AVAILABLE_IMAGE_NAME_CACHE.contains(dockerImageName)) {
54-
logger.trace("{} is already in image name cache", dockerImageName);
57+
if (AVAILABLE_IMAGE_NAME_CACHE.contains(imageName)) {
58+
logger.trace("{} is already in image name cache", imageName);
5559
break;
5660
}
5761

5862
// Update the cache
5963
ListImagesCmd listImagesCmd = dockerClient.listImagesCmd();
6064

6165
if (Boolean.parseBoolean(System.getProperty("useFilter"))) {
62-
listImagesCmd = listImagesCmd.withImageNameFilter(dockerImageName);
66+
listImagesCmd = listImagesCmd.withImageNameFilter(imageName.toString());
6367
}
6468

6569
List<Image> updatedImages = listImagesCmd.exec();
66-
for (Image image : updatedImages) {
67-
if (image.getRepoTags() != null) {
68-
Collections.addAll(AVAILABLE_IMAGE_NAME_CACHE, image.getRepoTags());
69-
}
70-
}
70+
updatedImages.stream()
71+
.map(Image::getRepoTags)
72+
.filter(Objects::nonNull)
73+
.flatMap(Stream::of)
74+
.map(DockerImageName::new)
75+
.collect(Collectors.toCollection(() -> AVAILABLE_IMAGE_NAME_CACHE));
7176

7277
// And now?
73-
if (AVAILABLE_IMAGE_NAME_CACHE.contains(dockerImageName)) {
74-
logger.trace("{} is in image name cache following listing of images", dockerImageName);
78+
if (AVAILABLE_IMAGE_NAME_CACHE.contains(imageName)) {
79+
logger.trace("{} is in image name cache following listing of images", imageName);
7580
break;
7681
}
7782

7883
// Log only on first attempt
7984
if (attempts == 0) {
80-
logger.info("Pulling docker image: {}. Please be patient; this may take some time but only needs to be done once.", dockerImageName);
85+
logger.info("Pulling docker image: {}. Please be patient; this may take some time but only needs to be done once.", imageName);
8186
profiler.start("Pull image");
8287
}
8388

8489
if (attempts++ >= 3) {
85-
logger.error("Retry limit reached while trying to pull image: " + dockerImageName + ". Please check output of `docker pull " + dockerImageName + "`");
86-
throw new ContainerFetchException("Retry limit reached while trying to pull image: " + dockerImageName);
90+
logger.error("Retry limit reached while trying to pull image: {}. Please check output of `docker pull {}`", imageName, imageName);
91+
throw new ContainerFetchException("Retry limit reached while trying to pull image: " + imageName, lastException);
8792
}
8893

8994
// The image is not available locally - pull it
9095
try {
91-
dockerClient.pullImageCmd(dockerImageName).exec(new PullImageResultCallback()).awaitCompletion();
92-
} catch (InterruptedException e) {
93-
throw new ContainerFetchException("Failed to fetch container image for " + dockerImageName, e);
96+
final PullImageResultCallback callback = new PullImageResultCallback();
97+
dockerClient
98+
.pullImageCmd(imageName.getUnversionedPart())
99+
.withTag(imageName.getVersionPart())
100+
.exec(callback);
101+
callback.awaitSuccess();
102+
AVAILABLE_IMAGE_NAME_CACHE.add(imageName);
103+
break;
104+
} catch (DockerClientException e) {
105+
lastException = e;
94106
}
95-
96-
// Do not break here, but step into the next iteration, where it will be verified with listImagesCmd().
97-
// see https://github.com/docker/docker/issues/10708
98107
}
99108

100-
return dockerImageName;
109+
return imageName.toString();
101110
} catch (DockerClientException e) {
102-
throw new ContainerFetchException("Failed to get Docker client for " + dockerImageName, e);
111+
throw new ContainerFetchException("Failed to get Docker client for " + imageName, e);
103112
} finally {
104113
profiler.stop().log();
105114
}

core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/FromStatementTrait.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
public interface FromStatementTrait<SELF extends FromStatementTrait<SELF> & DockerfileBuilderTrait<SELF>> {
77

88
default SELF from(String dockerImageName) {
9-
DockerImageName.validate(dockerImageName);
9+
new DockerImageName(dockerImageName).assertValid();
1010

1111
return ((SELF) this).withStatement(new SingleArgumentStatement("FROM", dockerImageName));
1212
}

0 commit comments

Comments
 (0)