@SneakyThrows private Connection createSSHSession() { String password = UUID.randomUUID().toString(); container = new GenericContainer<>(TestcontainersConfiguration.getInstance().getSSHdImage()) .withExposedPorts(22) .withEnv("PASSWORD", password) .withCommand( "sh", "-c", // Disable ipv6 & Make it listen on all interfaces, not just localhost "echo \"root:$PASSWORD\" | chpasswd && /usr/sbin/sshd -D -o PermitRootLogin=yes -o AddressFamily=inet -o GatewayPorts=yes" ); container.start(); Connection connection = new Connection(container.getContainerIpAddress(), container.getMappedPort(22)); connection.setTCPNoDelay(true); connection.connect( (hostname, port, serverHostKeyAlgorithm, serverHostKey) -> true, (int) Duration.ofSeconds(30).toMillis(), (int) Duration.ofSeconds(30).toMillis() ); if (!connection.authenticateWithPassword("root", password)) { throw new IllegalStateException("Authentication failed."); } return connection; }
@Test public void containerStartFailsIfContainerIsUnhealthy() { container.withCommand("tail", "-f", "/dev/null"); assertThrows("Container launch fails when unhealthy", ContainerLaunchException.class, container::start); } }
public static void main(String[] args) { Thread mainThread = Thread.currentThread(); GenericContainer genericContainer = null; try { genericContainer = new GenericContainer().withCommand("top"); genericContainer.start(); Set<Thread> threads = new HashSet<>(Thread.getAllStackTraces().keySet()); threads.remove(mainThread); Set<Thread> nonDaemonThreads = threads.stream().filter(it -> !it.isDaemon()).collect(Collectors.toSet()); if (nonDaemonThreads.isEmpty()) { VisibleAssertions.pass("All threads marked as daemon"); } else { String nonDaemonThreadNames = nonDaemonThreads.stream() .map(Thread::getName) .collect(Collectors.joining("\n", "\n", "")); VisibleAssertions.fail("Expected all threads to be daemons but the following are not:\n" + nonDaemonThreadNames); } } finally { if (genericContainer != null) { genericContainer.stop(); } } }
protected GenericContainer startContainerWithCommand(String shellCommand, WaitStrategy waitStrategy, Integer... ports) { // apply WaitStrategy to container return new GenericContainer(IMAGE_NAME) .withExposedPorts(ports) .withCommand("sh", "-c", shellCommand) .waitingFor(waitStrategy.withStartupTimeout(Duration.ofMillis(WAIT_TIMEOUT_MILLIS))); }
@Test public void testExposedHost() throws Exception { assertResponse(new GenericContainer().withCommand("top")); }
@Test(expected = NotFoundException.class) public void copyFromContainerShouldFailBecauseNoFileTest() throws NotFoundException { try ( GenericContainer alpineCopyToContainer = new GenericContainer("alpine:3.2") .withCommand("top") ) { alpineCopyToContainer.start(); alpineCopyToContainer.copyFileFromContainer("/home/test.txt", "src/test/resources/copy-from/test.txt"); } }
@Test public void copyFileToContainerFolderTest() throws Exception { try ( GenericContainer alpineCopyToContainer = new GenericContainer("alpine:3.2") .withCommand("top") ) { alpineCopyToContainer.start(); final MountableFile mountableFile = MountableFile.forClasspathResource("test_copy_to_container.txt"); alpineCopyToContainer.copyFileToContainer(mountableFile, "/home/"); File actualFile = new File(temporaryFolder.getRoot().getAbsolutePath() + "/test_copy_to_container.txt"); alpineCopyToContainer.copyFileFromContainer("/home/test_copy_to_container.txt", actualFile.getPath()); File expectedFile = new File(mountableFile.getResolvedPath()); assertTrue("Files aren't same ", FileUtils.contentEquals(expectedFile, actualFile)); } }
@Test public void copyFileToContainerFileTest() throws Exception { try ( GenericContainer alpineCopyToContainer = new GenericContainer("alpine:3.2") .withCommand("top") ) { alpineCopyToContainer.start(); final MountableFile mountableFile = MountableFile.forClasspathResource("test_copy_to_container.txt"); alpineCopyToContainer.copyFileToContainer(mountableFile, "/test.txt"); File actualFile = new File(temporaryFolder.getRoot().getAbsolutePath() + "/test_copy_to_container.txt"); alpineCopyToContainer.copyFileFromContainer("/test.txt", actualFile.getPath()); File expectedFile = new File(mountableFile.getResolvedPath()); assertTrue("Files aren't same ", FileUtils.contentEquals(expectedFile, actualFile)); } }
@Test public void copyFolderToContainerFolderTest() throws Exception { try ( GenericContainer alpineCopyToContainer = new GenericContainer("alpine:3.2") .withCommand("top") ) { alpineCopyToContainer.start(); final MountableFile mountableFile = MountableFile.forClasspathResource("mappable-resource/"); alpineCopyToContainer.copyFileToContainer(mountableFile, "/home/test/"); File actualFile = new File(temporaryFolder.getRoot().getAbsolutePath() + "/test_copy_to_container.txt"); alpineCopyToContainer.copyFileFromContainer("/home/test/test-resource.txt", actualFile.getPath()); File expectedFile = new File(mountableFile.getResolvedPath() + "/test-resource.txt"); assertTrue("Files aren't same ", FileUtils.contentEquals(expectedFile, actualFile)); } }
@Test public void customLabelTest() { try (final GenericContainer alpineCustomLabel = new GenericContainer("alpine:3.2") .withLabel("our.custom", "label") .withCommand("top")) { alpineCustomLabel.start(); Map<String, String> labels = alpineCustomLabel.getCurrentContainerInfo().getConfig().getLabels(); assertTrue("org.testcontainers label is present", labels.containsKey("org.testcontainers")); assertTrue("our.custom label is present", labels.containsKey("our.custom")); assertEquals("our.custom label value is label", labels.get("our.custom"), "label"); } }
@Test public void test() { try (final GenericContainer container = new GenericContainer<>(image) .withCommand("/bin/sh", "-c", "sleep 0") .withStartupCheckStrategy(new OneShotStartupCheckStrategy())) { container.start(); // do nothing other than start and stop } } }
@Test public void shouldCopyFileFromContainerTest() throws IOException { try ( GenericContainer alpineCopyToContainer = new GenericContainer("alpine:3.2") .withCommand("top") ) { alpineCopyToContainer.start(); final MountableFile mountableFile = MountableFile.forClasspathResource("test_copy_to_container.txt"); alpineCopyToContainer.copyFileToContainer(mountableFile, "/home/"); File actualFile = new File(temporaryFolder.getRoot().getAbsolutePath() + "/test_copy_from_container.txt"); alpineCopyToContainer.copyFileFromContainer("/home/test_copy_to_container.txt", actualFile.getPath()); File expectedFile = new File(mountableFile.getResolvedPath()); assertTrue("Files aren't same ", FileUtils.contentEquals(expectedFile, actualFile)); } } }
@Test public void testExposedHostWithNetwork() throws Exception { try (Network network = Network.newNetwork()) { assertResponse(new GenericContainer().withNetwork(network).withCommand("top")); } }
public ParameterizedDockerfileContainerTest(String baseImage, String expectedVersion) { container = new GenericContainer(new ImageFromDockerfile().withDockerfileFromBuilder(builder -> { builder .from(baseImage) // Could potentially customise the image here, e.g. adding files, running // commands, etc. .build(); })).withCommand("top"); this.expectedVersion = expectedVersion; }
@Test public void testThatAuthLocatorIsUsed() throws Exception { final DockerImageName expectedName = new DockerImageName(testImageNameWithTag); final AuthConfig authConfig = new AuthConfig() .withUsername("testuser") .withPassword("notasecret") .withRegistryAddress("http://" + testRegistryAddress); // Replace the RegistryAuthLocator singleton with our mock, for the duration of this test final RegistryAuthLocator mockAuthLocator = Mockito.mock(RegistryAuthLocator.class); RegistryAuthLocator.setInstance(mockAuthLocator); when(mockAuthLocator.lookupAuthConfig(eq(expectedName), any())) .thenReturn(authConfig); // a push will use the auth locator for authentication, although that isn't the goal of this test putImageInRegistry(); // actually start a container, which will require an authenticated pull try (final GenericContainer container = new GenericContainer<>(testImageNameWithTag) .withCommand("/bin/sh", "-c", "sleep 10")) { container.start(); assertTrue("container started following an authenticated pull", container.isRunning()); } }
@Test public void checkFileCopied() throws IOException, InterruptedException { try( GenericContainer container = new GenericContainer("alpine:latest") .withCommand("sleep","3000") .withCopyFileToContainer(MountableFile.forClasspathResource("/mappable-resource/"), containerPath) ) { container.start(); String filesList = container.execInContainer("ls","/tmp/mappable-resource").getStdout(); Assert.assertTrue(filesList.contains(fileName)); } } }
@Test public void testNetworkSupport() throws Exception { try ( Network network = newNetwork(); GenericContainer foo = new GenericContainer() .withNetwork(network) .withNetworkAliases("foo") .withCommand("/bin/sh", "-c", "while true ; do printf 'HTTP/1.1 200 OK\\n\\nyay' | nc -l -p 8080; done"); GenericContainer bar = new GenericContainer() .withNetwork(network) .withCommand("top") ) { foo.start(); bar.start(); String response = bar.execInContainer("wget", "-O", "-", "http://foo:8080").getStdout(); assertEquals("received response", "yay", response); } }
@Test public void testIsRunning() { try (GenericContainer container = new GenericContainer().withCommand("top")) { assertFalse("Container is not started and not running", container.isRunning()); container.start(); assertTrue("Container is started and running", container.isRunning()); } }
@Test public void withTmpFsTest() throws Exception { try ( GenericContainer container = new GenericContainer() .withCommand("top") .withTmpFs(singletonMap("/testtmpfs", "rw")) ) { container.start(); // check file doesn't exist String path = "/testtmpfs/test.file"; Container.ExecResult execResult = container.execInContainer("ls", path); assertEquals("tmpfs inside container works fine", execResult.getStderr(), "ls: /testtmpfs/test.file: No such file or directory\n"); // touch && check file does exist container.execInContainer("touch", path); execResult = container.execInContainer("ls", path); assertEquals("tmpfs inside container works fine", execResult.getStdout(), path + "\n"); } }
@Test public void createContainerCmdHookTest() { // Use random name to avoid the conflicts between the tests String randomName = Base58.randomString(5); try( GenericContainer container = new GenericContainer<>("redis:3.0.2") .withCommand("redis-server", "--help") .withCreateContainerCmdModifier(cmd -> cmd.withName("overrideMe")) // Preserves the order .withCreateContainerCmdModifier(cmd -> cmd.withName(randomName)) // Allows to override pre-configured values by GenericContainer .withCreateContainerCmdModifier(cmd -> cmd.withCmd("redis-server", "--port", "6379")) ) { container.start(); assertEquals("Name is configured", "/" + randomName, container.getContainerInfo().getName()); assertEquals("Command is configured", "[redis-server, --port, 6379]", Arrays.toString(container.getContainerInfo().getConfig().getCmd())); } }