package org.arquillian.cube.docker.impl.client.containerobject;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import org.apache.commons.io.FileUtils;
import org.arquillian.cube.CubeController;
import org.arquillian.cube.containerobject.Cube;
import org.arquillian.cube.containerobject.CubeDockerFile;
import org.arquillian.cube.containerobject.Environment;
import org.arquillian.cube.containerobject.Image;
import org.arquillian.cube.containerobject.Link;
import org.arquillian.cube.containerobject.Volume;
import org.arquillian.cube.docker.impl.docker.DockerClientExecutor;
import org.arquillian.cube.docker.impl.model.DockerCube;
import org.arquillian.cube.impl.model.LocalCubeRegistry;
import org.arquillian.cube.spi.CubeRegistry;
import org.arquillian.cube.spi.metadata.IsContainerObject;
import org.jboss.arquillian.core.api.Injector;
import org.jboss.arquillian.core.spi.ServiceLoader;
import org.jboss.arquillian.test.spi.TestEnricher;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.GenericArchive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.descriptor.api.Descriptors;
import org.jboss.shrinkwrap.descriptor.api.docker.DockerDescriptor;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
public class CubeContainerObjectTestEnricherTest {
private CubeRegistry cubeRegistry;
private CubeController cubeController;
private DockerClientExecutor dockerClientExecutor;
private Injector injector;
private ServiceLoader serviceLoader;
private DockerContainerObjectFactory dockerContainerObjectFactory;
@AfterClass
public static void cleanEnvironment() {
deleteTestDirectory();
}
@Before
public void init() {
cubeRegistry = new LocalCubeRegistry();
dockerContainerObjectFactory = new DockerContainerObjectFactory();
cubeController = mock(CubeController.class);
dockerClientExecutor = mock(DockerClientExecutor.class);
injector = mock(Injector.class);
serviceLoader = mock(ServiceLoader.class);
when(serviceLoader.all(any(Class.class))).thenReturn(Collections.emptyList());
dockerContainerObjectFactory.serviceLoaderInstance = () -> serviceLoader;
dockerContainerObjectFactory.dockerClientExecutorInstance = () -> dockerClientExecutor;
dockerContainerObjectFactory.cubeRegistryInstance = () -> cubeRegistry;
dockerContainerObjectFactory.cubeControllerInstance = () -> cubeController;
dockerContainerObjectFactory.injectorInstance = () -> injector;
//We asure that there is no previous executions there.
deleteTestDirectory();
}
@Test
public void shouldStartAContainerObject() {
CubeContainerObjectTestEnricher cubeContainerObjectTestEnricher = new CubeContainerObjectTestEnricher();
cubeContainerObjectTestEnricher.containerObjectFactoryInstance = () -> dockerContainerObjectFactory;
when(serviceLoader.all(TestEnricher.class)).thenReturn(Arrays.asList(cubeContainerObjectTestEnricher));
InjectableTest injectableTest = new InjectableTest();
cubeContainerObjectTestEnricher.enrich(injectableTest);
final org.arquillian.cube.spi.Cube<?> mycontainer = cubeRegistry.getCube("mycontainer");
assertThat(mycontainer, is(notNullValue()));
assertThat(mycontainer.hasMetadata(IsContainerObject.class), is(true));
assertThat(mycontainer.getMetadata(IsContainerObject.class).getTestClass().getName(), is(InjectableTest.class.getName()));
verify(cubeController, times(1)).start("mycontainer");
verify(cubeController, times(1)).create("mycontainer");
}
@Test
public void shouldShouldStartAContainerObjectDefinedUsingDescriptor() {
CubeContainerObjectTestEnricher cubeContainerObjectTestEnricher = new CubeContainerObjectTestEnricher();
cubeContainerObjectTestEnricher.containerObjectFactoryInstance = () -> dockerContainerObjectFactory;
when(serviceLoader.all(TestEnricher.class)).thenReturn(Arrays.asList(cubeContainerObjectTestEnricher));
SecondInjectableTest secondInjectableTest = new SecondInjectableTest();
cubeContainerObjectTestEnricher.enrich(secondInjectableTest);
final org.arquillian.cube.spi.Cube<?> mycontainer = cubeRegistry.getCube("mycontainer2");
assertThat(mycontainer, is(notNullValue()));
verify(cubeController, times(1)).start("mycontainer2");
verify(cubeController, times(1)).create("mycontainer2");
final File generatedDirectory = findGeneratedDirectory();
assertThat(generatedDirectory, is(notNullValue()));
assertThat(new File(generatedDirectory, "Dockerfile").exists(), is(true));
}
@Test
public void shouldLinkInnerContainers() {
CubeContainerObjectTestEnricher cubeContainerObjectTestEnricher = new CubeContainerObjectTestEnricher();
cubeContainerObjectTestEnricher.containerObjectFactoryInstance = () -> dockerContainerObjectFactory;
when(serviceLoader.all(TestEnricher.class)).thenReturn(Arrays.asList(cubeContainerObjectTestEnricher));
ThirdInjetableTest thirdInjetableTest = new ThirdInjetableTest();
cubeContainerObjectTestEnricher.enrich(thirdInjetableTest);
final org.arquillian.cube.spi.Cube<?> outterContainer = cubeRegistry.getCube("outter");
assertThat(outterContainer, is(notNullValue()));
DockerCube dockerCube = (DockerCube) outterContainer;
final Collection<org.arquillian.cube.docker.impl.client.config.Link> links = dockerCube.configuration().getLinks();
assertThat(links.size(), is(1));
assertThat(links, hasItem(org.arquillian.cube.docker.impl.client.config.Link.valueOf("db:db")));
final org.arquillian.cube.spi.Cube<?> innerContainer = cubeRegistry.getCube("inner");
assertThat(innerContainer, is(notNullValue()));
verify(cubeController, times(1)).start("outter");
verify(cubeController, times(1)).create("outter");
verify(cubeController, times(1)).start("inner");
verify(cubeController, times(1)).create("inner");
}
@Test
public void shouldLinkInnerContainersWithoutLink() {
CubeContainerObjectTestEnricher cubeContainerObjectTestEnricher = new CubeContainerObjectTestEnricher();
cubeContainerObjectTestEnricher.containerObjectFactoryInstance = () -> dockerContainerObjectFactory;
when(serviceLoader.all(TestEnricher.class)).thenReturn(Arrays.asList(cubeContainerObjectTestEnricher));
FifthInjetableTest fifthInjetableTest = new FifthInjetableTest();
cubeContainerObjectTestEnricher.enrich(fifthInjetableTest);
final org.arquillian.cube.spi.Cube<?> outterContainer = cubeRegistry.getCube("outter");
assertThat(outterContainer, is(notNullValue()));
DockerCube dockerCube = (DockerCube) outterContainer;
final Collection<org.arquillian.cube.docker.impl.client.config.Link> links = dockerCube.configuration().getLinks();
assertThat(links.size(), is(1));
assertThat(links, hasItem(org.arquillian.cube.docker.impl.client.config.Link.valueOf("inner:inner")));
final org.arquillian.cube.spi.Cube<?> innerContainer = cubeRegistry.getCube("inner");
assertThat(innerContainer, is(notNullValue()));
verify(cubeController, times(1)).start("outter");
verify(cubeController, times(1)).create("outter");
verify(cubeController, times(1)).start("inner");
verify(cubeController, times(1)).create("inner");
}
@Test
public void shouldStartAContainerObjectDefinedAsImage() {
CubeContainerObjectTestEnricher cubeContainerObjectTestEnricher = new CubeContainerObjectTestEnricher();
cubeContainerObjectTestEnricher.containerObjectFactoryInstance = () -> dockerContainerObjectFactory;
when(serviceLoader.all(TestEnricher.class)).thenReturn(Arrays.asList(cubeContainerObjectTestEnricher));
FourthInjectableTest injectableTest = new FourthInjectableTest();
cubeContainerObjectTestEnricher.enrich(injectableTest);
final org.arquillian.cube.spi.Cube<?> image = cubeRegistry.getCube("image");
assertThat(image, is(notNullValue()));
assertThat(image.hasMetadata(IsContainerObject.class), is(true));
assertThat(image.getMetadata(IsContainerObject.class).getTestClass().getName(), is(FourthInjectableTest.class.getName()));
verify(cubeController, times(1)).start("image");
verify(cubeController, times(1)).create("image");
DockerCube dockerCube = (DockerCube) image;
assertThat(dockerCube.configuration().getImage().toImageRef(), is("tomee:8-jre-1.7.2-webprofile"));
}
@Test
public void shouldStartAContainerObjectDefinedAsImageAndEnvironmentVariables() {
CubeContainerObjectTestEnricher cubeContainerObjectTestEnricher = new CubeContainerObjectTestEnricher();
cubeContainerObjectTestEnricher.containerObjectFactoryInstance = () -> dockerContainerObjectFactory;
when(serviceLoader.all(TestEnricher.class)).thenReturn(Arrays.asList(cubeContainerObjectTestEnricher));
FifthInjectableTest injectableTest = new FifthInjectableTest();
cubeContainerObjectTestEnricher.enrich(injectableTest);
final org.arquillian.cube.spi.Cube<?> image = cubeRegistry.getCube("image");
assertThat(image, is(notNullValue()));
assertThat(image.hasMetadata(IsContainerObject.class), is(true));
assertThat(image.getMetadata(IsContainerObject.class).getTestClass().getName(), is(FifthInjectableTest.class.getName()));
verify(cubeController, times(1)).start("image");
verify(cubeController, times(1)).create("image");
DockerCube dockerCube = (DockerCube) image;
assertThat(dockerCube.configuration().getImage().toImageRef(), is("tomee:8-jre-1.7.2-webprofile"));
assertThat(dockerCube.configuration().getEnv(), hasItems("a=b", "c=d"));
}
@Test
public void shouldStartAContainerObjectDefinedAsImageAndVolumesVariables() {
CubeContainerObjectTestEnricher cubeContainerObjectTestEnricher = new CubeContainerObjectTestEnricher();
cubeContainerObjectTestEnricher.containerObjectFactoryInstance = () -> dockerContainerObjectFactory;
when(serviceLoader.all(TestEnricher.class)).thenReturn(Arrays.asList(cubeContainerObjectTestEnricher));
SixthInjectableTest injectableTest = new SixthInjectableTest();
cubeContainerObjectTestEnricher.enrich(injectableTest);
final org.arquillian.cube.spi.Cube<?> image = cubeRegistry.getCube("image");
assertThat(image, is(notNullValue()));
assertThat(image.hasMetadata(IsContainerObject.class), is(true));
assertThat(image.getMetadata(IsContainerObject.class).getTestClass().getName(), is(SixthInjectableTest.class.getName()));
verify(cubeController, times(1)).start("image");
verify(cubeController, times(1)).create("image");
DockerCube dockerCube = (DockerCube) image;
assertThat(dockerCube.configuration().getImage().toImageRef(), is("tomee:8-jre-1.7.2-webprofile"));
assertThat(dockerCube.configuration().getBinds(), hasItems("/mypath:/containerPath:rw", "/mypath2:/containerPath2:rw"));
}
private static class InjectableTest {
@Cube(value = "mycontainer")
TestContainerObject testContainerObject;
}
private static class SecondInjectableTest {
@Cube("mycontainer2")
TestInnerDockerfileContainerObject testInnerDockerfileContainerObject;
}
private static class ThirdInjetableTest {
@Cube("outter")
TestLinkedContainerObject testLinkedContainerObject;
}
private static class FifthInjetableTest {
@Cube("outter")
TestLinkedContainerObjectNoLink testLinkedContainerObjectNoLink;
}
private static class FourthInjectableTest {
@Cube("image")
ImageContainerObject imageContainerObject;
}
private static class FifthInjectableTest {
@Cube("image")
ImageWithEnvContainerObject imageContainerObject;
}
private static class SixthInjectableTest {
@Cube("image")
@Volume(hostPath = "/mypath2", containerPath = "/containerPath2")
VolumesContainerObject volumesContainerObject;
}
@CubeDockerFile
public static class TestContainerObject {
public TestContainerObject() {
}
}
public static class TestInnerDockerfileContainerObject {
@CubeDockerFile
public static Archive<?> createDockerfile() {
String dockerDescriptor = Descriptors.create(DockerDescriptor.class).from("tomee").exportAsString();
return ShrinkWrap.create(GenericArchive.class)
.add(new StringAsset(dockerDescriptor), "Dockerfile");
}
}
public static class TestLinkedContainerObject {
@CubeDockerFile
public static Archive<?> createDockerfile() {
String dockerDescriptor = Descriptors.create(DockerDescriptor.class).from("tomee").exportAsString();
return ShrinkWrap.create(GenericArchive.class)
.add(new StringAsset(dockerDescriptor), "Dockerfile");
}
@Cube("inner")
@Link("db:db")
TestLinkContainerObject linkContainerObject;
}
public static class TestLinkedContainerObjectNoLink {
@CubeDockerFile
public static Archive<?> createDockerfile() {
String dockerDescriptor = Descriptors.create(DockerDescriptor.class).from("tomee").exportAsString();
return ShrinkWrap.create(GenericArchive.class)
.add(new StringAsset(dockerDescriptor), "Dockerfile");
}
@Cube("inner")
TestLinkContainerObject linkContainerObject;
}
@Image("tomee:8-jre-1.7.2-webprofile")
public static class ImageContainerObject {
}
@Image("tomee:8-jre-1.7.2-webprofile")
@Environment(key = "a", value = "b")
@Environment(key = "c", value = "d")
public static class ImageWithEnvContainerObject {
}
@Image("tomee:8-jre-1.7.2-webprofile")
@Volume(hostPath = "/mypath", containerPath = "/containerPath")
public static class VolumesContainerObject{
}
public static class TestLinkContainerObject {
@CubeDockerFile
public static Archive<?> createDockerfile() {
String dockerDescriptor = Descriptors.create(DockerDescriptor.class).from("mysql").exportAsString();
return ShrinkWrap.create(GenericArchive.class)
.add(new StringAsset(dockerDescriptor), "Dockerfile");
}
}
private static void deleteTestDirectory() {
File tempDirectory = new File(System.getProperty("java.io.tmpdir"));
final File[] testsDirectories = tempDirectory.listFiles(CubeContainerObjectTestEnricherTest::testDirectoryFilter);
for (File testDirectory: testsDirectories) {
try {
FileUtils.deleteDirectory(testDirectory);
} catch (IOException e) {
// ignore
}
}
}
private static File findGeneratedDirectory() {
File tempDirectory = new File(System.getProperty("java.io.tmpdir"));
final File[] testsDirectories = tempDirectory.listFiles(CubeContainerObjectTestEnricherTest::testDirectoryFilter);
if (testsDirectories.length > 0) {
return testsDirectories[0];
} else {
return null;
}
}
private static boolean testDirectoryFilter(File dir, String name) {
return dir.isDirectory()
&& name.startsWith(DockerContainerObjectBuilder.TEMPORARY_FOLDER_PREFIX)
&& name.endsWith(DockerContainerObjectBuilder.TEMPORARY_FOLDER_SUFFIX);
}
}