package org.arquillian.cube.docker.drone; import java.nio.file.Path; import java.util.Arrays; import org.arquillian.cube.docker.drone.util.SeleniumVersionExtractor; import org.arquillian.cube.docker.drone.util.VideoFileDestination; import org.arquillian.cube.docker.drone.util.VolumeCreator; import org.arquillian.cube.docker.impl.client.config.Await; import org.arquillian.cube.docker.impl.client.config.BuildImage; import org.arquillian.cube.docker.impl.client.config.CubeContainer; import org.arquillian.cube.docker.impl.client.config.Image; import org.arquillian.cube.docker.impl.client.config.Link; import org.arquillian.cube.docker.impl.client.config.PortBinding; public class SeleniumContainers { public static final String SELENIUM_CONTAINER_NAME = "browser"; public static final String VNC_CONTAINER_NAME = "vnc"; public static final String CONVERSION_CONTAINER_NAME = "flv2mp4"; private static final String CHROME_IMAGE = "selenium/standalone-chrome-debug:%s"; private static final String FIREFOX_IMAGE = "selenium/standalone-firefox-debug:%s"; private static final String VNC_IMAGE = "richnorth/vnc-recorder:latest"; private static final String CONVERSION_IMAGE = "arquillian/flv2mp4:0.0.1"; private static final String DEFAULT_PASSWORD = "secret"; private static final String VNC_HOSTNAME = "vnchost"; private static final String VOLUME_DIR = "recording"; private static final int SELENIUM_BOUNDED_PORT = 14444; private static final int VNC_EXPOSED_PORT = 5900; public static final String[] FLVREC_COMMAND = new String[] { "-o", "/" + VOLUME_DIR + "/screen.flv", "-P", "/" + VOLUME_DIR + "/password" , VNC_HOSTNAME , Integer.toString(VNC_EXPOSED_PORT)}; private CubeContainer seleniumContainer; private CubeContainer vncContainer; private CubeContainer videoConverterContainer; private String browser; private Path videoRecordingFolder; private SeleniumContainers(CubeContainer seleniumContainer, String browser, CubeContainer vncContainer, CubeContainer videoConverterContainer, Path videoRecordingFolder) { this.seleniumContainer = seleniumContainer; this.vncContainer = vncContainer; this.videoConverterContainer = videoConverterContainer; this.browser = browser; this.videoRecordingFolder = videoRecordingFolder; } public static SeleniumContainers create(String browser, CubeDroneConfiguration cubeDroneConfiguration) { final Path temporaryVolume = VolumeCreator.createTemporaryVolume(DEFAULT_PASSWORD); final Path targetVolume = VideoFileDestination.resolveTargetDirectory(cubeDroneConfiguration); return new SeleniumContainers(createSeleniumContainer(browser, cubeDroneConfiguration), browser, createVncContainer(temporaryVolume), createVideoConverterContainer(targetVolume), temporaryVolume); } private static CubeContainer createVideoConverterContainer(Path dockerVolume) { CubeContainer cubeContainer = new CubeContainer(); cubeContainer.setImage(Image.valueOf(CONVERSION_IMAGE)); cubeContainer.setBinds( Arrays.asList(dockerVolume.toAbsolutePath().toString() + ":/" + VOLUME_DIR + ":rw") ); // Using log await strategy to match the echo string indicating completion of conversion Await await = new Await(); await.setStrategy("log"); await.setMatch("CONVERSION COMPLETED"); cubeContainer.setAwait(await); // sets container as manual because we need to start and stop cubeContainer.setManual(true); return cubeContainer; } private static CubeContainer createVncContainer(final Path dockerVolume) { CubeContainer cubeContainer = new CubeContainer(); cubeContainer.setImage(Image.valueOf(VNC_IMAGE)); cubeContainer.setBinds( Arrays.asList(dockerVolume.toAbsolutePath().toString() + ":/" + VOLUME_DIR + ":rw") ); final Link link = Link.valueOf(SELENIUM_CONTAINER_NAME + ":" + VNC_HOSTNAME); cubeContainer.setLinks(Arrays.asList(link)); // Using sleeping strategy since VNC client is a CLI without exposing a port Await await = new Await(); await.setStrategy("sleeping"); await.setSleepTime("100 ms"); cubeContainer.setAwait(await); cubeContainer.setCmd(Arrays.asList(FLVREC_COMMAND)); // sets container as manual because we need to start and stop for each test case cubeContainer.setManual(true); return cubeContainer; } private static CubeContainer createSeleniumContainer(String browser, CubeDroneConfiguration cubeDroneConfiguration) { if (cubeDroneConfiguration.isBrowserDockerfileDirectorySet()) { return createCube(cubeDroneConfiguration.getBrowserDockerfileLocation()); } else { if (cubeDroneConfiguration.isBrowserImageSet()) { return configureCube(cubeDroneConfiguration.getBrowserImage()); } else { return useOfficialSeleniumImages(browser); } } } private static CubeContainer useOfficialSeleniumImages(String browser) { String version = SeleniumVersionExtractor.fromClassPath(); switch (browser) { case "firefox": return configureCube(String.format(FIREFOX_IMAGE, version)); case "chrome": return configureCube(String.format(CHROME_IMAGE, version)); default: throw new UnsupportedOperationException( "Unsupported browser " + browser + ". Only firefox and chrome are supported."); } } private static CubeContainer createCube(String dockerFileLocation) { CubeContainer cubeContainer = new CubeContainer(); BuildImage buildImage = new BuildImage(dockerFileLocation, null, true, true); cubeContainer.setBuildImage(buildImage); setDefaultSeleniumCubeProperties(cubeContainer); return cubeContainer; } private static CubeContainer configureCube(String image) { CubeContainer cubeContainer = new CubeContainer(); cubeContainer.setImage(Image.valueOf(image)); setDefaultSeleniumCubeProperties(cubeContainer); return cubeContainer; } private static void setDefaultSeleniumCubeProperties(CubeContainer cubeContainer) { cubeContainer.setPortBindings( Arrays.asList(PortBinding.valueOf(SELENIUM_BOUNDED_PORT + "-> 4444")) ); Await await = new Await(); await.setStrategy("http"); // Doing an http request to selenium node returns a 403 if Jetty is up and running await.setResponseCode(403); await.setUrl("http://dockerHost:" + SELENIUM_BOUNDED_PORT); cubeContainer.setAwait(await); cubeContainer.setKillContainer(true); } public CubeContainer getSeleniumContainer() { return seleniumContainer; } public CubeContainer getVncContainer() { return vncContainer; } public CubeContainer getVideoConverterContainer() { return videoConverterContainer; } public Path getVideoRecordingFolder() { return videoRecordingFolder; } public Path getVideoRecordingFile() { return videoRecordingFolder.resolve("screen.flv"); } public int getSeleniumBoundedPort() { return SELENIUM_BOUNDED_PORT; } public String getSeleniumContainerName() { return SELENIUM_CONTAINER_NAME; } public String getVncContainerName() { return VNC_CONTAINER_NAME; } public String getVideoConverterContainerName() { return CONVERSION_CONTAINER_NAME; } public String getBrowser() { return browser; } }