/** * Copyright 2014-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.agent.internal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import net.roboconf.agent.internal.test.AgentTestUtils; import net.roboconf.core.internal.tests.TestApplicationTemplate; import net.roboconf.core.model.beans.Component; import net.roboconf.core.model.beans.ExportedVariable; import net.roboconf.core.model.beans.Import; import net.roboconf.core.model.beans.ImportedVariable; 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.messaging.api.MessagingConstants; import net.roboconf.messaging.api.factory.MessagingClientFactoryRegistry; import net.roboconf.messaging.api.internal.client.test.TestClient; import net.roboconf.messaging.api.internal.client.test.TestClientFactory; import net.roboconf.messaging.api.messages.from_agent_to_agent.MsgCmdAddImport; import net.roboconf.messaging.api.messages.from_agent_to_agent.MsgCmdRemoveImport; import net.roboconf.messaging.api.messages.from_agent_to_agent.MsgCmdRequestImport; import net.roboconf.messaging.api.messages.from_dm_to_agent.MsgCmdSetScopedInstance; import net.roboconf.plugin.api.PluginInterface; /** * @author Vincent Zurczak - Linagora */ public class AgentMessageProcessorImportsTest { private static final String APP = "app"; private Agent agent; @Before public void initializeAgent() throws Exception { final MessagingClientFactoryRegistry registry = new MessagingClientFactoryRegistry(); registry.addMessagingClientFactory(new TestClientFactory()); this.agent = new Agent(); this.agent.applicationName = APP; // We first need to start the agent, so it creates the reconfigurable messaging client. this.agent.setMessagingType(MessagingConstants.FACTORY_TEST); this.agent.start(); // We then set the factory registry of the created client, and reconfigure the agent, so the messaging client backend is created. this.agent.getMessagingClient().setRegistry(registry); this.agent.reconfigure(); Thread.sleep( 200 ); AgentTestUtils.getInternalClient( this.agent.getMessagingClient()).clearMessages(); } @After public void stopAgent() { this.agent.stop(); } @Test public void testImportsRequest() throws Exception { TestClient client = AgentTestUtils.getInternalClient( this.agent.getMessagingClient()); AgentMessageProcessor processor = (AgentMessageProcessor) this.agent.getMessagingClient().getMessageProcessor(); TestApplicationTemplate app = new TestApplicationTemplate(); processor.scopedInstance = app.getTomcatVm(); app.getTomcatVm().setStatus( InstanceStatus.DEPLOYED_STARTED ); // There are as many client invocations as started instances that // export the requested variables. processor.processMessage( new MsgCmdRequestImport( APP, "war" )); Assert.assertEquals( 0, client.messagesForAgents.size()); app.getTomcat().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getWar().setStatus( InstanceStatus.DEPLOYED_STARTED ); client.messagesForAgents.clear(); processor.processMessage( new MsgCmdRequestImport( APP, "war" )); Assert.assertEquals( 1, client.messagesForAgents.size()); } @Test public void testImportsRequestOnScopedInstance() throws Exception { TestClient client = AgentTestUtils.getInternalClient( this.agent.getMessagingClient()); AgentMessageProcessor processor = (AgentMessageProcessor) this.agent.getMessagingClient().getMessageProcessor(); // Our scoped instance has variables to export TestApplicationTemplate app = new TestApplicationTemplate(); app.getTomcatVm().getComponent().addExportedVariable( new ExportedVariable( "config", "test" )); // Remove children instances to not simplify the test app.getTomcatVm().getChildren().clear(); // Set the scoped instance Assert.assertNull( processor.scopedInstance ); Assert.assertEquals( 0, client.messagesForTheDm.size()); processor.processMessage( new MsgCmdSetScopedInstance( app.getTomcatVm())); Assert.assertEquals( processor.scopedInstance, app.getTomcatVm()); Assert.assertEquals( 1, client.messagesForTheDm.size()); // No instance imports anything (we removed the WAR) => no message. Assert.assertEquals( 0, client.messagesForAgents.size()); // Request variables from the scoped instance processor.processMessage( new MsgCmdRequestImport( APP, app.getTomcatVm().getComponent().getName())); Assert.assertEquals( 1, client.messagesForAgents.size()); Assert.assertEquals( 1, client.messagesForTheDm.size()); } @Test public void testImports_applicationScope_noExternalExport() throws Exception { AgentMessageProcessor processor = (AgentMessageProcessor) this.agent.getMessagingClient().getMessageProcessor(); TestApplicationTemplate app = new TestApplicationTemplate(); processor.scopedInstance = app.getTomcatVm(); app.getTomcatVm().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getTomcat().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getWar().setStatus( InstanceStatus.DEPLOYED_STARTED ); // Notify a MySQL instance is available Assert.assertEquals( 0, app.getWar().getImports().size()); Map<String,String> variables1 = new HashMap<> (); variables1.put( "mysql.ip", "192.168.0.15" ); variables1.put( "mysql.port", "3306" ); processor.processMessage( new MsgCmdAddImport( APP, "mysql", "mysql-vm-1/mysql", variables1 )); Assert.assertEquals( 1, app.getWar().getImports().size()); Collection<Import> imports = app.getWar().getImports().get( "mysql" ); Assert.assertEquals( 1, imports.size()); Import imp = imports.iterator().next(); Assert.assertEquals( 2, imp.getExportedVars().size()); Assert.assertEquals( "192.168.0.15", imp.getExportedVars().get( "mysql.ip" )); Assert.assertEquals( "3306", imp.getExportedVars().get( "mysql.port" )); Assert.assertEquals( "mysql-vm-1/mysql", imp.getInstancePath()); // Another instance is made available Map<String,String> variables2 = new HashMap<> (); variables2.put( "mysql.ip", "192.168.0.21" ); variables2.put( "mysql.port", "31306" ); processor.processMessage( new MsgCmdAddImport( APP, "mysql", "mysql-vm-2/mysql", variables2 )); Assert.assertEquals( 1, app.getWar().getImports().size()); imports = app.getWar().getImports().get( "mysql" ); Assert.assertEquals( 2, imports.size()); imp = imports.toArray( new Import[ 0 ])[ 1 ]; Assert.assertEquals( 2, imp.getExportedVars().size()); Assert.assertEquals( "192.168.0.21", imp.getExportedVars().get( "mysql.ip" )); Assert.assertEquals( "31306", imp.getExportedVars().get( "mysql.port" )); Assert.assertEquals( "mysql-vm-2/mysql", imp.getInstancePath()); // Remove the last one processor.processMessage( new MsgCmdRemoveImport( APP, "mysql", "mysql-vm-2/mysql" )); Assert.assertEquals( 1, app.getWar().getImports().size()); imports = app.getWar().getImports().get( "mysql" ); Assert.assertEquals( 1, imports.size()); imp = imports.iterator().next(); Assert.assertEquals( 2, imp.getExportedVars().size()); Assert.assertEquals( "192.168.0.15", imp.getExportedVars().get( "mysql.ip" )); Assert.assertEquals( "3306", imp.getExportedVars().get( "mysql.port" )); Assert.assertEquals( "mysql-vm-1/mysql", imp.getInstancePath()); // Remove an invalid one processor.processMessage( new MsgCmdRemoveImport( APP, "mysql", "mysql-vm-54/mysql" )); Assert.assertEquals( 1, app.getWar().getImports().size()); processor.processMessage( new MsgCmdRemoveImport( APP, "something-else", "a-vm/something-else" )); Assert.assertEquals( 1, app.getWar().getImports().size()); } @Test public void testImports_filtering_withExternalExport_noBinding() throws Exception { AgentMessageProcessor processor = (AgentMessageProcessor) this.agent.getMessagingClient().getMessageProcessor(); TestApplicationTemplate app = new TestApplicationTemplate(); processor.scopedInstance = app.getTomcatVm(); app.getTomcatVm().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getTomcat().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getWar().setStatus( InstanceStatus.DEPLOYED_STARTED ); // Notify a MySQL instance is available Assert.assertEquals( 0, app.getWar().getImports().size()); Assert.assertEquals( 0, processor.applicationNameToExternalExports.size()); Map<String,String> variables1 = new HashMap<> (); variables1.put( "mysql.ip", "192.168.0.15" ); variables1.put( "mysql.port", "3306" ); processor.processMessage( new MsgCmdAddImport( "not-app", "mysql", "mysql-vm-1/mysql", variables1 )); Assert.assertEquals( 0, app.getWar().getImports().size()); Assert.assertEquals( 1, processor.applicationNameToExternalExports.size()); Assert.assertTrue( processor.applicationNameToExternalExports.containsKey( "not-app" )); Assert.assertEquals( 1, processor.applicationNameToExternalExports.get( "not-app" ).size()); // Try to remove it... No error processor.processMessage( new MsgCmdRemoveImport( "not-app", "mysql", "mysql-vm-1/mysql" )); Assert.assertEquals( 0, app.getWar().getImports().size()); Assert.assertEquals( 0, processor.applicationNameToExternalExports.size()); } @Test public void testImports_filtering_withExternalExport_withBinding() throws Exception { AgentMessageProcessor processor = (AgentMessageProcessor) this.agent.getMessagingClient().getMessageProcessor(); TestApplicationTemplate app = new TestApplicationTemplate(); processor.scopedInstance = app.getTomcatVm(); app.getTomcatVm().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getTomcat().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getWar().setStatus( InstanceStatus.DEPLOYED_STARTED ); // Create a binding - not really meaningful here Set<String> appNames = new HashSet<>( 1 ); appNames.add( "not-app" ); processor.applicationBindings.put( "mysql", appNames ); // Notify a MySQL instance is available Assert.assertEquals( 0, app.getWar().getImports().size()); Assert.assertEquals( 0, processor.applicationNameToExternalExports.size()); Map<String,String> variables1 = new HashMap<> (); variables1.put( "mysql.ip", "192.168.0.15" ); variables1.put( "mysql.port", "3306" ); processor.processMessage( new MsgCmdAddImport( "not-app", "mysql", "mysql-vm-1/mysql", variables1 )); Assert.assertEquals( 1, app.getWar().getImports().size()); Collection<Import> imports = app.getWar().getImports().get( "mysql" ); Assert.assertEquals( 1, imports.size()); Assert.assertEquals( 1, processor.applicationNameToExternalExports.size()); Assert.assertTrue( processor.applicationNameToExternalExports.containsKey( "not-app" )); Assert.assertEquals( 1, processor.applicationNameToExternalExports.get( "not-app" ).size()); Import imp = imports.iterator().next(); Assert.assertEquals( 2, imp.getExportedVars().size()); Assert.assertEquals( "192.168.0.15", imp.getExportedVars().get( "mysql.ip" )); Assert.assertEquals( "3306", imp.getExportedVars().get( "mysql.port" )); Assert.assertEquals( "mysql-vm-1/mysql", imp.getInstancePath()); // Remove it processor.processMessage( new MsgCmdRemoveImport( "not-app", "mysql", "mysql-vm-1/mysql" )); Assert.assertEquals( 0, app.getWar().getImports().size()); Assert.assertEquals( 0, processor.applicationNameToExternalExports.size()); } @Test public void testAddImport_noPlugin() throws Exception { this.agent.stop(); this.agent = new Agent() { @Override public PluginInterface findPlugin( Instance instance ) { return null; } }; this.agent.setMessagingType(MessagingConstants.FACTORY_TEST); this.agent.applicationName = APP; this.agent.start(); AgentMessageProcessor processor = (AgentMessageProcessor) this.agent.getMessagingClient().getMessageProcessor(); TestApplicationTemplate app = new TestApplicationTemplate(); processor.scopedInstance = app.getTomcatVm(); app.getTomcatVm().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getTomcat().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getWar().setStatus( InstanceStatus.DEPLOYED_STARTED ); // Notify a MySQL instance is available Assert.assertEquals( 0, app.getWar().getImports().size()); Map<String,String> variables1 = new HashMap<> (); variables1.put( "mysql.ip", "192.168.0.15" ); variables1.put( "mysql.port", "3306" ); processor.processMessage( new MsgCmdAddImport( APP, "mysql", "mysql-vm-1/mysql", variables1 )); Assert.assertEquals( 1, app.getWar().getImports().size()); Collection<Import> imports = app.getWar().getImports().get( "mysql" ); Assert.assertEquals( 1, imports.size()); Import imp = imports.iterator().next(); Assert.assertEquals( 2, imp.getExportedVars().size()); Assert.assertEquals( "192.168.0.15", imp.getExportedVars().get( "mysql.ip" )); Assert.assertEquals( "3306", imp.getExportedVars().get( "mysql.port" )); Assert.assertEquals( "mysql-vm-1/mysql", imp.getInstancePath()); // No plug-in => no error (the exception is caught somewhere) } @Test public void testRemoveImport_noPlugin() throws Exception { this.agent.stop(); this.agent = new Agent() { @Override public PluginInterface findPlugin( Instance instance ) { return null; } }; this.agent.setMessagingType(MessagingConstants.FACTORY_TEST); this.agent.start(); AgentMessageProcessor processor = (AgentMessageProcessor) this.agent.getMessagingClient().getMessageProcessor(); TestApplicationTemplate app = new TestApplicationTemplate(); processor.scopedInstance = app.getTomcatVm(); app.getTomcatVm().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getTomcat().setStatus( InstanceStatus.DEPLOYED_STARTED ); app.getWar().setStatus( InstanceStatus.DEPLOYED_STARTED ); List<Import> imports = new ArrayList<>( Arrays.asList( new Import( "mysql-vm-1/mysql", "mysql" ))); app.getWar().getImports().put( "mysql", imports ); // Remove the MySQL export Assert.assertEquals( 1, app.getWar().getImports().size()); Assert.assertEquals( 1, app.getWar().getImports().get( "mysql" ).size()); processor.processMessage( new MsgCmdRemoveImport( APP, "mysql", "mysql-vm-1/mysql" )); Assert.assertEquals( 0, app.getWar().getImports().size()); // No plug-in => no error (the exception is caught somewhere) } @Test public void testSelfImport() throws Exception { // A node depends on other nodes AgentMessageProcessor processor = (AgentMessageProcessor) this.agent.getMessagingClient().getMessageProcessor(); Component clusterNodeComponent = new Component( "cluster" ).installerName( "whatever" ); clusterNodeComponent.addImportedVariable( new ImportedVariable( "cluster.ip", true, false )); clusterNodeComponent.addImportedVariable( new ImportedVariable( "cluster.port", true, false )); clusterNodeComponent.addExportedVariable( new ExportedVariable( "cluster.ip", null )); clusterNodeComponent.addExportedVariable( new ExportedVariable( "cluster.port", "9007" )); Instance i1 = new Instance( "inst 1" ).component( clusterNodeComponent ); i1.overriddenExports.put( "cluster.ip", "192.168.1.15" ); processor.scopedInstance = i1; // Adding itself does not work Assert.assertEquals( 0, i1.getImports().size()); processor.processMessage( new MsgCmdAddImport( APP, "cluster", "/inst 1", InstanceHelpers.findAllExportedVariables( i1 ))); Assert.assertEquals( 0, i1.getImports().size()); // Adding another node works Map<String,String> variables = new HashMap<> (); variables.put( "cluster.ip", "192.168.0.45" ); processor.processMessage( new MsgCmdAddImport( APP, "cluster", "/vm/cluster node", variables )); Assert.assertEquals( 1, i1.getImports().size()); Collection<Import> imports = i1.getImports().get( "cluster" ); Assert.assertEquals( 1, imports.size()); Import imp = imports.iterator().next(); Assert.assertEquals( 1, imp.getExportedVars().size()); Assert.assertEquals( "192.168.0.45", imp.getExportedVars().get( "cluster.ip" )); } }