arquillian / arquillian-cube

Control (docker, kubernetes, openshift) containers in your tests with ease!
http://arquillian.org/arquillian-cube/
120 stars 98 forks source link

ConfigUtil.dump and load seems to be not symmetric #357

Closed smiklosovic closed 8 years ago

smiklosovic commented 8 years ago

I want to get rid of arquillian.xml file completely so everything will be configurable from the configuration class where I basically gather possible configuration from user and after that I set system properties programmatically so Arquillian manager will be configured purely from system properties so arquillian.xml is not needed anymore.

The problem is that when I provide some CubeContainer configuration, currently Cube does it other way around, it takes whatever is in "dockerContainers" in arquillian.xml and it constructs CubeContainers structure where that string is demarshalled from string to its model class.

I want it other way around, I construct CubeContainers and I want to marshall it to String and set it as a system property arq.extension.docker.dockerContainers so once Arqullian picks it from there, it will be reconstructed again by Cube internals.

But this is not symmetrical, look at this:

@Test
public void testParsingOfCubeContainers() {
    final CubeContainer cubeContainer = new CubeContainer();

    cubeContainer.setImage(Image.valueOf("some.image:5000/org/tomcat:latest"));

    cubeContainer.setExposedPorts(Stream.of(
            ExposedPort.valueOf("1099/tcp"),
            ExposedPort.valueOf("8000/tcp"),
            ExposedPort.valueOf("8080/tcp"),
            ExposedPort.valueOf("8009/tcp")
    ).collect(Collectors.toList()));

    Await await = new Await();
    await.setStrategy("polling");
    await.setType("ping");
    await.setSleepPollingTime("5 s");
    await.setIterations(15);

    cubeContainer.setAwait(await);

    cubeContainer.setPortBindings(Stream.of(
            PortBinding.valueOf("1099/tcp"),
            PortBinding.valueOf("8000/tcp"),
            PortBinding.valueOf("8080/tcp"),
            PortBinding.valueOf("8009/tcp")
    ).collect(Collectors.toList()));

    cubeContainer.setLinks(Stream.of(
            Link.valueOf("mariadb:mariadb"),
            Link.valueOf("mongodb:mongodb"),
            Link.valueOf("activemq:activemq")
    ).collect(Collectors.toList()));

    CubeContainers cubeContainers = new CubeContainers();
    cubeContainers.add("tomcat", cubeContainer);

    String dump = ConfigUtil.dump(cubeContainers);

    System.out.println(dump);

    // this throws exception

    CubeContainers demarshalledCubeContainers = ConfigUtil.load(dump);
}

The output is like this:

containers:
  tomcat:
    alwaysPull: false
    await: {iterations: 15, sleepPollingTime: 5 s, strategy: polling, type: ping}
    exposedPorts: [1099/tcp, 8000/tcp, 8080/tcp, 8009/tcp]
    image: some.image:5000/org/tomcat:latest
    links: ['mariadb:mariadb', 'mongodb:mongodb', 'activemq:activemq']
    portBindings: [1099/tcp, 8000/tcp, 8080/tcp, 8009/tcp]
    readonlyRootfs: false

And the exception raised by loading is this:

Cannot create property=tomcat for     JavaBean=org.arquillian.cube.docker.impl.client.config.CubeContainer@33f88ab
 in 'string', line 1, column 1:
    tomcat:
    ^
Unable to find property 'tomcat' on class:     org.arquillian.cube.docker.impl.client.config.CubeContainer
 in 'string', line 2, column 3:
      alwaysPull: false
      ^

at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:308)
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructor.java:189)
at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:341)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:182)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:141)
at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:127)
at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:450)
at org.yaml.snakeyaml.Yaml.loadAs(Yaml.java:427)
at org.arquillian.cube.docker.impl.util.ConfigUtil.load(ConfigUtil.java:93)
at org.arquillian.cube.docker.impl.util.ConfigUtil.load(ConfigUtil.java:81)
lordofthejars commented 8 years ago

Yes the problem I see is that sysout does something related for loging and not for being reused in another way.

smiklosovic commented 8 years ago

This seems to fix it

https://github.com/arquillian/arquillian-cube/pull/358

smiklosovic commented 8 years ago

After dumping it looks like this:

containers:
    tomcat:
        alwaysPull: false
        await: {iterations: 15, sleepPollingTime: 5 s, stdErr: false, stdOut: true, strategy: polling,
        timeout: 15, type: ping}
        cpuSet: '123'
        exposedPorts: [1099/tcp, 8000/tcp, 8080/tcp, 8009/tcp]
        image: some.image:5000/org/tomcat:latest
        links: ['mariadb:mariadb', 'mongodb:mongodb', 'activemq:activemq']
        portBindings: [1099/tcp, 8000/tcp, 8080/tcp, 8009/tcp]
        readonlyRootfs: false
networks: {}

The problem was that there was "containers" string which was treated as a name of container so there was not any "tomcat" variable in CubeContainer - so you have to basically do one step down to containers.