/**
* Copyright 2015-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.dm.internal.api.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import net.roboconf.core.internal.tests.TestApplication;
import net.roboconf.core.model.beans.Application;
import net.roboconf.core.model.beans.Instance;
import net.roboconf.core.model.beans.Instance.InstanceStatus;
import net.roboconf.core.model.runtime.EventType;
import net.roboconf.dm.internal.api.IRandomMngr;
import net.roboconf.dm.internal.api.ITargetConfigurator;
import net.roboconf.dm.internal.test.TestTargetResolver;
import net.roboconf.dm.management.ManagedApplication;
import net.roboconf.dm.management.api.IConfigurationMngr;
import net.roboconf.dm.management.api.IInstancesMngr;
import net.roboconf.dm.management.api.IMessagingMngr;
import net.roboconf.dm.management.api.INotificationMngr;
import net.roboconf.dm.management.api.ITargetHandlerResolver;
import net.roboconf.dm.management.api.ITargetsMngr;
import net.roboconf.messaging.api.business.IDmClient;
import net.roboconf.messaging.api.messages.Message;
import net.roboconf.messaging.api.messages.from_dm_to_agent.MsgCmdSendInstances;
import net.roboconf.target.api.TargetException;
import net.roboconf.target.api.TargetHandler;
import net.roboconf.target.api.TargetHandlerParameters;
/**
* @author Vincent Zurczak - Linagora
*/
public class InstancesMngrImplTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void testProcessExceptions_noException() throws Exception {
Logger logger = Logger.getLogger( getClass().getName());
List<Exception> exceptions = new ArrayList<>( 0 );
InstancesMngrImpl.processExceptions( logger, exceptions, "whatever" );
}
@Test( expected = IOException.class )
public void testProcessExceptions_withException() throws Exception {
Logger logger = Logger.getLogger( getClass().getName());
List<Exception> exceptions = new ArrayList<>( 1 );
exceptions.add( new Exception( "oops" ));
InstancesMngrImpl.processExceptions( logger, exceptions, "whatever" );
}
@Test
public void testNotificationsWhenUndeployingScopedInstances_changeInstanceState() throws Exception {
// Prepare stuff
final TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
final Map<Instance,List<InstanceStatus>> instanceToStatusHistory = new HashMap<> ();
INotificationMngr notificationMngr = new NotificationMngrImpl() {
@Override
public void instance( Instance instance, Application application, EventType eventType ) {
Assert.assertEquals( EventType.CHANGED, eventType );
Assert.assertEquals( app, application );
List<InstanceStatus> status = instanceToStatusHistory.get( instance );
if( status == null ) {
status = new ArrayList<> ();
instanceToStatusHistory.put( instance, status );
}
status.add( instance.getStatus());
}
};
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
Mockito.when( messagingMngr.getMessagingClient()).thenReturn( Mockito.mock( IDmClient.class ));
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( new TestTargetResolver());
// Make one of our VM being fully deployed
ManagedApplication ma = new ManagedApplication( app );
app.getTomcatVm().setStatus( InstanceStatus.DEPLOYED_STARTED );
app.getTomcat().setStatus( InstanceStatus.DEPLOYED_STARTED );
app.getWar().setStatus( InstanceStatus.DEPLOYED_STARTED );
// One scoped instance has a machine ID (considered as running somewhere)
app.getTomcatVm().data.put( Instance.MACHINE_ID, "machine-id" );
// Stop everything
mngr.changeInstanceState( ma, app.getTomcatVm(), InstanceStatus.NOT_DEPLOYED );
// Check notifications
Assert.assertEquals( 3, instanceToStatusHistory.size());
List<InstanceStatus> statusHistory = instanceToStatusHistory.get( app.getTomcatVm());
Assert.assertNotNull( statusHistory );
Assert.assertEquals( Arrays.asList( InstanceStatus.UNDEPLOYING, InstanceStatus.NOT_DEPLOYED ), statusHistory );
statusHistory = instanceToStatusHistory.get( app.getTomcat());
Assert.assertNotNull( statusHistory );
Assert.assertEquals( Arrays.asList( InstanceStatus.NOT_DEPLOYED ), statusHistory );
statusHistory = instanceToStatusHistory.get( app.getWar());
Assert.assertNotNull( statusHistory );
Assert.assertEquals( Arrays.asList( InstanceStatus.NOT_DEPLOYED ), statusHistory );
Mockito.verify( targetConfigurator, Mockito.only()).cancelCandidate(
Mockito.any( TargetHandlerParameters.class ),
Mockito.eq( app.getTomcatVm()));
}
@Test
public void testNotificationsWhenUndeployingScopedInstances_undeployAll() throws Exception {
// Prepare stuff
final TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
final Map<Instance,List<InstanceStatus>> instanceToStatusHistory = new HashMap<> ();
INotificationMngr notificationMngr = new NotificationMngrImpl() {
@Override
public void instance( Instance instance, Application application, EventType eventType ) {
Assert.assertEquals( EventType.CHANGED, eventType );
Assert.assertEquals( app, application );
List<InstanceStatus> status = instanceToStatusHistory.get( instance );
if( status == null ) {
status = new ArrayList<> ();
instanceToStatusHistory.put( instance, status );
}
status.add( instance.getStatus());
}
};
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
Mockito.when( messagingMngr.getMessagingClient()).thenReturn( Mockito.mock( IDmClient.class ));
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( new TestTargetResolver());
// Make one of our VM being fully deployed
ManagedApplication ma = new ManagedApplication( app );
app.getTomcatVm().setStatus( InstanceStatus.DEPLOYED_STARTED );
app.getTomcat().setStatus( InstanceStatus.DEPLOYED_STARTED );
app.getWar().setStatus( InstanceStatus.DEPLOYED_STARTED );
// One scoped instance has a machine ID (considered as running somewhere)
app.getTomcatVm().data.put( Instance.MACHINE_ID, "machine-id" );
// Stop everything
mngr.undeployAll( ma, app.getTomcatVm());
// Check notifications
Assert.assertEquals( 3, instanceToStatusHistory.size());
List<InstanceStatus> statusHistory = instanceToStatusHistory.get( app.getTomcatVm());
Assert.assertNotNull( statusHistory );
Assert.assertEquals( Arrays.asList( InstanceStatus.UNDEPLOYING, InstanceStatus.NOT_DEPLOYED ), statusHistory );
statusHistory = instanceToStatusHistory.get( app.getTomcat());
Assert.assertNotNull( statusHistory );
Assert.assertEquals( Arrays.asList( InstanceStatus.NOT_DEPLOYED ), statusHistory );
statusHistory = instanceToStatusHistory.get( app.getWar());
Assert.assertNotNull( statusHistory );
Assert.assertEquals( Arrays.asList( InstanceStatus.NOT_DEPLOYED ), statusHistory );
Mockito.verify( targetConfigurator, Mockito.only()).cancelCandidate(
Mockito.any( TargetHandlerParameters.class ),
Mockito.eq( app.getTomcatVm()));
}
@Test
public void testTargetsLocking_whenCreatingMachines_noException() throws Exception {
// Prepare stuff
INotificationMngr notificationMngr = Mockito.mock( INotificationMngr.class );
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
Mockito.when( messagingMngr.getMessagingClient()).thenReturn( Mockito.mock( IDmClient.class ));
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( new TestTargetResolver());
TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
ManagedApplication ma = new ManagedApplication( app );
// We want to make sure target locking is correctly invoked by the instances manager.
// So, we store requests to lock or unlock a target for a given instance.
final Map<Instance,Integer> instancePathToLock = new HashMap<> ();
Mockito.when( targetsMngr.lockAndGetTarget( app, app.getMySqlVm())).thenAnswer( new Answer<Map<String,String>>() {
@Override
public Map<String,String> answer( InvocationOnMock invocation ) throws Throwable {
Instance inst = invocation.getArgumentAt( 1, Instance.class );
Integer count = instancePathToLock.get( inst );
count = count == null ? 1 : count + 1;
instancePathToLock.put( inst, count );
Map<String,String> result = new HashMap<>( 0 );
return result;
}
});
Mockito.doAnswer( new Answer<Object>() {
@Override
public Object answer( InvocationOnMock invocation ) throws Throwable {
Instance inst = invocation.getArgumentAt( 1, Instance.class );
Integer count = instancePathToLock.get( inst );
count = count == null ? 0 : count - 1;
if( count > 0 )
instancePathToLock.put( inst, count );
else
instancePathToLock.remove( inst );
return null;
}
}).when( targetsMngr ).unlockTarget( app, app.getMySqlVm());
// Let's run assertions now
Assert.assertEquals( 0, instancePathToLock.size());
Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app.getMySqlVm().getStatus());
mngr.changeInstanceState( ma, app.getMySqlVm(), InstanceStatus.DEPLOYED_STARTED );
Assert.assertEquals( 1, instancePathToLock.size());
Integer lockCount = instancePathToLock.get( app.getMySqlVm());
Assert.assertNotNull( lockCount );
Assert.assertEquals( 1, lockCount.intValue());
Assert.assertEquals( InstanceStatus.DEPLOYING, app.getMySqlVm().getStatus());
Mockito.verify( targetConfigurator ).reportCandidate(
Mockito.any( TargetHandlerParameters.class ),
Mockito.eq( app.getMySqlVm()));
// Release the machine
mngr.changeInstanceState( ma, app.getMySqlVm(), InstanceStatus.NOT_DEPLOYED );
Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app.getMySqlVm().getStatus());
Assert.assertEquals( 0, instancePathToLock.size());
}
@Test
public void testTargetsLocking_whenCreatingMachines_withExceptionInDeploy() throws Exception {
// Prepare stuff
INotificationMngr notificationMngr = Mockito.mock( INotificationMngr.class );
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
Mockito.when( messagingMngr.getMessagingClient()).thenReturn( Mockito.mock( IDmClient.class ));
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
final TargetHandler targetHandler = Mockito.mock( TargetHandler.class );
Mockito.when( targetHandler
.createMachine( Mockito.any( TargetHandlerParameters.class )))
.thenThrow( new TargetException( "for test" ));
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( new TestTargetResolver() {
@Override
public TargetHandler findTargetHandler( Map<String,String> targetProperties ) throws TargetException {
return targetHandler;
}
});
TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
ManagedApplication ma = new ManagedApplication( app );
// We will try to create a machine. It will fail.
// We must be sure the lock was acquired, and that it was released.
final AtomicBoolean acquired = new AtomicBoolean( false );
final AtomicBoolean released = new AtomicBoolean( false );
Mockito.when( targetsMngr.lockAndGetTarget( app, app.getMySqlVm())).thenAnswer( new Answer<Map<String,String>>() {
@Override
public Map<String,String> answer( InvocationOnMock invocation ) throws Throwable {
acquired.set( true );
Map<String,String> result = new HashMap<>( 0 );
return result;
}
});
Mockito.doAnswer( new Answer<Object>() {
@Override
public Object answer( InvocationOnMock invocation ) throws Throwable {
released.set( true );
return null;
}
}).when( targetsMngr ).unlockTarget( app, app.getMySqlVm());
// Let's run assertions now
Assert.assertFalse( acquired.get());
Assert.assertFalse( released.get());
Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app.getMySqlVm().getStatus());
try {
mngr.changeInstanceState( ma, app.getMySqlVm(), InstanceStatus.DEPLOYED_STARTED );
Assert.fail( "A target exception was expected." );
} catch( Exception e ) {
// nothing
}
Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app.getMySqlVm().getStatus());
Assert.assertTrue( acquired.get());
Assert.assertTrue( released.get());
// Since the handler failed, nothing was scheduled for post-configuration
Mockito.verifyZeroInteractions( targetConfigurator );
}
@Test
public void testRestoreInstances_nullHandler() throws Exception {
// Prepare stuff
INotificationMngr notificationMngr = Mockito.mock( INotificationMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
Mockito.when( targetsMngr.findRawTargetProperties(
Mockito.any( Application.class ),
Mockito.anyString())).thenReturn( new HashMap<String,String>( 0 ));
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
final TargetHandler targetHandlerArgument = Mockito.mock( TargetHandler.class );
Mockito.when( targetHandlerArgument.getTargetId()).thenReturn( "some target id" );
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( new TestTargetResolver() {
@Override
public TargetHandler findTargetHandler( Map<String,String> targetProperties ) throws TargetException {
throw new TargetException( "No handler for tests" );
}
});
TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
ManagedApplication ma = new ManagedApplication( app );
// One scoped instance has a machine ID (considered as running somewhere)
app.getMySqlVm().data.put( Instance.MACHINE_ID, "machine-id" );
// Try to restore instances
mngr.restoreInstanceStates( ma, targetHandlerArgument );
// The handler's ID did not match => no restoration and no use of other mocks
Mockito.verify( targetsMngr ).findRawTargetProperties( Mockito.eq( app ), Mockito.anyString());
Mockito.verify( targetsMngr ).unlockTarget( Mockito.eq( app ), Mockito.eq( app.getTomcatVm()));
Mockito.verifyNoMoreInteractions( targetsMngr );
Mockito.verifyZeroInteractions( targetHandlerArgument );
Mockito.verifyZeroInteractions( messagingMngr );
Mockito.verifyZeroInteractions( randomMngr );
// No notification was sent since there was no change on Tomcat instances
Mockito.verifyZeroInteractions( notificationMngr );
Mockito.verifyZeroInteractions( targetConfigurator );
}
@Test
public void testRestoreInstances_nonNullNonMatchingHandler() throws Exception {
// Prepare stuff
INotificationMngr notificationMngr = Mockito.mock( INotificationMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
Mockito.when( targetsMngr.findRawTargetProperties(
Mockito.any( Application.class ),
Mockito.anyString())).thenReturn( new HashMap<String,String>( 0 ));
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
final TargetHandler targetHandlerArgument = Mockito.mock( TargetHandler.class );
Mockito.when( targetHandlerArgument.getTargetId()).thenReturn( "some target id" );
final TargetHandler targetHandler = Mockito.mock( TargetHandler.class );
Mockito.when( targetHandler.getTargetId()).thenReturn( "some other target id" );
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( new TestTargetResolver() {
@Override
public TargetHandler findTargetHandler( Map<String,String> targetProperties ) throws TargetException {
return targetHandler;
}
});
TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
ManagedApplication ma = new ManagedApplication( app );
// One scoped instance has a machine ID (considered as running somewhere)
app.getMySqlVm().data.put( Instance.MACHINE_ID, "machine-id" );
// Try to restore instances
mngr.restoreInstanceStates( ma, targetHandlerArgument );
// The handler's ID did not match => no restoration and no use of other mocks
Mockito.verify( targetsMngr ).findRawTargetProperties( Mockito.eq( app ), Mockito.anyString());
Mockito.verify( targetsMngr ).unlockTarget( Mockito.eq( app ), Mockito.eq( app.getTomcatVm()));
Mockito.verifyNoMoreInteractions( targetsMngr );
Mockito.verify( targetHandler, Mockito.only()).getTargetId();
Mockito.verify( targetHandlerArgument, Mockito.only()).getTargetId();
Mockito.verifyZeroInteractions( messagingMngr );
Mockito.verifyZeroInteractions( randomMngr );
// No notification was sent since there was no change on Tomcat instances
Mockito.verifyZeroInteractions( notificationMngr );
Mockito.verifyZeroInteractions( targetConfigurator );
}
@Test
public void testRestoreInstances_rightHandler_vmRunning() throws Exception {
// Prepare stuff
Map<String,String> targetProperties = new HashMap<>( 0 );
INotificationMngr notificationMngr = Mockito.mock( INotificationMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
Mockito.when( messagingMngr.getMessagingClient()).thenReturn( Mockito.mock( IDmClient.class ));
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
Mockito.when( targetsMngr.findRawTargetProperties(
Mockito.any( Application.class ),
Mockito.anyString())).thenReturn( targetProperties );
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
final TargetHandler targetHandlerArgument = Mockito.mock( TargetHandler.class );
Mockito.when( targetHandlerArgument.getTargetId()).thenReturn( "some target id" );
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( new TestTargetResolver() {
@Override
public TargetHandler findTargetHandler( Map<String,String> targetProperties ) throws TargetException {
return targetHandlerArgument;
}
});
TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
ManagedApplication ma = new ManagedApplication( app );
// One scoped instance has a machine ID (considered as running somewhere)
app.getMySqlVm().data.put( Instance.MACHINE_ID, "machine-id" );
app.getMySqlVm().setStatus( InstanceStatus.DEPLOYING );
// Try to restore instances
Assert.assertEquals( InstanceStatus.DEPLOYING, app.getMySqlVm().getStatus());
Mockito.when( targetHandlerArgument.isMachineRunning(
Mockito.any( TargetHandlerParameters.class ),
Mockito.eq( "machine-id" ))).thenReturn( true );
mngr.restoreInstanceStates( ma, targetHandlerArgument );
Assert.assertEquals( InstanceStatus.DEPLOYING, app.getMySqlVm().getStatus());
// The handler's ID matched and the VM is running => a message was sent.
Mockito.verify( targetsMngr ).findRawTargetProperties( Mockito.eq( app ), Mockito.anyString());
Mockito.verify( targetsMngr ).findScriptForDm( Mockito.eq( app ), Mockito.eq( app.getMySqlVm()));
Mockito.verify( targetsMngr ).unlockTarget( Mockito.eq( app ), Mockito.eq( app.getTomcatVm()));
Mockito.verifyNoMoreInteractions( targetsMngr );
Mockito.verify( targetHandlerArgument, Mockito.times( 1 )).isMachineRunning(
Mockito.any( TargetHandlerParameters.class ),
Mockito.eq( "machine-id" ));
Mockito.verify( messagingMngr ).getMessagingClient();
Mockito.verify( messagingMngr ).sendMessageDirectly(
Mockito.eq( ma ),
Mockito.eq( app.getMySqlVm() ),
Mockito.any( MsgCmdSendInstances.class ));
Mockito.verifyNoMoreInteractions( messagingMngr );
// No notification was sent since there was no change on Tomcat instances
Mockito.verifyZeroInteractions( notificationMngr );
Mockito.verifyZeroInteractions( randomMngr );
Mockito.verifyZeroInteractions( targetConfigurator );
}
@Test
public void testRestoreInstances_rightHandler_vmRunning_withMessagingException() throws Exception {
// Prepare stuff
Map<String,String> targetProperties = new HashMap<>( 0 );
INotificationMngr notificationMngr = Mockito.mock( INotificationMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
Mockito.when( targetsMngr.findRawTargetProperties(
Mockito.any( Application.class ),
Mockito.anyString())).thenReturn( targetProperties );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
Mockito.when( messagingMngr.getMessagingClient()).thenReturn( Mockito.mock( IDmClient.class ));
Mockito.doThrow( new IOException( "for test" )).when( messagingMngr ).sendMessageDirectly(
Mockito.any( ManagedApplication.class ),
Mockito.any( Instance.class ),
Mockito.any( Message.class ));
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
final TargetHandler targetHandlerArgument = Mockito.mock( TargetHandler.class );
Mockito.when( targetHandlerArgument.getTargetId()).thenReturn( "some target id" );
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( new TestTargetResolver() {
@Override
public TargetHandler findTargetHandler( Map<String,String> targetProperties ) throws TargetException {
return targetHandlerArgument;
}
});
TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
ManagedApplication ma = new ManagedApplication( app );
// One scoped instance has a machine ID (considered as running somewhere)
app.getMySqlVm().data.put( Instance.MACHINE_ID, "machine-id" );
app.getMySqlVm().setStatus( InstanceStatus.DEPLOYING );
// Try to restore instances
Assert.assertEquals( InstanceStatus.DEPLOYING, app.getMySqlVm().getStatus());
Mockito.when( targetHandlerArgument.isMachineRunning(
Mockito.any( TargetHandlerParameters.class ),
Mockito.eq( "machine-id" ))).thenReturn( true );
mngr.restoreInstanceStates( ma, targetHandlerArgument );
Assert.assertEquals( InstanceStatus.DEPLOYING, app.getMySqlVm().getStatus());
// The handler's ID matched and the VM is running => a message was sent.
Mockito.verify( targetsMngr ).findRawTargetProperties( Mockito.eq( app ), Mockito.anyString());
Mockito.verify( targetsMngr ).findScriptForDm( Mockito.eq( app ), Mockito.eq( app.getMySqlVm()));
Mockito.verify( targetsMngr ).unlockTarget( Mockito.eq( app ), Mockito.eq( app.getTomcatVm()));
Mockito.verifyNoMoreInteractions( targetsMngr );
Mockito.verify( targetHandlerArgument, Mockito.times( 1 )).isMachineRunning(
Mockito.any( TargetHandlerParameters.class ),
Mockito.eq( "machine-id" ));
Mockito.verify( messagingMngr ).getMessagingClient();
Mockito.verify( messagingMngr ).sendMessageDirectly(
Mockito.eq( ma ),
Mockito.eq( app.getMySqlVm() ),
Mockito.any( MsgCmdSendInstances.class ));
Mockito.verifyNoMoreInteractions( messagingMngr );
// No notification was sent since there was no change on Tomcat instances
Mockito.verifyZeroInteractions( notificationMngr );
Mockito.verifyZeroInteractions( randomMngr );
Mockito.verifyZeroInteractions( targetConfigurator );
}
@Test
public void testRestoreInstances_rightHandler_vmNotRunning() throws Exception {
// Prepare stuff
Map<String,String> targetProperties = new HashMap<>( 0 );
INotificationMngr notificationMngr = Mockito.mock( INotificationMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
Mockito.when( messagingMngr.getMessagingClient()).thenReturn( Mockito.mock( IDmClient.class ));
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
Mockito.when( targetsMngr.findRawTargetProperties(
Mockito.any( Application.class ),
Mockito.anyString())).thenReturn( targetProperties );
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
final TargetHandler targetHandlerArgument = Mockito.mock( TargetHandler.class );
Mockito.when( targetHandlerArgument.getTargetId()).thenReturn( "some target id" );
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( new TestTargetResolver() {
@Override
public TargetHandler findTargetHandler( Map<String,String> targetProperties ) throws TargetException {
return targetHandlerArgument;
}
});
TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
ManagedApplication ma = new ManagedApplication( app );
// One scoped instance has a machine ID (considered as running somewhere)
app.getMySqlVm().data.put( Instance.MACHINE_ID, "machine-id" );
// Try to restore instances
Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app.getMySqlVm().getStatus());
app.getMySqlVm().setStatus( InstanceStatus.DEPLOYED_STARTED );
Mockito.when( targetHandlerArgument.isMachineRunning(
Mockito.any( TargetHandlerParameters.class ),
Mockito.eq( "machine-id" ))).thenReturn( false );
mngr.restoreInstanceStates( ma, targetHandlerArgument );
Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app.getMySqlVm().getStatus());
// The handler's ID matched and the VM is NOT running => no message was sent.
Mockito.verify( targetsMngr ).findRawTargetProperties( Mockito.eq( app ), Mockito.anyString());
Mockito.verify( targetsMngr ).unlockTarget( Mockito.eq( app ), Mockito.eq( app.getMySqlVm()));
Mockito.verify( targetsMngr ).unlockTarget( Mockito.eq( app ), Mockito.eq( app.getTomcatVm()));
Mockito.verify( targetsMngr ).findScriptForDm( Mockito.eq( app ), Mockito.eq( app.getMySqlVm()));
Mockito.verifyNoMoreInteractions( targetsMngr );
Mockito.verify( targetHandlerArgument, Mockito.times( 1 )).isMachineRunning(
Mockito.any( TargetHandlerParameters.class ),
Mockito.eq( "machine-id" ));
Mockito.verify( messagingMngr, Mockito.only()).getMessagingClient();
Mockito.verifyZeroInteractions( randomMngr );
Mockito.verifyZeroInteractions( targetConfigurator );
// A notification was sent for the instance whose state changed
Mockito.verify( notificationMngr ).instance(
Mockito.any( Instance.class ),
Mockito.eq( app ),
Mockito.eq( EventType.CHANGED ));
}
@Test
public void testRestoreInstances_noMachineId() throws Exception {
// Prepare stuff
IInstancesMngr mngr = new InstancesMngrImpl( null, null, null, null, null );
TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
ManagedApplication ma = new ManagedApplication( app );
TargetHandler targetHandler = Mockito.mock( TargetHandler.class );
// Try to restore instances
mngr.restoreInstanceStates( ma, targetHandler );
// We did not go very far, and the mock was not even checked.
Mockito.verifyZeroInteractions( targetHandler );
}
@Test
public void testConfigurationError() throws Exception {
// Prepare stuff
INotificationMngr notificationMngr = Mockito.mock( INotificationMngr.class );
IRandomMngr randomMngr = Mockito.mock( IRandomMngr.class );
ITargetsMngr targetsMngr = Mockito.mock( ITargetsMngr.class );
ITargetConfigurator targetConfigurator = Mockito.mock( ITargetConfigurator.class );
IMessagingMngr messagingMngr = Mockito.mock( IMessagingMngr.class );
Mockito.when( messagingMngr.getMessagingClient()).thenReturn( Mockito.mock( IDmClient.class ));
IConfigurationMngr configurationMngr = new ConfigurationMngrImpl();
configurationMngr.setWorkingDirectory( this.folder.newFolder());
TargetHandler targetHandler = Mockito.mock( TargetHandler.class );
Mockito.when( targetHandler.createMachine( Mockito.any( TargetHandlerParameters.class ))).thenReturn( "this-id" );
Mockito.doThrow( new TargetException( "for test" )).when( targetHandler ).configureMachine(
Mockito.any( TargetHandlerParameters.class ),
Mockito.anyString(),
Mockito.any( Instance.class ));
ITargetHandlerResolver targetHandlerResolver = Mockito.mock( ITargetHandlerResolver.class );
Mockito.when( targetHandlerResolver.findTargetHandler( Mockito.anyMap())).thenReturn( targetHandler );
IInstancesMngr mngr = new InstancesMngrImpl( messagingMngr, notificationMngr, targetsMngr, randomMngr, targetConfigurator );
((InstancesMngrImpl) mngr).setTargetHandlerResolver( targetHandlerResolver );
TestApplication app = new TestApplication();
app.setDirectory( this.folder.newFolder());
ManagedApplication ma = new ManagedApplication( app );
// Preconditions
Assert.assertEquals( 0, app.getMySqlVm().data.size());
// Deploy
mngr.changeInstanceState( ma, app.getMySqlVm(), InstanceStatus.DEPLOYED_STARTED );
// Postconditions
Assert.assertEquals( InstanceStatus.PROBLEM, app.getMySqlVm().getStatus());
Assert.assertEquals( "this-id", app.getMySqlVm().data.get( Instance.MACHINE_ID ));
Assert.assertNotNull( app.getMySqlVm().data.get( Instance.LAST_PROBLEM ));
Assert.assertNotNull( app.getMySqlVm().data.get( Instance.TARGET_ACQUIRED ));
}
}