Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to launch Informix via testcontainers?

I'm very interested in using testcontainers in my project.

However, I'm having a hard time setting it up to work with Informix.

Note that I can start an informix container using Docker-for-Mac and it will build and start.

Not sure it can work with testcontainers though. I wish it would.

Here's what I have so far

Test class

package com.example.demo;

import com.github.dockerjava.api.command.CreateContainerCmd;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import org.testcontainers.containers.wait.strategy.WaitAllStrategy;

import java.time.Duration;

import static org.junit.Assert.assertEquals;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

  private static GenericContainer informix;

  @BeforeClass
  public static void init() {
    informix = new GenericContainer("ibmcom/informix-innovator-c")
        .withExposedPorts(9088)
        .withEnv("LICENSE", "accept")
        .withPrivilegedMode(true)
        .withCreateContainerCmdModifier(command -> ((CreateContainerCmd)command).withTty(Boolean.TRUE))
        .waitingFor(new WaitAllStrategy().withStrategy(new LogMessageWaitStrategy().withRegEx(".*listener on port.*\n"))
            .withStrategy(new HostPortWaitStrategy())
            .withStartupTimeout(Duration.ofMinutes(2)));

    informix.start();
  }

  @AfterClass
  public static void destroy(){
    informix.close();
  }

  @Test
  public void testDemo() {
    int foo = 1;
    assertEquals(foo, 1);
  }

}

The container starts up and then hangs forever, and test is never entered

Here's the output:

...
00:32:27  Updating Low Memory Manager to version 11 
00:32:27  Installing patch to Low Memory Manager code. version(11.01)
00:32:27  Installing patch to upgrade ph_task code. version(13.08)
00:32:27  SCHAPI: Started 2 dbWorker threads.
00:32:27  Checkpoint Completed:  duration was 0 seconds.
00:32:27  Sat Jul  6 - loguniq 3, logpos 0xa2e080, timestamp: 0x32abd Interval: 6

00:32:27  Maximum server connections 1 
00:32:27  Checkpoint Statistics - Avg. Txn Block Time 0.000, # Txns blocked 1, Plog used 178, Llog used 4831

starting mongo listener on port 27017
starting rest listener on port 27018
starting mqtt listener on port 27883
17:34:05.472 [main] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536,false,com.github.dockerjava.core.exec.InspectContainerCmdExec@3fabf088
17:34:05.472 [main] DEBUG com.github.dockerjava.core.exec.InspectContainerCmdExec - GET: OkHttpWebTarget(okHttpClient=org.testcontainers.shaded.okhttp3.OkHttpClient@70925b45, baseUrl=http://docker.socket/, path=[/containers/b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536/json], queryParams={})
17:34:05.482 [main] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536,<null>,com.github.dockerjava.core.exec.KillContainerCmdExec@5cbf9e9f
17:34:06.186 [main] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536,false,com.github.dockerjava.core.exec.InspectContainerCmdExec@18e8473e
17:34:06.187 [main] DEBUG com.github.dockerjava.core.exec.InspectContainerCmdExec - GET: OkHttpWebTarget(okHttpClient=org.testcontainers.shaded.okhttp3.OkHttpClient@70925b45, baseUrl=http://docker.socket/, path=[/containers/b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536/json], queryParams={})
17:34:06.194 [main] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b252c6f234c9d133d17f64f54344061e3689758089339abb7eda3f056adde536,true,true,com.github.dockerjava.core.exec.RemoveContainerCmdExec@6f6a7463
17:34:06.297 [main] DEBUG org.testcontainers.utility.ResourceReaper - Removed container and associated volume(s): ibmcom/informix-innovator-c:latest
17:34:06.298 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - After test class: context [DefaultTestContext@624ea235 testClass = DemoApplicationTests, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@3932c79a testClass = DemoApplicationTests, locations = '{}', classes = '{class com.example.demo.DemoApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@3e2e18f2, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@703580bf, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@5c30a9b0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@3c407114], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]], class annotated with @DirtiesContext [false] with mode [null].

org.testcontainers.containers.ContainerLaunchException: Container startup failed

    at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:217)
    at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:199)
    at com.example.demo.DemoApplicationTests.init(DemoApplicationTests.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
    at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:83)
    at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:210)
    ... 20 more
Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
    at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:277)
    at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:212)
    at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:76)
    ... 21 more
