package org.arquillian.cube.docker.impl.client.container; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; import java.util.regex.Pattern; import org.arquillian.cube.docker.impl.client.CubeDockerConfiguration; import org.arquillian.cube.docker.impl.util.ContainerUtil; import org.arquillian.cube.docker.impl.util.OperatingSystemFamily; import org.arquillian.cube.spi.Cube; import org.arquillian.cube.spi.CubeRegistry; import org.arquillian.cube.spi.metadata.HasPortBindings; import org.jboss.arquillian.config.descriptor.api.ContainerDef; import org.jboss.arquillian.container.spi.Container; import org.jboss.arquillian.container.spi.ContainerRegistry; import org.jboss.arquillian.container.spi.event.container.BeforeSetup; import org.jboss.arquillian.core.api.Instance; import org.jboss.arquillian.core.api.annotation.Inject; import org.jboss.arquillian.core.api.annotation.Observes; public class DockerServerIPConfigurator { //private static final Pattern portPattern = Pattern.compile("(?i:.*port.*)"); private static final Pattern hostPattern = Pattern.compile("(?i:.*host.*)"); private static final Pattern addressPattern = Pattern.compile("(?i:.*address.*)"); private static final Pattern jmxPattern = Pattern.compile("(?i:.*jmx.*)"); @Inject private Instance<OperatingSystemFamily> familyInstance; public void applyDockerServerIpChange(@Observes BeforeSetup event, CubeRegistry cubeRegistry, ContainerRegistry containerRegistry) throws InstantiationException, IllegalAccessException, MalformedURLException { Container container = ContainerUtil.getContainerByDeployableContainer(containerRegistry, event.getDeployableContainer()); if (container == null) { return; } Cube<?> cube = cubeRegistry.getCube(org.arquillian.cube.impl.util.ContainerUtil.getCubeIDForContainer(container)); if (cube == null) { return; // No Cube found matching Container name, not managed by Cube } HasPortBindings portBindings = cube.getMetadata(HasPortBindings.class); if (portBindings == null) { return; } ContainerDef containerConfiguration = container.getContainerConfiguration(); boolean foundAttribute = resolveConfigurationPropertiesWithDockerServerIp(containerConfiguration, portBindings.getContainerIP()); //if user doesn't configured in arquillian.xml the host then we can override the default value. if (!foundAttribute) { Class<?> configurationClass = container.getDeployableContainer().getConfigurationClass(); List<PropertyDescriptor> configurationClassHostOrAddressFields = filterConfigurationClassPropertiesByHostOrAddressAttribute(configurationClass); for (PropertyDescriptor propertyDescriptor : configurationClassHostOrAddressFields) { //we get default address value and we replace to boot2docker ip containerConfiguration.overrideProperty(propertyDescriptor.getName(), portBindings.getContainerIP()); } } } private boolean resolveConfigurationPropertiesWithDockerServerIp(ContainerDef containerDef, String containerIP) { boolean foundAttribute = false; for (Entry<String, String> entry : containerDef.getContainerProperties().entrySet()) { if ((hostPattern.matcher(entry.getKey()).matches() || addressPattern.matcher(entry.getKey()).matches())) { //if property is already configured, doesn't matter if it is a boot2docker or not we can say that we have matched a defined property. foundAttribute = true; if (entry.getValue().contains(CubeDockerConfiguration.DOCKER_SERVER_IP)) { containerDef.overrideProperty(entry.getKey(), entry.getValue().replaceAll(CubeDockerConfiguration.DOCKER_SERVER_IP, containerIP)); } } } return foundAttribute; } private List<PropertyDescriptor> filterConfigurationClassPropertiesByHostOrAddressAttribute( Class<?> configurationClass) { List<PropertyDescriptor> fields = new ArrayList<PropertyDescriptor>(); try { PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(configurationClass, Object.class) .getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { String propertyName = propertyDescriptor.getName(); if ((hostPattern.matcher(propertyName).matches() || addressPattern.matcher(propertyName).matches()) && (!jmxPattern.matcher(propertyName).matches())) { fields.add(propertyDescriptor); } } } catch (IntrospectionException e) { throw new IllegalArgumentException(e); } return fields; } }