Skip to content

Commit

Permalink
Merge branch 'main' into add_timeplus_container
Browse files Browse the repository at this point in the history
  • Loading branch information
lizhou1111 authored Jul 4, 2024
2 parents ece9945 + 7989b20 commit fd8678c
Show file tree
Hide file tree
Showing 29 changed files with 462 additions and 85 deletions.
58 changes: 58 additions & 0 deletions .github/workflows/moby-latest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Tests against recent Docker engine releases

on:
workflow_dispatch:
schedule:
# nightly build, at 23:59 CEST
- cron: '59 23 * * *'

jobs:
test_docker:
strategy:
matrix:
install-docker-type: ["STABLE", "ROOTLESS", "ROOTFUL"]
name: "Core tests using Docker ${{ matrix.install-docker-type }}"
runs-on: ubuntu-22.04
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-build

- name: Install Stable Docker
if: ${{ matrix.install-docker-type == 'STABLE' }}
run: curl https://get.docker.com

- name: Install Docker from the TEST channel
if: ${{ matrix.install-docker-type == 'ROOTFUL' }}
run: curl https://get.docker.com | CHANNEL=test sh

- name: Setup rootless Docker
if: ${{ matrix.install-docker-type == 'ROOTLESS' }}
uses: ScribeMD/rootless-docker@6bd157a512c2fafa4e0243a8aa87d964eb890886 # v0.2.2

- name: Remove Docker root socket
if: ${{ matrix.install-docker-type == 'ROOTLESS' }}
run: sudo rm -rf /var/run/docker.sock

- name: Check Docker version
run: docker version

- name: Build with Gradle
run: ./gradlew cleanTest --no-daemon --continue --scan -Dscan.tag.DOCKER_${{ matrix.install-docker-type }} testcontainers:test -Dorg.gradle.caching=false
- uses: ./.github/actions/setup-junit-report

