package org.arquillian.cube.docker.impl.client.containerobject; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.logging.Logger; import java.util.stream.Collectors; import org.apache.commons.lang3.ArrayUtils; import org.arquillian.cube.ContainerObjectConfiguration; import org.arquillian.cube.ContainerObjectFactory; import org.arquillian.cube.containerobject.Cube; import org.arquillian.cube.containerobject.Environment; import org.arquillian.cube.containerobject.Link; import org.arquillian.cube.containerobject.Volume; import org.arquillian.cube.docker.impl.await.PollingAwaitStrategy; import org.arquillian.cube.docker.impl.client.config.Await; import org.arquillian.cube.docker.impl.client.config.CubeContainer; import org.arquillian.cube.docker.impl.client.config.PortBinding; import org.arquillian.cube.impl.util.ReflectionUtil; import org.jboss.arquillian.core.api.Instance; import org.jboss.arquillian.core.api.annotation.Inject; import org.jboss.arquillian.test.spi.TestEnricher; public class CubeContainerObjectTestEnricher implements TestEnricher { private static final Logger logger = Logger.getLogger(CubeContainerObjectTestEnricher.class.getName()); @Inject Instance<ContainerObjectFactory> containerObjectFactoryInstance; private static ContainerObjectConfiguration extractConfigFrom(Field field) { return new CubeContainerObjectConfiguration(extractCubeContainerFrom(field)); } private static CubeContainer extractCubeContainerFrom(Field field) { final CubeContainer cubeContainer = new CubeContainer(); final Cube cubeAnnotation = field.getAnnotation(Cube.class); if (cubeAnnotation == null) { throw new IllegalArgumentException( String.format("Field %s requires to be annotated with %s annotation", field.getName(), Cube.class.getSimpleName())); } // cubeName from Cube::value() final String cubeName = cubeAnnotation.value(); if (cubeName != null && !Cube.DEFAULT_VALUE.equals(cubeName)) { cubeContainer.setContainerName(cubeName); } // port bindings from Cube::portBinding() final String[] portBindingsFromAnnotation = cubeAnnotation.portBinding(); if (portBindingsFromAnnotation != null && !Arrays.equals(portBindingsFromAnnotation, Cube.DEFAULT_PORT_BINDING)) { final List<PortBinding> portBindings = Arrays.stream(portBindingsFromAnnotation) .map(PortBinding::valueOf) .collect(Collectors.toList()); cubeContainer.setPortBindings(portBindings); } // await using PollingStrategy with Cube::awaitPorts() final int[] awaitPortsFromAnnotation = cubeAnnotation.awaitPorts(); if (awaitPortsFromAnnotation != null && !Arrays.equals(awaitPortsFromAnnotation, Cube.DEFAULT_AWAIT_PORT_BINDING)) { final Await await = new Await(); await.setStrategy(PollingAwaitStrategy.TAG); await.setPorts(Arrays.asList(ArrayUtils.toObject(awaitPortsFromAnnotation))); cubeContainer.setAwait(await); } // environment variables from Environment annotations final Environment[] environmentVariablesFromAnnotations = field.getAnnotationsByType(Environment.class); if (environmentVariablesFromAnnotations != null && environmentVariablesFromAnnotations.length > 0) { final List<String> environmentVariables = Arrays.stream(environmentVariablesFromAnnotations) .map(environment -> environment.key() + "=" + environment.value()) .collect(Collectors.toList()); cubeContainer.setEnv(environmentVariables); } // volumes from Volume annotations final Volume[] volumesFromAnnotations = field.getAnnotationsByType(Volume.class); if (volumesFromAnnotations != null && volumesFromAnnotations.length > 0) { final List<String> volumeBindings = Arrays.stream(volumesFromAnnotations) .map(volume -> volume.hostPath() + ":" + volume.containerPath() + ":rw") .collect(Collectors.toList()); cubeContainer.setBinds(volumeBindings); } // links from link annotations final Link[] linksFromAnnotations = field.getAnnotationsByType(Link.class); if (linksFromAnnotations != null && linksFromAnnotations.length > 0) { final List<org.arquillian.cube.docker.impl.client.config.Link> links = Arrays.stream(linksFromAnnotations) .map(Link::value) .map(org.arquillian.cube.docker.impl.client.config.Link::valueOf) .collect(Collectors.toList()); cubeContainer.setLinks(links); } return cubeContainer; } @Override public void enrich(Object testCase) { List<Field> cubeFields = ReflectionUtil.getFieldsWithAnnotation(testCase.getClass(), Cube.class); if (cubeFields.size() > 0) { for (Field cubeField : cubeFields) { try { logger.fine(String.format("Creating Container Object for field %s", cubeField.getName())); enrichField(testCase, cubeField); } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } } } } private void enrichField(Object testCase, Field field) throws IllegalAccessException { final Object cubeContainerObject = field.get(testCase); if (cubeContainerObject == null) { final Class<?> cubeContainerClazz = field.getType(); final ContainerObjectConfiguration configuration = extractConfigFrom(field); final Object containerObjectInstance = containerObjectFactoryInstance.get().createContainerObject(cubeContainerClazz, configuration, testCase); field.set(testCase, containerObjectInstance); } } @Override public Object[] resolve(Method method) { return new Object[0]; } }