/** * Copyright 2016-2017 Linagora, Université Joseph Fourier, Floralis * * The present code is developed in the scope of the joint LINAGORA - * Université Joseph Fourier - Floralis research program and is designated * as a "Result" pursuant to the terms and conditions of the LINAGORA * - Université Joseph Fourier - Floralis research program. Each copyright * holder of Results enumerated here above fully & independently holds complete * ownership of the complete Intellectual Property rights applicable to the whole * of said Results, and may freely exploit it in any manner which does not infringe * the moral rights of the other copyright holders. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.roboconf.target.docker.internal; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import net.roboconf.target.api.TargetException; import net.roboconf.target.docker.internal.DockerMachineConfigurator.RoboconfBuildImageResultCallback; import net.roboconf.target.docker.internal.DockerMachineConfigurator.RoboconfPullImageResultCallback; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.BuildImageCmd; import com.github.dockerjava.api.command.ListImagesCmd; import com.github.dockerjava.api.command.PullImageCmd; import com.github.dockerjava.api.model.Image; /** * @author Vincent Zurczak - Linagora */ public class DockerMachineConfiguratorTest { private DockerfileGenerator dockerfileGenerator; private DockerClient dockerClient; private DockerMachineConfigurator configurator; private Map<String,String> targetProperties; @Before public void prepareConfigurator() { this.targetProperties = new HashMap<> (); this.configurator = new DockerMachineConfigurator( this.targetProperties, new HashMap<String,String>( 0 ), "machineId", "scopedInstancePath", "applicationName", null ); this.configurator = Mockito.spy( this.configurator ); this.configurator.dockerClient = Mockito.mock( DockerClient.class ); this.dockerClient = this.configurator.dockerClient; this.dockerfileGenerator = Mockito.mock( DockerfileGenerator.class ); Mockito.when( this.configurator.dockerfileGenerator( Mockito.anyString(), Mockito.anyString(), Mockito.anyListOf( String.class ), Mockito.anyString())).thenReturn( this.dockerfileGenerator ); } @Test public void testFixImageId() { Assert.assertEquals( DockerMachineConfigurator.DEFAULT_IMG_NAME, DockerMachineConfigurator.fixImageId( null )); Assert.assertEquals( DockerMachineConfigurator.DEFAULT_IMG_NAME, DockerMachineConfigurator.fixImageId( " " )); Assert.assertEquals( "test1", DockerMachineConfigurator.fixImageId( "test1" )); } @Test public void testClose() throws Exception { Mockito.verifyZeroInteractions( this.dockerfileGenerator ); Mockito.verifyZeroInteractions( this.dockerClient ); this.configurator.close(); Mockito.verify( this.dockerClient, Mockito.times( 1 )).close(); } @Test public void testCreateImage_noDownload_noBaseImage_withAgentPackage() throws Exception { // No base image, agent URL specified, no download required. // => no error. // => no request to download an image. this.targetProperties.put( DockerHandler.AGENT_PACKAGE_URL, "file://somewhere" ); BuildImageCmd buildImageCmd = Mockito.mock( BuildImageCmd.class ); Mockito.when( this.dockerClient.buildImageCmd( Mockito.any( File.class ))).thenReturn( buildImageCmd ); Mockito.when( buildImageCmd.withTag( Mockito.anyString())).thenReturn( buildImageCmd ); RoboconfBuildImageResultCallback callback = Mockito.mock( RoboconfBuildImageResultCallback.class ); Mockito.when( buildImageCmd.exec( Mockito.any( RoboconfBuildImageResultCallback.class ))).thenReturn( callback ); Mockito.when( callback.awaitImageId()).thenReturn( "xxxx" ); this.configurator.createImage( "invalid" ); Mockito.verify( this.dockerClient, Mockito.never()).pullImageCmd( Mockito.anyString()); } @Test( expected = TargetException.class ) public void testCreateImage_withErrorOnCreation() throws Exception { // No base image, agent URL specified, no download required. // => no error. // => no request to download an image. this.targetProperties.put( DockerHandler.AGENT_PACKAGE_URL, "file://somewhere" ); BuildImageCmd buildImageCmd = Mockito.mock( BuildImageCmd.class ); Mockito.when( this.dockerClient.buildImageCmd( Mockito.any( File.class ))).thenReturn( buildImageCmd ); Mockito.when( buildImageCmd.withTag( Mockito.anyString())).thenReturn( buildImageCmd ); RoboconfBuildImageResultCallback callback = Mockito.mock( RoboconfBuildImageResultCallback.class ); Mockito.when( buildImageCmd.exec( Mockito.any( RoboconfBuildImageResultCallback.class ))).thenReturn( callback ); // We simply simulate the occurrence of an exception at the end. Mockito.when( callback.awaitImageId()).thenThrow( new RuntimeException( "for test" )); this.configurator.createImage( "invalid" ); } @Test public void testCreateImage_noDownload_withBaseImage_notFound_withAgentPackage() throws Exception { // A base image and the agent URL are specified, no download required. // The image is not found => error. this.targetProperties.put( DockerHandler.AGENT_PACKAGE_URL, "file://somewhere" ); this.targetProperties.put( DockerHandler.BASE_IMAGE, "something" ); this.targetProperties.put( DockerHandler.DOWNLOAD_BASE_IMAGE, "false" ); // This section deals with the (successful) creation of an image. BuildImageCmd buildImageCmd = Mockito.mock( BuildImageCmd.class ); Mockito.when( this.dockerClient.buildImageCmd( Mockito.any( File.class ))).thenReturn( buildImageCmd ); Mockito.when( buildImageCmd.withTag( Mockito.anyString())).thenReturn( buildImageCmd ); RoboconfBuildImageResultCallback callback = Mockito.mock( RoboconfBuildImageResultCallback.class ); Mockito.when( buildImageCmd.exec( Mockito.any( RoboconfBuildImageResultCallback.class ))).thenReturn( callback ); Mockito.when( callback.awaitImageId()).thenReturn( "xxxx" ); // End of section // Make sure the image is not found. ListImagesCmd listImagesCmd = Mockito.mock( ListImagesCmd.class ); Mockito.when( this.dockerClient.listImagesCmd()).thenReturn( listImagesCmd ); Mockito.when( listImagesCmd.exec()).thenReturn( new ArrayList<Image>( 0 )); try { this.configurator.createImage( "invalid" ); Assert.fail( "Creation should have failed. The base image was not supposed to be found." ); } catch( Exception e ) { // nothing } // We did not try to download anything Mockito.verify( this.dockerClient, Mockito.never()).pullImageCmd( Mockito.anyString()); } @Test public void testCreateImage_withDownload_withBaseImage_notFound_withAgentPackage() throws Exception { // A base image and the agent URL are specified, download is required. // By the end, the image will not be found. => error. this.targetProperties.put( DockerHandler.AGENT_PACKAGE_URL, "file://somewhere" ); this.targetProperties.put( DockerHandler.BASE_IMAGE, "something" ); this.targetProperties.put( DockerHandler.DOWNLOAD_BASE_IMAGE, "true" ); // This section deals with the (successful) creation of an image. BuildImageCmd buildImageCmd = Mockito.mock( BuildImageCmd.class ); Mockito.when( this.dockerClient.buildImageCmd( Mockito.any( File.class ))).thenReturn( buildImageCmd ); Mockito.when( buildImageCmd.withTag( Mockito.anyString())).thenReturn( buildImageCmd ); RoboconfBuildImageResultCallback callback = Mockito.mock( RoboconfBuildImageResultCallback.class ); Mockito.when( buildImageCmd.exec( Mockito.any( RoboconfBuildImageResultCallback.class ))).thenReturn( callback ); Mockito.when( callback.awaitImageId()).thenReturn( "xxxx" ); // End of section // Make sure the image is not found. ListImagesCmd listImagesCmd = Mockito.mock( ListImagesCmd.class ); Mockito.when( this.dockerClient.listImagesCmd()).thenReturn( listImagesCmd ); Mockito.when( listImagesCmd.exec()).thenReturn( new ArrayList<Image>( 0 )); // Make sure there is no error thrown by the pull request. ArgumentCaptor<String> tagArg = ArgumentCaptor.forClass( String.class ); ArgumentCaptor<String> imageNameArg = ArgumentCaptor.forClass( String.class ); PullImageCmd pullImageCmd = Mockito.mock( PullImageCmd.class ); Mockito.when( this.dockerClient.pullImageCmd( imageNameArg.capture())).thenReturn( pullImageCmd ); Mockito.when( pullImageCmd.withRegistry( Mockito.anyString())).thenReturn( pullImageCmd ); Mockito.when( pullImageCmd.withTag( tagArg.capture())).thenReturn( pullImageCmd ); RoboconfPullImageResultCallback pullCallback = Mockito.mock( RoboconfPullImageResultCallback.class ); Mockito.when( pullImageCmd.exec( Mockito.any( RoboconfPullImageResultCallback.class ))).thenReturn( pullCallback ); // Execution try { this.configurator.createImage( "invalid" ); Assert.fail( "Creation should have failed. The base image was not supposed to be found." ); } catch( Exception e ) { // nothing } // We tried to download something Mockito.verify( this.dockerClient, Mockito.times( 1 )).pullImageCmd( Mockito.anyString()); Assert.assertEquals( "something", imageNameArg.getValue()); Assert.assertEquals( 0, tagArg.getAllValues().size()); // Try with an image name using a tag this.targetProperties.put( DockerHandler.BASE_IMAGE, "something:else" ); try { this.configurator.createImage( "invalid" ); Assert.fail( "Creation should have failed. The base image was not supposed to be found." ); } catch( Exception e ) { // nothing } // We tried to download something Mockito.verify( this.dockerClient, Mockito.times( 2 )).pullImageCmd( Mockito.anyString()); Assert.assertEquals( "something", imageNameArg.getValue()); Assert.assertEquals( "else", tagArg.getValue()); } @Test( expected = TargetException.class ) public void testCreateImage_withDownload_withBaseImage_withAgentPackage_withErrorOnPull() throws Exception { // A base image and the agent URL are specified, download is required. // By the end, the image will not be found. => error. this.targetProperties.put( DockerHandler.AGENT_PACKAGE_URL, "file://somewhere" ); this.targetProperties.put( DockerHandler.BASE_IMAGE, "something" ); this.targetProperties.put( DockerHandler.DOWNLOAD_BASE_IMAGE, "true" ); // Make sure the image is not found. ListImagesCmd listImagesCmd = Mockito.mock( ListImagesCmd.class ); Mockito.when( this.dockerClient.listImagesCmd()).thenReturn( listImagesCmd ); Mockito.when( listImagesCmd.exec()).thenReturn( new ArrayList<Image>( 0 )); // Normal flow for the pull request. ArgumentCaptor<String> tagArg = ArgumentCaptor.forClass( String.class ); ArgumentCaptor<String> imageNameArg = ArgumentCaptor.forClass( String.class ); PullImageCmd pullImageCmd = Mockito.mock( PullImageCmd.class ); Mockito.when( this.dockerClient.pullImageCmd( imageNameArg.capture())).thenReturn( pullImageCmd ); Mockito.when( pullImageCmd.withRegistry( Mockito.anyString())).thenReturn( pullImageCmd ); Mockito.when( pullImageCmd.withTag( tagArg.capture())).thenReturn( pullImageCmd ); // Execution => exception. Mockito.when( pullImageCmd.exec( Mockito.any( RoboconfPullImageResultCallback.class ))).thenThrow( new RuntimeException( "for test" )); this.configurator.createImage( "invalid" ); } }