- name: Notify to Slack on failures
if: failure()
id: slack
uses: slackapi/slack-github-action@v1.26.0
with:
payload: |
{
"tc_project": "testcontainers-java",
"tc_docker_install_type": "${{ matrix.install-docker-type }}",
"tc_github_action_url": "https://github.com/testcontainers/testcontainers-java/actions/runs/${{ env.GITHUB_RUN_ID }}/job/${{ env.GITHUB_RUN_NUMBER }}",
"tc_github_action_status": "FAILED",
"tc_slack_channel_id": "${{ secrets.SLACK_DOCKER_LATEST_CHANNEL_ID }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DOCKER_LATEST_WEBHOOK }}
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private DockerClientProviderStrategy getOrInitializeStrategy() {
if (strategy != null) {
return strategy;
}

log.info("Testcontainers version: {}", DEFAULT_LABELS.get(TESTCONTAINERS_VERSION_LABEL));
List<DockerClientProviderStrategy> configurationStrategies = new ArrayList<>();
ServiceLoader.load(DockerClientProviderStrategy.class).forEach(configurationStrategies::add);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ protected WaitStrategy getWaitStrategy() {

@Override
public void setWaitStrategy(WaitStrategy waitStrategy) {
this.containerDef.setWaitStrategy(waitStrategy);
this.waitStrategy = waitStrategy;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.testcontainers.images.ParsedDockerfile;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.resolver.Resolver;

import java.io.File;
import java.io.FileInputStream;
Expand All @@ -34,10 +37,20 @@ class ParsedDockerComposeFile {
private final File composeFile;

@Getter
private Map<String, Set<String>> serviceNameToImageNames = new HashMap<>();
private final Map<String, Set<String>> serviceNameToImageNames = new HashMap<>();

ParsedDockerComposeFile(File composeFile) {
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
// The default is 50 and a big docker-compose.yml file can easily go above that number. 1,000 should give us some room
LoaderOptions options = new LoaderOptions();
options.setMaxAliasesForCollections(1_000);
DumperOptions dumperOptions = new DumperOptions();
Yaml yaml = new Yaml(
new SafeConstructor(options),
new Representer(dumperOptions),
dumperOptions,
options,
new Resolver()
);
try (FileInputStream fileInputStream = FileUtils.openInputStream(composeFile)) {
composeFileContent = yaml.load(fileInputStream);
} catch (Exception e) {
Expand Down Expand Up @@ -82,7 +95,9 @@ private void parseAndValidate() {
return;
}

servicesMap = (Map<String, ?>) servicesElement;
@SuppressWarnings("unchecked")
Map<String, ?> temp = (Map<String, ?>) servicesElement;
servicesMap = temp;
} else {
servicesMap = composeFileContent;
}
Expand All @@ -99,15 +114,16 @@ private void parseAndValidate() {
break;
}

final Map serviceDefinitionMap = (Map) serviceDefinition;
@SuppressWarnings("unchecked")
final Map<String, ?> serviceDefinitionMap = (Map<String, ?>) serviceDefinition;

validateNoContainerNameSpecified(serviceName, serviceDefinitionMap);
findServiceImageName(serviceName, serviceDefinitionMap);
findImageNamesInDockerfile(serviceName, serviceDefinitionMap);
}
}

private void validateNoContainerNameSpecified(String serviceName, Map serviceDefinitionMap) {
private void validateNoContainerNameSpecified(String serviceName, Map<String, ?> serviceDefinitionMap) {
if (serviceDefinitionMap.containsKey("container_name")) {
throw new IllegalStateException(
String.format(
Expand All @@ -119,20 +135,21 @@ private void validateNoContainerNameSpecified(String serviceName, Map serviceDef
}
}

private void findServiceImageName(String serviceName, Map serviceDefinitionMap) {
if (serviceDefinitionMap.containsKey("image") && serviceDefinitionMap.get("image") instanceof String) {
final String imageName = (String) serviceDefinitionMap.get("image");
private void findServiceImageName(String serviceName, Map<String, ?> serviceDefinitionMap) {
Object result = serviceDefinitionMap.get("image");
if (result instanceof String) {
final String imageName = (String) result;
log.debug("Resolved dependency image for Docker Compose in {}: {}", composeFileName, imageName);
serviceNameToImageNames.put(serviceName, Sets.newHashSet(imageName));
}
}

private void findImageNamesInDockerfile(String serviceName, Map serviceDefinitionMap) {
private void findImageNamesInDockerfile(String serviceName, Map<String, ?> serviceDefinitionMap) {
final Object buildNode = serviceDefinitionMap.get("build");
Path dockerfilePath = null;

if (buildNode instanceof Map) {
final Map buildElement = (Map) buildNode;
final Map<?, ?> buildElement = (Map<?, ?>) buildNode;
final Object dockerfileRelativePath = buildElement.get("dockerfile");
final Object contextRelativePath = buildElement.get("context");
if (dockerfileRelativePath instanceof String && contextRelativePath instanceof String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import org.testcontainers.TestImages;
import org.testcontainers.containers.startupcheck.StartupCheckStrategy;
import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.RemoteDockerImage;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.images.builder.Transferable;
Expand Down Expand Up @@ -256,6 +258,21 @@ public void shouldContainDefaultNetworkAliasWhenUsingContainerDef() {
}
}

@Test
public void shouldRespectWaitStrategy() {
try (
HelloWorldLogStrategyContainer container = new HelloWorldLogStrategyContainer(
"testcontainers/helloworld:1.1.0"
)
) {
container.setWaitStrategy(Wait.forLogMessage(".*Starting server on port.*", 1));
container.start();
assertThat((LogMessageWaitStrategy) container.getWaitStrategy())
.extracting("regEx", "times")
.containsExactly(".*Starting server on port.*", 1);
}
}

static class NoopStartupCheckStrategy extends StartupCheckStrategy {

@Override
Expand Down Expand Up @@ -319,4 +336,13 @@ class HelloWorldContainerDef extends ContainerDef {
}
}
}

static class HelloWorldLogStrategyContainer extends GenericContainer<HelloWorldContainer> {

public HelloWorldLogStrategyContainer(String image) {
super(DockerImageName.parse(image));
withExposedPorts(8080);
waitingFor(Wait.forLogMessage(".*Starting server on port.*", 2));
}
}
}
2 changes: 2 additions & 0 deletions core/src/test/java/org/testcontainers/containers/JibTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.testcontainers.containers;

import com.github.dockerjava.api.command.InspectImageResponse;
import org.junit.Ignore;
import org.junit.Test;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.output.OutputFrame.OutputType;
Expand All @@ -12,6 +13,7 @@

import static org.assertj.core.api.Assertions.assertThat;

@Ignore("Jib doesn't work with latest Docker version provided by GH Actions. Jib should be updated")
public class JibTest {

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import lombok.SneakyThrows;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.File;
import java.io.PrintWriter;
import java.util.Collections;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;

public class ParsedDockerComposeFileValidationTest {

@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Test
public void shouldValidate() {
File file = new File("src/test/resources/docker-compose-container-name-v1.yml");
Expand Down Expand Up @@ -129,4 +136,22 @@ public void shouldObtainImageFromDockerfileBuildWithContext() {
entry("custom", Sets.newHashSet("alpine:3.17"))
); // redis, mysql from compose file, alpine:3.17 from Dockerfile build
}

@Test
public void shouldSupportALotOfAliases() throws Exception {
File file = temporaryFolder.newFile();
try (PrintWriter writer = new PrintWriter(file)) {
writer.println("x-entry: &entry");
writer.println(" key: value");
writer.println();
writer.println("services:");
for (int i = 0; i < 1_000; i++) {
writer.println(" service" + i + ":");
writer.println(" image: busybox");
writer.println(" environment:");
writer.println(" <<: *entry");
}
}
assertThatNoException().isThrownBy(() -> new ParsedDockerComposeFile(file));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public static String[] parameters() {
"alpine:3.17",
"alpine", // omitting the tag should work and default to latest
"alpine@sha256:1775bebec23e1f3ce486989bfc9ff3c4e951690df84aa9f926497d82f2ffca9d",
"quay.io/testcontainers/ryuk:latest",
"quay.io/testcontainers/ryuk:0.2.3",
"quay.io/testcontainers/ryuk@sha256:bb5a635cac4bd96c93cc476969ce11dc56436238ec7cd028d0524462f4739dd9",
"docker.io/testcontainers/ryuk:latest",
"docker.io/testcontainers/ryuk:0.7.0",
"docker.io/testcontainers/ryuk@sha256:bcbee39cd601396958ba1bd06ea14ad64ce0ea709de29a427d741d1f5262080a",
// "ibmcom/db2express-c", // Big image for testing with slow networks
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ public class DependsOnTest {
public GenericContainer<?> redis = new GenericContainer<>("redis:6-alpine").withExposedPorts(6379);

@Rule
public GenericContainer<?> nginx = new GenericContainer<>("nginx:1.9.4").dependsOn(redis).withExposedPorts(80);
public GenericContainer<?> nginx = new GenericContainer<>("nginx:1.27.0-alpine3.19-slim")
.dependsOn(redis)
.withExposedPorts(80);

// }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ public class WaitStrategiesTest {

@Rule
// waitForNetworkListening {
public GenericContainer nginx = new GenericContainer(DockerImageName.parse("nginx:1.9.4")) //
public GenericContainer nginx = new GenericContainer(DockerImageName.parse("nginx:1.27.0-alpine3.19-slim")) //
.withExposedPorts(80);

// }

@Rule
// waitForSimpleHttp {
public GenericContainer nginxWithHttpWait = new GenericContainer(DockerImageName.parse("nginx:1.9.4"))
public GenericContainer nginxWithHttpWait = new GenericContainer(
DockerImageName.parse("nginx:1.27.0-alpine3.19-slim")
)
.withExposedPorts(80)
.waitingFor(Wait.forHttp("/"));

Expand Down
19 changes: 19 additions & 0 deletions examples/ollama-hugging-face/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
id 'java'
}

repositories {
mavenCentral()
}

dependencies {
testImplementation 'org.testcontainers:ollama'
testImplementation 'org.assertj:assertj-core:3.25.3'
testImplementation 'ch.qos.logback:logback-classic:1.3.14'
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
testImplementation 'io.rest-assured:rest-assured:5.4.0'
}

test {
useJUnitPlatform()
}
Loading

0 comments on commit fd8678c

Please sign in to comment.