arquillian / arquillian-cube Goto Github PK
View Code? Open in Web Editor NEWControl (docker, kubernetes, openshift) containers in your tests with ease!
Home Page: http://arquillian.org/arquillian-cube/
Control (docker, kubernetes, openshift) containers in your tests with ease!
Home Page: http://arquillian.org/arquillian-cube/
Arquillian test runners normally come in two forms, with or without container/deployment support, e.g. arquillian-junit-container, arquillian-junit-standalone.
While Cube has integration with Arquillian Container, it's features are still useful in a standalone mode.
Make the extension registry of the ...container.* observers optional and depend on the availability of the Container module. Mark container-spi/impls as optional/provided.
Cube should expose SPI level Lifecycle events for extensibility.
When starting big containers on slow computers it might be required to wait more then 500ms for the ports to respond..
We should allow to configure the timeout of the PollingAwaitStrategy via arquillian.xml:
https://github.com/arquillian/arquillian-cube/blob/master/docker/src/main/java/org/arquillian/cube/impl/await/PollingAwaitStrategy.java#L32
In case the docker container is not available remotely, execute the tests by using the ip address of the docker host instead of the ip address of the started docker container.
Perhaps this can be solved by adding a dedicated property which overrides the default behavior. This should then also update the injected ArquillianURL address.
Create an enricher for injectcing container id in test, so it can be used in conjunction with DockerClient.
The Container it self only knows which ports it is bound to inside the Docker image, not which ports are opened from the outside via PortForward.
This effects the ServletProtocol when attempting to communicate with incontainer test cases and @ArquillianResource URL injection.
When defining multiple similar Docker containers it would be useful to allow some form of extensions model where you can override only the few parameters that change.
e.g.
wildfly:
buildImage:
dockerfileLocation: src/test/resources/wildfly
noCache: true
remove: true
exposedPorts: [8080/tcp, 9990/tcp]
await:
strategy: polling
links:
- database:database
portBindings:
- exposedPort: 8080/tcp
port: 8081
- exposedPort: 9990/tcp
port: 9991
wildfly2:
extends: wildfly
portBindings:
- exposedPort: 8080/tcp
port: 8082
- exposedPort: 9990/tcp
port: 9992
Add Cube provider that can control Docker images via OpenShift Origin
ConnectionRefusedException should be handled here;
https://github.com/arquillian/arquillian-cube/blob/master/docker/src/main/java/org/arquillian/cube/docker/DockerClientExecutor.java#L165
and user presented with a Exception message that explains possible causes;
e.g.
Some applications like Spring Boot uses an embedded Jetty/Tomcat to run itself. So there is no server container to configure because it is embedded.
In this cases if we want to test this kind of applications we need to create a jar file and copy it inside Docker container. To copy the generated jar file is as simple as create a Dockerfile and call ADD command, and then finally execute the CMD like CMD ["java", "-jar", "example-jar-with-dependencies.jar"]
.
The problem is how to create this jar, I think we cannot use @Deployment
because there will be no servlet container configured. Moreover we need to copy the file physically to disk, so probably we need another annotation maybe called @CliDeployment
where you can set the location where the JavaArchive will be copied.
Then it is a simple matter of creating correctly the Dockferfile.
Create an static time await strategy so for example you can set to wait an specific amount of time without doing anything against an ip.
A simple 'mvn clean install -DskipTests' fail to build Cube.
ftest require some profile to be active to get the Servlet spec apis. Either activate a profile by default, or depend on the Servlet api.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project arquillian-cube-ftest: Compilation failure: Compilation failure:
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[6,21] package javax.servlet does not exist
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[7,32] package javax.servlet.annotation does not exist
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[8,26] package javax.servlet.http does not exist
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[9,26] package javax.servlet.http does not exist
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[10,26] package javax.servlet.http does not exist
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[13,40] cannot find symbol
[ERROR] symbol: class HttpServlet
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[12,2] cannot find symbol
[ERROR] symbol: class WebServlet
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[16,26] cannot find symbol
[ERROR] symbol: class HttpServletRequest
[ERROR] location: class org.arquillian.cube.servlet.HelloWorldServlet
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[16,50] cannot find symbol
[ERROR] symbol: class HttpServletResponse
[ERROR] location: class org.arquillian.cube.servlet.HelloWorldServlet
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[16,83] cannot find symbol
[ERROR] symbol: class ServletException
[ERROR] location: class org.arquillian.cube.servlet.HelloWorldServlet
[ERROR] /home/aslak/dev/source/arquillian/arquillian-cube/ftest/src/main/java/org/arquillian/cube/servlet/HelloWorldServlet.java:[15,5] method does not override or implement a method from a supertype
Fix transitive deps with jaxrs issues. Several users has found some issues when they were using RestEasy and docker cube, this is because docker-java uses Jersey as jaxrs provider and adds it as dependency on classpath so depending on the order of execution the test may fail.
It seems that docker-spotify project addresses this problem. For this reason we are going to move that library and see if the problem is fixed.
Cube workspace is locally checked out and built. Running a simple servlet test using them gives:
Running org.javaee7.servlet.metadata.complete.SimpleServletTest
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.712 sec <<< FAILURE! - in org.javaee7.servlet.metadata.complete.SimpleServletTest
org.javaee7.servlet.metadata.complete.SimpleServletTest Time elapsed: 1.707 sec <<< ERROR!
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to java.lang.String
at org.arquillian.cube.impl.util.BindingUtil.binding(BindingUtil.java:44)
at org.arquillian.cube.impl.client.container.RemapContainerController.remapContainer(RemapContainerController.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:135)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:115)
at org.jboss.arquillian.core.impl.EventImpl.fire(EventImpl.java:67)
at org.jboss.arquillian.container.impl.ContainerImpl.setup(ContainerImpl.java:173)
at org.jboss.arquillian.container.impl.client.container.ContainerLifecycleController$7.perform(ContainerLifecycleController.java:149)
at org.jboss.arquillian.container.impl.client.container.ContainerLifecycleController$7.perform(ContainerLifecycleController.java:145)
at org.jboss.arquillian.container.impl.client.container.ContainerLifecycleController.forContainer(ContainerLifecycleController.java:255)
at org.jboss.arquillian.container.impl.client.container.ContainerLifecycleController.setupContainer(ContainerLifecycleController.java:144)
Separate between binding to .e.g. Container Events like BeforeStart and actually performing the CubeStart action.
A binding to e.g. container.BeforeStart should only 'remap' to a StartCubeContainer event.
By doing this we encapsulate the behavior of starting a Cube 'behind' an event and allows other extensions easly to trigger our behavior.
Create a nowait strategy which simply do nothing. SImply pass the check.
Expose a simple user exposed API that can perform basic Cube operations:
.e.g
public interface CubeController {
void start(String cubeId);
void stop(String cubeId);
}
Should support as-client and in-container.
Currently Cube-Docker function as Cube-Core and Docker since Docker is the only implementation.
OpenShift3 is next in line and parts of Cube-Docker can be reused.
My remote docker host installed on centos 7 in hyper-v vm. configured like in arquillian cube git documentation.
-H tcp://{hostIp}:2375 -H unix:///var/run/docker.sock (for remote connections)
firewalld disabled.
telnet works from windows hostIp:2375
started docker container ports exposed (8080,9990) works to.
everything works.
running tests from windows machine tests not executed.
Exception
.net.ConnectException: Connection timed out: connect
javax.ws.rs.ProcessingException
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
after some research I found arquillian executes tests again
http://172.17.42.1:8080/7c832426-9615-4e47-bf74-458813015fa2
ip 172.17.42.1 is internal docker ip which is not visible from LAN.
but correct url must be
http://{hostIp}:8080/7c832426-9615-4e47-bf74-458813015fa2
Change return type when creating a container to String instead of docker-client CreateContainer class. In this way we will decouple Cube from underlying Docker library.
Adds log messages in actions not related with Docker itself.
Allow dynamic port binding so the bind port to an exposed port is assigned automatically from random port. In this way we will be able to run tests in parallel without having port collisions.
When using the CubeController the user is left to him self, for both starting and stopping the cubes in Suite scope.
Cube should provide some type of 'mode' similar to Arquillian Container that gives Cube a hint of what to do with the different started cubes to avoid leak between Test Classes.
If user provides:
portBindings: [8081->8080/tcp, 9091->9990/tcp]
We should be able to infer that 8080/tcp and 9990/tcp should be exposed:
exposedPorts: [8080/tcp, 9990/tcp]
Narrative:
As a developer
I want to be able to create a Docker container from Dockerfile
So that integration tests can run against a new created container
Acceptance Criteria:
Scenario1: A tar file with Dockerfile can be used for creating a new container containing an application server
Given Arquillian test
And Docker Server installed and TCP port open
And a Dockerfile file defining inside or any other parent container an application server
And Arquillian remote adapter for application server
When Test is executed
Then New Docker container shall be created
And Deployment file deployed inside Docker's application server
Scenario2: A tar file with Dockerfile can be loaded from URL.
Given a Dockerfile URL (file, http, classpath, ...)
When Test is executed
Then Docker container shall be created from Dockerfile provided by URL
Scenario3: A directory with Dockerfile can be used for creating a new container containing an application server.
Given a Folder with Dockerfile on root
When Test is executed
Then Docker container shall be created from Dockerfile provided.
Scenario4: An exception is thrown if Dockerfile cannot be read
Given a Dockerfile
When Test is executed
Then An exception shall be thrown if Dockerfile is not readable
Narrative:
As a developer
I want to be able to orchestrate several Docker container inside test
So I can reproduce complex scenarios
Acceptance Criteria:
Scenario1: Multiple Docker containers can be spawn in same test
Given Arquillian test
And Docker Server installed and TCP port open
And A definition of Docker containers with at least one having an application server
And Arquillian remote adapter for application server
When Test is started
Then Docker containers shall be orchestrated
And Deployment file deployed inside Docker's application server
Currently Cube require to control the full life cycle of the Docker image.
We should allow connecting to a pre running image.
e.g. Start the dev Docker image in the morning and reuse the same instance all day.
If the defined Docker image is not already pulled locally docker will throw a 'no image found' exception.
The extension could attempt to run a docker pull if no image is found
When we have more then 'docker server' as an implementation we need to split the configuration.
Probably in :
Core currently has options like:
Docker has:
Assuming Cube is Docker focused, dockerContainers, dockerContainersFile and dockerRegistry might be reusable configuration options for Cube Core.
Define Docker images in Core, Docker Server info in Docker and extra Kuberetes features around the Docker images in it's own config
Update docker client to v 0.10.5 so we can use unix sockets and exec command.
To give the user full control over the environment we should support Docker Containers that are controllable outside of the Arquillian DeployableContainer lifecycle.
Allow configure repository from where docker images are pulled. By default it uses the official docker repository, but it should be possible to configure a private repository as well.
Currently Arquillian Cube uses TCP to communicate with Docker server, but Docker server can also run using unix sockets. Allow developers to use this mode instead of TCP.
This issue is related with docker-java/docker-java#85
Currently Cube use the ContainerIP and the Forwarded port when testing if the port is alive.
Docker sets up a forward from localhost:ForwardPort with a forward to ContainerIP:ExposedPort.
Change to use ContainerIP:ExposedPort.
Currently port binding is configured by using a list of objects in yaml.
portBindings:
- exposedPort: 8089/tcp
port: 8089
- exposedPort: 8080/tcp
port: 8080
To avoid user having to write many lines with redundant information, this will be changed to:
portBindings: [8080:8080/tcp, 8089:8089/tcp]
Update README with shouldAllowToConnectToRunningContainers description
I think we should be able to remap the configured/default DeployableContainer values based on Docker Containers port forward mapping.
Steps
Hi,
I've just hit an NPE here:
I'll try to figure out what went wrong in PingCmd but in general it would help to make catch more robust.
Narrative:
As a developer
I want to be able to execute Arquillian tests in/against Docker container
So that my integration tests are executed in a production like-environment
Acceptance Criteria:
Scenario 1: Docker container with an application server should be started
Given Arquillian test
And Docker Server installed and TCP port open
And Docker container with application server correctly configured
And Arquillian remote adapter for application server
When Test is started
Then Docker container shall be started
And Deployment file deployed inside Docker's application server
Scenario 2: An exception should be thrown if Docker server is not available
Given Arquillian test
And Docker container with application server correctly configured
And Arquillian remote adapter for application server
When Test is executed
Then An exception shall be thrown because of Docker server not running or TCP port not open
Scenario 3: Docker container parameters should be available during test
Given Arquillian test
And Docker Server installed and TCP port open
And Docker container with application server correctly configured
And Arquillian remote adapter for application server
When Test is executed
Then Docker parameters like host, port, ... shall be available during test execution.
Instead of using @Cube
enricher for injecting DockerClient
in test, use ResourceProvider
so DockerClient
is injected by using @ArquillianResource
annotation
Following up from #48 ...
Running org.javaee7.servlet.metadata.complete.SimpleServletTest
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Dec 10, 2014 8:58:13 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 1 * Sending client request on thread main
1 > GET http://192.168.59.103:2376/v1.15/_ping
Dec 10, 2014 8:58:13 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 2 * Sending client request on thread main
2 > POST http://192.168.59.103:2376/v1.15/containers/create?name=wildfly-docker
2 > Accept: application/json
2 > Content-Type: application/json
{"name":"wildfly-docker","Hostname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":null,"Cmd":null,"Dns":null,"Image":"arungupta/javaee7-samples-wildfly","Volumes":{},"VolumesFrom":[],"WorkingDir":"","DisableNetwork":false,"ExposedPorts":{"8080/tcp":{},"9990/tcp":{}}}
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.356 sec <<< FAILURE! - in org.javaee7.servlet.metadata.complete.SimpleServletTest
org.javaee7.servlet.metadata.complete.SimpleServletTest Time elapsed: 1.355 sec <<< ERROR!
org.arquillian.cube.spi.CubeControlException: Could not create wildfly-docker
at org.arquillian.cube.spi.CubeControlException.failedCreate(CubeControlException.java:19)
at org.arquillian.cube.impl.model.DockerCube.create(DockerCube.java:69)
at org.arquillian.cube.impl.client.CubeLifecycleController.create(CubeLifecycleController.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Polling sleep time units should be configurable. It has not much sense for example days, hours or minutes, but for example ms (for milliseconds) or s (for seconds) would be desirable.
Updates docker-java library to latest stable version
To allow developers run in parallel tests instead of naming the containers we should use the generated id for referencing it. Name container will be only used by Arquillian Cube to know which container to start.
My limited experience with Arquillian-cube showed my that cube doesn't allow to run the same container configuration twice. Maybe you have already foreseen this and I don't know how to configure this. Currently, I can't.
Use Case: It is necessarily to run multiple test runs of the same code base. A CI build triggers a test run and a official build triggers a test run. The first one wins an the later fails. It should be possible to configure cube to allow concurrent docker instances.
I try to run some tests with arquillian-cube-containerless 1.0.0.Alpha3.
I got the exception : org.arquillian.cube.spi.CubeControlException: Could not create mycube.
...
Caused by: java.lang.IllegalStateException: Docker server has not provided an imageId for image build from src/test/resources/docker/mondrian. Response from the server was:
Step 0 : FROM ubuntu:12.04 ---> f959d044ebdfStep 1 : MAINTAINER ......Successfully built bc7b77133064
As you can see the docker was build but the image id was not retrieved by DockerClientExecutor .buildImage().
I run this test on a ubuntu 12.04.
Using regular expression it is possible to resolve this issue in DockerClientExecutor class
private static final Pattern IMAGEID_PATTERN = Pattern.compile(".*Successfully built\s(\p{XDigit}+)");
Matcher m = IMAGEID_PATTERN.matcher(fullLog);
String imageId = null;
if (m.find()) {
imageId = m.group(1);
}
return imageId;
Complete example in README is missing;
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.