package org.arquillian.cube.docker.impl.client.containerobject.dsl; import org.arquillian.cube.CubeController; import org.arquillian.cube.docker.impl.docker.DockerClientExecutor; import org.arquillian.cube.docker.impl.model.DockerCube; import org.arquillian.cube.docker.impl.model.NetworkRegistry; import org.arquillian.cube.impl.util.ReflectionUtil; import org.arquillian.cube.spi.CubeRegistry; import org.arquillian.cube.spi.metadata.IsContainerObject; import org.arquillian.cube.spi.metadata.IsNetworkContainerObject; import org.jboss.arquillian.core.api.Injector; import org.jboss.arquillian.core.api.Instance; import org.jboss.arquillian.core.api.annotation.Inject; import org.jboss.arquillian.test.spi.TestEnricher; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.logging.Logger; /** * Enricher that starts any networks or containers defined in tests. This enricher must start both because we need to be sure that networks are started before containers. */ public class ContainerNetworkObjectDslTestEnricher implements TestEnricher { private static final Logger logger = Logger.getLogger(ContainerNetworkObjectDslTestEnricher.class.getName()); @Inject Instance<CubeController> cubeControllerInstance; @Inject Instance<CubeRegistry> cubeRegistryInstance; @Inject Instance<DockerClientExecutor> dockerClientExecutorInstance; @Inject Instance<NetworkRegistry> networkRegistryInstance; @Inject Instance<Injector> injectorInstance; @Override public void enrich(final Object testCase) { // Needs to get definitions of network and contaienrs at same enricher because first we need to register networks and then containers // And there is no way to order test enrichers. startNetworks(testCase); startContainers(testCase); } private void startContainers(Object testCase) { final List<Field> containerFields = ReflectionUtil.getFieldsWithAnnotation(testCase.getClass(), DockerContainer.class); Collections.sort(containerFields, Comparator.comparingInt(f -> f.getAnnotation(DockerContainer.class).order())); Collections.reverse(containerFields); for (Field field : containerFields) { try { final Object object = field.get(testCase); if (Container.class.isAssignableFrom(object.getClass())) { Container containerObject = (Container) object; final Container enrichedContainer = injectorInstance.get().inject(containerObject); field.set(testCase, enrichedContainer); startContainer(enrichedContainer, testCase.getClass()); } else { throw new IllegalArgumentException(String.format("Object %s is not assignable to %s.", object.getClass(), Container.class.getName())); } } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } } } private void startNetworks(Object testCase) { List<Field> networkFields = ReflectionUtil.getFieldsWithAnnotation(testCase.getClass(), DockerNetwork.class); for (Field field : networkFields) { try { final Object object = field.get(testCase); if (Network.class.isAssignableFrom(object.getClass())) { Network networkObject = (Network) object; startNetwork(networkObject); } else { throw new IllegalArgumentException(String.format("Object %s is not assignable to %s.", object.getClass(), Network.class.getName())); } } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } } } @Override public Object[] resolve(Method method) { return new Object[0]; } private void startNetwork(Network network) { final org.arquillian.cube.docker.impl.client.config.Network dockerNetwork = network.getNetwork(); final String id = dockerClientExecutorInstance.get().createNetwork(network.getId(), dockerNetwork); dockerNetwork.addMetadata(IsNetworkContainerObject.class, new IsNetworkContainerObject()); networkRegistryInstance.get().addNetwork(id, dockerNetwork); } private void startContainer(Container container, Class<?> testClass) { String containerName = container.getContainerName(); if (isNotInitialized(containerName)) { DockerCube dockerCube = new DockerCube(containerName, container.getCubeContainer(), dockerClientExecutorInstance.get()); dockerCube.addMetadata(IsContainerObject.class, new IsContainerObject(testClass, container.getConnectionMode())); logger.finer(String.format("Created Cube with name %s and configuration %s", containerName, dockerCube.configuration())); cubeRegistryInstance.get().addCube(injectorInstance.get().inject(dockerCube)); CubeController cubeController = cubeControllerInstance.get(); cubeController.create(containerName); cubeController.start(containerName); } } private boolean isNotInitialized(String containerName) { return cubeRegistryInstance.get().getCube(containerName) == null; } }