Caused by: org.rnorth.ducttape.TimeoutException: java.util.concurrent.TimeoutException
    at org.rnorth.ducttape.timeouts.Timeouts.callFuture(Timeouts.java:70)
    at org.rnorth.ducttape.timeouts.Timeouts.doWithTimeout(Timeouts.java:60)
    at org.testcontainers.containers.wait.strategy.WaitAllStrategy.waitUntilReady(WaitAllStrategy.java:53)
    at org.testcontainers.containers.GenericContainer.waitUntilContainerStarted(GenericContainer.java:582)
    at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:259)
    ... 23 more
Caused by: java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask.get(FutureTask.java:205)
    at org.rnorth.ducttape.timeouts.Timeouts.callFuture(Timeouts.java:65)
    ... 27 more


Disconnected from the target VM, address: '127.0.0.1:51062', transport: 'socket'

Test ignored.

Process finished with exit code 255

If I comment out this line

// .withCreateContainerCmdModifier(command -> ((CreateContainerCmd)command).withTty(Boolean.TRUE))

Then it starts, but then gets stuck in a loop endlessly with these messages then ultimately timesout the same way

6:09:07.489 [ducttape-1] DEBUG com.github.dockerjava.core.exec.InspectExecCmdExec - GET: OkHttpWebTarget(okHttpClient=org.testcontainers.shaded.okhttp3.OkHttpClient@1a2e2935, baseUrl=http://docker.socket/, path=[/exec/ab3ed2f2d3fa129b21c787a7bcce603a267fea48268ab7c861657005919ee546/json], queryParams={})
16:09:08.494 [ducttape-1] DEBUG org.testcontainers.containers.ExecInContainerPattern - /elastic_raman: Running "exec" command: /bin/sh -c cat /proc/net/tcp{,6} | awk '{print $2}' | grep -i :2380
16:09:08.495 [ducttape-1] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: 3a30ec6ec83dff4b2f330b9c9d71b907dbfd7596a0bd9cc54d1b4f7eb2164f3e,<null>,true,true,<null>,<null>,<null>,{/bin/sh,-c,cat /proc/net/tcp{,6} | awk '{print $2}' | grep -i :2380},com.github.dockerjava.core.exec.ExecCreateCmdExec@74c5bfba
16:09:08.582 [ducttape-1] DEBUG com.github.dockerjava.core.command.AbstrDockerCmd - Cmd: b82e102d716c5530e5aa8c9699f8f5a5e0d6aa6cc4aa69c44b8553f79de4101f,com.github.dockerjava.core.exec.InspectExecCmdExec@90283ab
16:09:08.582 [ducttape-1] DEBUG com.github.dockerjava.core.exec.InspectExecCmdExec - GET: OkHttpWebTarget(okHttpClient=org.testcontainers.shaded.okhttp3.OkHttpClient@1a2e2935, baseUrl=http://docker.socket/, path=[/exec/b82e102d716c5530e5aa8c9699f8f5a5e0d6aa6cc4aa69c44b8553f79de4101f/json], queryParams={})
like image 639
slashdottir Avatar asked Jul 06 '19 00:07

slashdottir


1 Answers

There was a mis-configuration in the docker image for Informix. The servers that start in the docker containers only would listen on the hostname, and not localhost. Testcontainers uses 'localhost' as the network interface to connect to your containers. So when you used .withExposedPorts(9088) the port was not actually exposed on a network interface TestContainers could connect to.

This is why you still had trouble most likely even if you waited for the log message you also waited on the port and it would never be available.

The good news is that this is now fixed and available by pulling down the latest Informix docker images

ibmcom/informix-developer-database:latest for the latest 14.10 docker image

Below is the code I ran to validate the new images are working better with TestContainers.

public class DockerTest {
    GenericContainer<?>container  = new GenericContainer<>("ibmcom/informix-developer-database:latest")
        .withExposedPorts(9088, 9089, 27017, 27018, 27883).withEnv("LICENSE", "accept");
@Test
public void testIfxContainer() throws Exception {
    container.start();
    System.out.println("Informix started");
    //test the connection
    try(Connection c = DriverManager.getConnection("jdbc:informix-sqli:localhost:"  + container.getFirstMappedPort() + "/sysmaster:user=informix;password=your-password")) {
      try(Statement s = c.createStatement(); ResultSet rs = s.executeQuery("SELECT FIRST 10 tabname from systables");) {
        while(rs.next()) {
          System.out.println(r.getString(1));
        }
      }
    }
  }
}
like image 109
Brian Hughes Avatar answered Oct 07 '22 01:10

Brian Hughes