/**
* 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.dm.internal.api.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.logging.Logger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import net.roboconf.core.internal.tests.TestApplication;
import net.roboconf.core.model.beans.Instance;
import net.roboconf.core.model.beans.Instance.InstanceStatus;
import net.roboconf.core.model.helpers.InstanceHelpers;
import net.roboconf.dm.internal.api.impl.TargetConfiguratorImpl.ConfigurationRunnable;
import net.roboconf.dm.internal.api.impl.TargetConfiguratorImpl.ProgramUtilsProxy;
import net.roboconf.dm.management.api.ITargetHandlerResolver;
import net.roboconf.target.api.TargetException;
import net.roboconf.target.api.TargetHandler;
import net.roboconf.target.api.TargetHandlerParameters;
/**
* @author Vincent Zurczak - Linagora
*/
public class TargetConfiguratorImplTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
private TargetConfiguratorImpl targetConfigurator;
private ExecutorService executor;
@Before
public void configure() {
this.executor = Mockito.mock( ExecutorService.class );
this.targetConfigurator = new TargetConfiguratorImpl();
this.targetConfigurator.executor = this.executor;
}
@Test
public void testStartAndStop() {
this.targetConfigurator.start();
Assert.assertNotNull( this.targetConfigurator.executor );
Assert.assertNotEquals( this.executor, this.targetConfigurator.executor );
this.targetConfigurator.stop();
Assert.assertNull( this.targetConfigurator.executor );
// Invoking "stop" several times does not throw any error
this.targetConfigurator.stop();
}
@Test
public void testReportCandidate_sameInstancePath_differentApplications() throws Exception {
for( int i=1; i<4; i++ ) {
TestApplication app = new TestApplication();
app.setName( "app" + i );
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( this.folder.newFile());
this.targetConfigurator.reportCandidate( parameters, app.getMySqlVm());
Assert.assertEquals( i, this.targetConfigurator.candidates.size());
}
}
@Test
public void testReportCandidate_noConfigScript() throws Exception {
TestApplication app = new TestApplication();
app.setName( "app" );
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( null );
this.targetConfigurator.reportCandidate( parameters, app.getMySqlVm());
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
}
@Test
public void testReportCandidate_inexistingConfigScript() throws Exception {
TestApplication app = new TestApplication();
app.setName( "app" );
File f = this.folder.newFile();
Assert.assertTrue( f.delete());
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( f );
this.targetConfigurator.reportCandidate( parameters, app.getMySqlVm());
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
}
@Test
public void testCancelCandidate() throws Exception {
TestApplication app = new TestApplication();
app.setName( "app" );
TargetHandlerParameters parameters1 = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" );
TargetHandlerParameters parameters2 = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getTomcatVm()))
.domain( "domain" );
this.targetConfigurator.reportCandidate( parameters1, app.getMySqlVm());
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
this.targetConfigurator.reportCandidate( parameters2, app.getTomcatVm());
Assert.assertEquals( 2, this.targetConfigurator.candidates.size());
this.targetConfigurator.cancelCandidate( parameters1, app.getMySqlVm());
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
this.targetConfigurator.cancelCandidate( parameters2, app.getTomcatVm());
Assert.assertEquals( 0, this.targetConfigurator.candidates.size());
this.targetConfigurator.cancelCandidate( parameters2, app.getTomcat());
Assert.assertEquals( 0, this.targetConfigurator.candidates.size());
}
@Test
public void testVerifyCandidates_noExecutor() {
this.targetConfigurator.verifyCandidates();
Mockito.verifyZeroInteractions( this.executor );
}
@Test
public void testVerifyCandidates_noMarker() throws Exception {
// Add a candidates
TestApplication app = new TestApplication();
app.setName( "app" );
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( this.folder.newFile());
this.targetConfigurator.reportCandidate( parameters, app.getMySqlVm());
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
// Verify the candidates
this.targetConfigurator.verifyCandidates();
// Still here
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
// Nothing scheduled
Mockito.verifyZeroInteractions( this.executor );
}
@Test
public void testVerifyCandidates_withMarker_everythingOk() throws Exception {
// Add a candidates
TestApplication app = new TestApplication();
app.setName( "app" );
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( this.folder.newFile());
this.targetConfigurator.setTargetHandlerResolver( Mockito.mock( ITargetHandlerResolver.class ));
this.targetConfigurator.reportCandidate( parameters, app.getMySqlVm());
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
// Mark the instance
app.getMySqlVm().data.put( Instance.READY_FOR_CFG_MARKER, "true" );
// Make sure it is not undeployed
app.getMySqlVm().setStatus( InstanceStatus.DEPLOYING );
// Verify the candidates
this.targetConfigurator.verifyCandidates();
// Not here anymore
Assert.assertEquals( 0, this.targetConfigurator.candidates.size());
// No more markers
Assert.assertFalse( app.getMySqlVm().data.containsKey( Instance.READY_FOR_CFG_MARKER ));
// Something was scheduled
Mockito.verify( this.executor, Mockito.only()).execute( Mockito.any( ConfigurationRunnable.class ));
}
@Test
public void testVerifyCandidates_withMarker_inexistingScript() throws Exception {
// Add a candidates
TestApplication app = new TestApplication();
app.setName( "app" );
File f = this.folder.newFile();
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( f );
this.targetConfigurator.setTargetHandlerResolver( Mockito.mock( ITargetHandlerResolver.class ));
this.targetConfigurator.reportCandidate( parameters, app.getMySqlVm());
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
// Mark the instance
app.getMySqlVm().data.put( Instance.READY_FOR_CFG_MARKER, "true" );
// Delete the script
Assert.assertTrue( f.delete());
// Verify the candidates
this.targetConfigurator.verifyCandidates();
// Not here anymore (e.g. the target was deleted)
Assert.assertEquals( 0, this.targetConfigurator.candidates.size());
// No more markers
Assert.assertFalse( app.getMySqlVm().data.containsKey( Instance.READY_FOR_CFG_MARKER ));
// Nothing scheduled
Mockito.verifyZeroInteractions( this.executor );
}
@Test
public void testVerifyCandidates_withMarker_noScript() throws Exception {
// Add a candidates
TestApplication app = new TestApplication();
app.setName( "app" );
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" );
this.targetConfigurator.setTargetHandlerResolver( Mockito.mock( ITargetHandlerResolver.class ));
this.targetConfigurator.reportCandidate( parameters, app.getMySqlVm());
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
// Mark the instance
app.getMySqlVm().data.put( Instance.READY_FOR_CFG_MARKER, "true" );
// Verify the candidates
this.targetConfigurator.verifyCandidates();
// Not here anymore (e.g. the target was deleted)
Assert.assertEquals( 0, this.targetConfigurator.candidates.size());
// No more markers
Assert.assertFalse( app.getMySqlVm().data.containsKey( Instance.READY_FOR_CFG_MARKER ));
// Nothing scheduled
Mockito.verifyZeroInteractions( this.executor );
}
@Test
public void testVerifyCandidates_withMarker_noTargetHandler() throws Exception {
// Add a candidates
TestApplication app = new TestApplication();
app.setName( "app" );
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( this.folder.newFile());
this.targetConfigurator.reportCandidate( parameters, app.getMySqlVm());
Assert.assertEquals( 1, this.targetConfigurator.candidates.size());
// Mark the instance
app.getMySqlVm().data.put( Instance.READY_FOR_CFG_MARKER, "true" );
// Verify the candidates
this.targetConfigurator.verifyCandidates();
// Not a candidate anymore
Assert.assertEquals( 0, this.targetConfigurator.candidates.size());
// No more markers
Assert.assertFalse( app.getMySqlVm().data.containsKey( Instance.READY_FOR_CFG_MARKER ));
// Nothing scheduled
Mockito.verifyZeroInteractions( this.executor );
}
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testConfigurationRunnable_run_ok() throws Exception {
// Prepare
TestApplication app = new TestApplication();
app.setName( "app" );
String machineId = "sdg5465sdf1";
app.getMySqlVm().data.put( Instance.MACHINE_ID, machineId );
File scriptFile = this.folder.newFile();
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( scriptFile )
.messagingProperties( new HashMap<String,String>( 0 ))
.targetProperties( new HashMap<String,String>( 0 ));
TargetHandler targetHandler = Mockito.mock( TargetHandler.class );
Mockito.when( targetHandler.retrievePublicIpAddress( parameters, machineId )).thenReturn( "127.0.0.1" );
ProgramUtilsProxy programUtils = Mockito.mock( ProgramUtilsProxy.class );
ITargetHandlerResolver thResolver = Mockito.mock( ITargetHandlerResolver.class );
Mockito.when( thResolver.findTargetHandler( parameters.getTargetProperties())).thenReturn( targetHandler );
// Execute
ConfigurationRunnable runnable = new ConfigurationRunnable( parameters, app.getMySqlVm(), thResolver );
runnable.programUtils = programUtils;
runnable.run();
// Verify
Mockito.verify( thResolver, Mockito.only()).findTargetHandler( parameters.getTargetProperties());
Mockito.verify( targetHandler, Mockito.only()).retrievePublicIpAddress( parameters, machineId );
ArgumentCaptor<Map<String,String>> environmentVarsArg = ArgumentCaptor.forClass((Class) Map.class );
Mockito.verify( programUtils, Mockito.only()).executeCommand(
Mockito.any( Logger.class ),
Mockito.eq( new String[] { scriptFile.getAbsolutePath()}),
Mockito.eq( scriptFile.getParentFile()),
environmentVarsArg.capture(),
Mockito.eq( app.getName()),
Mockito.eq( parameters.getScopedInstancePath()));
Map<String,String> environmentVars = environmentVarsArg.getValue();
Assert.assertNotNull( environmentVars );
Assert.assertEquals( "127.0.0.1", environmentVars.get( "IP_ADDRESS" ));
Assert.assertEquals( app.getName(), environmentVars.get( "APPLICATION_NAME" ));
Assert.assertEquals( parameters.getScopedInstancePath(), environmentVars.get( "SCOPED_INSTANCE_PATH" ));
Assert.assertEquals( "domain", environmentVars.get( "DOMAIN" ));
Assert.assertNotNull( environmentVars.get( "USER_DATA" ));
Assert.assertEquals( 5, environmentVars.size());
}
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testConfigurationRunnable_run_ok_noMachineId_noIp() throws Exception {
// Prepare
TestApplication app = new TestApplication();
app.setName( "app" );
File scriptFile = this.folder.newFile();
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( scriptFile )
.messagingProperties( new HashMap<String,String>( 0 ))
.targetProperties( new HashMap<String,String>( 0 ));
TargetHandler targetHandler = Mockito.mock( TargetHandler.class );
ProgramUtilsProxy programUtils = Mockito.mock( ProgramUtilsProxy.class );
ITargetHandlerResolver thResolver = Mockito.mock( ITargetHandlerResolver.class );
Mockito.when( thResolver.findTargetHandler( parameters.getTargetProperties())).thenReturn( targetHandler );
// Execute
ConfigurationRunnable runnable = new ConfigurationRunnable( parameters, app.getMySqlVm(), thResolver );
runnable.programUtils = programUtils;
runnable.run();
// Verify
Mockito.verify( thResolver, Mockito.only()).findTargetHandler( parameters.getTargetProperties());
Mockito.verify( targetHandler, Mockito.only()).retrievePublicIpAddress( parameters, null );
ArgumentCaptor<Map<String,String>> environmentVarsArg = ArgumentCaptor.forClass((Class) Map.class );
Mockito.verify( programUtils, Mockito.only()).executeCommand(
Mockito.any( Logger.class ),
Mockito.eq( new String[] { scriptFile.getAbsolutePath()}),
Mockito.eq( scriptFile.getParentFile()),
environmentVarsArg.capture(),
Mockito.eq( app.getName()),
Mockito.eq( parameters.getScopedInstancePath()));
Map<String,String> environmentVars = environmentVarsArg.getValue();
Assert.assertNotNull( environmentVars );
Assert.assertEquals( "", environmentVars.get( "IP_ADDRESS" ));
Assert.assertEquals( app.getName(), environmentVars.get( "APPLICATION_NAME" ));
Assert.assertEquals( parameters.getScopedInstancePath(), environmentVars.get( "SCOPED_INSTANCE_PATH" ));
Assert.assertEquals( "domain", environmentVars.get( "DOMAIN" ));
Assert.assertNotNull( environmentVars.get( "USER_DATA" ));
Assert.assertEquals( 5, environmentVars.size());
}
@Test
public void testConfigurationRunnable_run_noTargetHandler() throws Exception {
// Prepare
TestApplication app = new TestApplication();
app.setName( "app" );
String machineId = "sdg5465sdf1";
app.getMySqlVm().data.put( Instance.MACHINE_ID, machineId );
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( this.folder.newFile())
.messagingProperties( new HashMap<String,String>( 0 ))
.targetProperties( new HashMap<String,String>( 0 ));
ITargetHandlerResolver thResolver = Mockito.mock( ITargetHandlerResolver.class );
ProgramUtilsProxy programUtils = Mockito.mock( ProgramUtilsProxy.class );
// Execute
ConfigurationRunnable runnable = new ConfigurationRunnable( parameters, app.getMySqlVm(), thResolver );
runnable.programUtils = programUtils;
runnable.run();
// Verify
Mockito.verify( thResolver, Mockito.only()).findTargetHandler( parameters.getTargetProperties());
Mockito.verifyZeroInteractions( programUtils );
}
@Test
public void testConfigurationRunnable_run_inexistingScript() throws Exception {
// Prepare
TestApplication app = new TestApplication();
app.setName( "app" );
String machineId = "sdg5465sdf1";
app.getMySqlVm().data.put( Instance.MACHINE_ID, machineId );
File scriptFile = this.folder.newFile();
Assert.assertTrue( scriptFile.delete());
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( scriptFile )
.messagingProperties( new HashMap<String,String>( 0 ))
.targetProperties( new HashMap<String,String>( 0 ));
ITargetHandlerResolver thResolver = Mockito.mock( ITargetHandlerResolver.class );
TargetHandler targetHandler = Mockito.mock( TargetHandler.class );
ProgramUtilsProxy programUtils = Mockito.mock( ProgramUtilsProxy.class );
Mockito.when( thResolver.findTargetHandler( parameters.getTargetProperties())).thenReturn( targetHandler );
// Execute
ConfigurationRunnable runnable = new ConfigurationRunnable( parameters, app.getMySqlVm(), thResolver );
runnable.programUtils = programUtils;
runnable.run();
// Verify
Mockito.verify( thResolver, Mockito.only()).findTargetHandler( parameters.getTargetProperties());
Mockito.verifyZeroInteractions( programUtils );
}
@Test
public void testConfigurationRunnable_run_withException() throws Exception {
// Prepare
TestApplication app = new TestApplication();
app.setName( "app" );
String machineId = "sdg5465sdf1";
app.getMySqlVm().data.put( Instance.MACHINE_ID, machineId );
File scriptFile = this.folder.newFile();
Assert.assertTrue( scriptFile.delete());
TargetHandlerParameters parameters = new TargetHandlerParameters()
.applicationName( app.getName())
.scopedInstancePath( InstanceHelpers.computeInstancePath( app.getMySqlVm()))
.domain( "domain" )
.targetConfigurationScript( scriptFile )
.messagingProperties( new HashMap<String,String>( 0 ))
.targetProperties( new HashMap<String,String>( 0 ));
ITargetHandlerResolver thResolver = Mockito.mock( ITargetHandlerResolver.class );
TargetHandler targetHandler = Mockito.mock( TargetHandler.class );
ProgramUtilsProxy programUtils = Mockito.mock( ProgramUtilsProxy.class );
Mockito.when( thResolver.findTargetHandler( parameters.getTargetProperties())).thenReturn( targetHandler );
Mockito.doThrow( new TargetException( "for test!" )).when( thResolver ).findTargetHandler( parameters.getTargetProperties());
// Execute
ConfigurationRunnable runnable = new ConfigurationRunnable( parameters, app.getMySqlVm(), thResolver );
runnable.programUtils = programUtils;
runnable.run();
// Verify
Mockito.verify( thResolver, Mockito.only()).findTargetHandler( parameters.getTargetProperties());
Mockito.verifyZeroInteractions( programUtils );
}
}