arquillian / arquillian-cube

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

"boot2docker" serverUri hack doesn't work #132

Closed rhuss closed 9 years ago

rhuss commented 9 years ago

When using a serverUri like https://boot2docker:2376, I get a NPE here:

private String resolveBoot2Docker(String tag,
            String boot2DockerPath) {
    return tag.replaceAll(Boot2Docker.BOOT2DOCKER_TAG, boot2DockerInstance.get().ip(boot2DockerPath, false));
 }

because the boot2DockerInstance.get() is still null. The reason is, that this method is called before the Boot2DockerCreator observer is notified with a ManagerStarted event where it creates the boot2DockerInstance:

class Boot2DockerCreator {
   //...
   public void configure(@Observes ManagerStarted managerStarted) {
     boot2DockerInstanceProducer.set(new Boot2Docker(new CommandLineExecutor()));
  }
}  
lordofthejars commented 9 years ago

I will need to check this with @aslakknutsen but I think that this is the first event that is sent by Arquillian, so we cannot inject this value before.

Can you explain what are you doing? I mean where are you trying to use boot2docker substitution? Maybe you have found a use case that we didn't contemplate it.

aslakknutsen commented 9 years ago

@lordofthejars Are we listening to ArquillianDescriptor to update the config in the very beginning? If so, then ArquillianDesscriptor is produced in the ManagerStarted cycle so technically the observer on ArquillianDescriptor could be called before another ManagerStarted observer. Would need to set the @Observer.precedence on the Boot2DockerCreator to ensure it is started very early.

lordofthejars commented 9 years ago

Well boot2Docker is resolved as:

public class Boot2DockerCreator {

    @Inject
    @ApplicationScoped
    private InstanceProducer<Boot2Docker> boot2DockerInstanceProducer;

    public void configure(@Observes ManagerStarted managerStarted) {
        boot2DockerInstanceProducer.set(new Boot2Docker(new CommandLineExecutor()));
    }

}

And we are using in ArquillianDescriptor

 @Inject
    private Instance<Boot2Docker> boot2DockerInstance;

    public void configure(@Observes ArquillianDescriptor arquillianDescriptor) {
        Map<String, String> config = arquillianDescriptor.extension(EXTENSION_NAME).getExtensionProperties();
        config = resolveServerUriByOperativeSystem(config);
        config = resolveServerIp(config);
        CubeConfiguration cubeConfiguration = CubeConfiguration.fromMap(config);
        configurationProducer.set(cubeConfiguration);
    }
rhuss commented 9 years ago

I just player around with @arun-gupta 's Docker integrations in javaee-samples/javaee7-samples (branch: docker). The configuration looks like

  <plugin>
      <artifactId>maven-surefire-plugin</artifactId>
      <configuration>
        <systemPropertyVariables>
           <arquillian.launch>wildfly-docker</arquillian.launch>
           <arq.container.wildfly-docker.configuration.username>admin</arq.container.wildfly-docker.configuration.username>
           <arq.container.wildfly-docker.configuration.password>Admin#70365</arq.container.wildfly-docker.configuration.password>
           <arq.extension.docker.serverVersion>1.15</arq.extension.docker.serverVersion>
           <arq.extension.docker.serverUri>https://boot2docker:2376</arq.extension.docker.serverUri>
           <arq.extension.docker.dockerContainers>
           wildfly-docker:
             image: arungupta/javaee7-samples-wildfly
               exposedPorts: [8080/tcp, 9990/tcp]
               await:
                   strategy: polling
                   sleepPollingTime: 50000
                   iterations: 5
               portBindings: [8080/tcp, 9990/tcp]
            </arq.extension.docker.dockerContainers>
         </systemPropertyVariables>
      </configuration>
  </plugin>

I replaced the serverUri with https://boot2docker:2376 and got this exception (shortened):

ava.lang.RuntimeException: Could not create new instance of class org.jboss.arquillian.test.impl.EventTestRunnerAdaptor
    at org.jboss.arquillian.test.spi.SecurityActions.newInstance(SecurityActions.java:165)
        ....
org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
        .....
Caused by: java.lang.NullPointerException: null
    at org.arquillian.cube.impl.client.CubeConfigurator.resolveBoot2Docker(CubeConfigurator.java:55)

Changing boot2docker to the proper IP and specifying a certPath worked, though.

aslakknutsen commented 9 years ago

@lordofthejars right, that's what I was wondering. So the ArquillianDescriptor is produced in a ManagerStarted event, so it's technically a sub event of ManagerStarted. So depending on the undefined order of Observers of ManagerStarted, ArquillianDescriptor may or may not be produced Before the Boot2DockerCreator. If you add a precedence to configure it should work predictable.

 public void configure(@Observes(precedence = 100) ManagerStarted managerStarted) {
        boot2DockerInstanceProducer.set(new Boot2Docker(new CommandLineExecutor()));
 }
lordofthejars commented 9 years ago

Cool I will fix it :)