/** * 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.HashMap; import java.util.Map; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import net.roboconf.core.Constants; import net.roboconf.core.model.beans.Component; import net.roboconf.core.model.beans.ExportedVariable; 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.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_dm_to_agent.MsgCmdChangeInstanceState; import net.roboconf.messaging.api.messages.from_dm_to_agent.MsgCmdSetScopedInstance; /** * @author Vincent Zurczak - Linagora */ public class AgentMessageProcessorWaitingAncestorsTest { private Agent agent; private AgentMessageProcessor processor; @Before public void initializeAgent() throws Exception { final MessagingClientFactoryRegistry registry = new MessagingClientFactoryRegistry(); registry.addMessagingClientFactory(new TestClientFactory()); this.agent = new Agent(); this.agent.setApplicationName( "my-app" ); this.agent.setScopedInstancePath( "app server" ); // 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(); this.agent.setSimulatePlugins( true ); Thread.sleep( 200 ); this.processor = (AgentMessageProcessor) this.agent.getMessagingClient().getMessageProcessor(); } @After public void stopAgent() { this.agent.stop(); } @Test public void testScenario_1() throws Exception { // Hierarchy: 3 levels. // The intermediate level has dependencies. // Model Component dbComponent = new Component( "database" ).installerName( "whatever" ); dbComponent.addExportedVariable( new ExportedVariable( "database.ip", null )); dbComponent.addExportedVariable( new ExportedVariable( "database.port", "3009" )); Component appServerComponent = new Component( "app-server" ).installerName( "whatever" ); appServerComponent.addExportedVariable( new ExportedVariable( "app-server.ip", null )); appServerComponent.addExportedVariable( new ExportedVariable( "app-server.port", "8009" )); appServerComponent.addImportedVariable( new ImportedVariable( "database.ip", false, false )); appServerComponent.addImportedVariable( new ImportedVariable( "database.port", false, false )); Component appComponent = new Component( "app1" ).installerName( "we do not care" ); appServerComponent.addChild( appComponent ); Component vmComponent = new Component( "vm" ).installerName( Constants.TARGET_INSTALLER ); vmComponent.addChild( dbComponent ); vmComponent.addChild( appServerComponent ); Instance appServer = new Instance( "app server" ).component( appServerComponent ); appServer.overriddenExports.put( "app-server.ip", "192.168.1.15" ); Instance app1 = new Instance( "app1" ).component( appComponent ); Instance app2 = new Instance( "app2" ).component( appComponent ); InstanceHelpers.insertChild( appServer, app1 ); InstanceHelpers.insertChild( appServer, app2 ); Instance vm1 = new Instance( "vm1" ).component( vmComponent ); InstanceHelpers.insertChild( vm1, appServer ); final String database = "database"; final Map<String,String> vars = new HashMap<String,String>( 1 ); vars.put( "database.ip", "192.168.1.18" ); // Register the model this.processor.processMessage( new MsgCmdSetScopedInstance( vm1 )); Assert.assertEquals( vm1, this.agent.getScopedInstance()); // Deploy and start all for( Instance i : InstanceHelpers.buildHierarchicalList( appServer )) { this.processor.processMessage( new MsgCmdChangeInstanceState( i, InstanceStatus.DEPLOYED_STARTED )); } Assert.assertEquals( InstanceStatus.UNRESOLVED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app1.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2.getStatus()); // We should not be able to start a "waiting..." explicitely this.processor.processMessage( new MsgCmdChangeInstanceState( app2, InstanceStatus.DEPLOYED_STARTED )); Assert.assertEquals( InstanceStatus.UNRESOLVED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app1.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2.getStatus()); // Resolve the missing dependency this.processor.processMessage( new MsgCmdAddImport( "my-app", database, "/vm/db", vars )); // The states should all be resolved Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app2.getStatus()); // Remove the dependency this.processor.processMessage( new MsgCmdRemoveImport( "my-app", database, "/vm/db" )); // Verify the states Assert.assertEquals( InstanceStatus.UNRESOLVED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app1.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2.getStatus()); // Stop an instance this.processor.processMessage( new MsgCmdChangeInstanceState( app2, InstanceStatus.DEPLOYED_STOPPED )); Assert.assertEquals( InstanceStatus.UNRESOLVED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app1.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STOPPED, app2.getStatus()); // Add it again (as another instance) this.processor.processMessage( new MsgCmdAddImport( "my-app", database, "/other-vm/db", vars )); // The states should all be resolved Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STOPPED, app2.getStatus()); } @Test public void testScenario_2() throws Exception { // Hierarchy: 4 levels. // The 2 intermediate levels have dependencies. // Model Component dbComponent = new Component( "database" ).installerName( "whatever" ); dbComponent.addExportedVariable( new ExportedVariable( "database.ip", null )); dbComponent.addExportedVariable( new ExportedVariable( "database.port", "3009" )); Component appServerComponent = new Component( "app-server" ).installerName( "whatever" ); appServerComponent.addExportedVariable( new ExportedVariable( "app-server.ip", null )); appServerComponent.addExportedVariable( new ExportedVariable( "app-server.port", "8009" )); appServerComponent.addImportedVariable( new ImportedVariable( "database.ip", false, false )); appServerComponent.addImportedVariable( new ImportedVariable( "database.port", false, false )); Component appComponent1 = new Component( "app1" ).installerName( "we do not care" ); appServerComponent.addChild( appComponent1 ); Component appComponent2 = new Component( "app1" ).installerName( "we do not care" ); appComponent2.addImportedVariable( new ImportedVariable( "something.else", false, false )); appServerComponent.addChild( appComponent2 ); Component appConfigComponent = new Component( "config" ).installerName( "we do not care" ); appComponent2.addChild( appConfigComponent ); Component vmComponent = new Component( "vm" ).installerName( Constants.TARGET_INSTALLER ); vmComponent.addChild( dbComponent ); vmComponent.addChild( appServerComponent ); Instance appServer = new Instance( "app server" ).component( appServerComponent ); appServer.overriddenExports.put( "app-server.ip", "192.168.1.15" ); Instance app1 = new Instance( "app1" ).component( appComponent1 ); Instance app2 = new Instance( "app2" ).component( appComponent2 ); InstanceHelpers.insertChild( appServer, app1 ); InstanceHelpers.insertChild( appServer, app2 ); Instance app2Config = new Instance( "config" ).component( appConfigComponent ); InstanceHelpers.insertChild( app2, app2Config ); Instance vm1 = new Instance( "vm1" ).component( vmComponent ); InstanceHelpers.insertChild( vm1, appServer ); final String database = "database"; final Map<String,String> vars = new HashMap<String,String>( 1 ); vars.put( "database.ip", "192.168.1.18" ); final String something = "something"; final Map<String,String> somethingVars = new HashMap<String,String>( 1 ); somethingVars.put( "something.else", "hi!" ); // Register the model this.processor.processMessage( new MsgCmdSetScopedInstance( vm1 )); Assert.assertEquals( vm1, this.agent.getScopedInstance()); // Deploy and start all for( Instance i : InstanceHelpers.buildHierarchicalList( appServer )) { this.processor.processMessage( new MsgCmdChangeInstanceState( i, InstanceStatus.DEPLOYED_STARTED )); } Assert.assertEquals( InstanceStatus.UNRESOLVED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app1.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2Config.getStatus()); // Resolve the missing dependency this.processor.processMessage( new MsgCmdAddImport( "my-app", database, "/vm/db", vars )); // The states should all be resolved Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.UNRESOLVED, app2.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2Config.getStatus()); // Stop the 2nd app this.processor.processMessage( new MsgCmdChangeInstanceState( app2, InstanceStatus.DEPLOYED_STOPPED )); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STOPPED, app2.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STOPPED, app2Config.getStatus()); // Start it - does not impact the child instance this.processor.processMessage( new MsgCmdChangeInstanceState( app2, InstanceStatus.DEPLOYED_STARTED )); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.UNRESOLVED, app2.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STOPPED, app2Config.getStatus()); // Undeploy all for( Instance i : InstanceHelpers.buildHierarchicalList( appServer )) { this.processor.processMessage( new MsgCmdChangeInstanceState( i, InstanceStatus.NOT_DEPLOYED )); } Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app1.getStatus()); Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app2.getStatus()); Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app2Config.getStatus()); // Deploy and start all, again - imports were kept for( Instance i : InstanceHelpers.buildHierarchicalList( appServer )) { this.processor.processMessage( new MsgCmdChangeInstanceState( i, InstanceStatus.DEPLOYED_STARTED )); } Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.UNRESOLVED, app2.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2Config.getStatus()); // Resolve the missing dependencIES this.processor.processMessage( new MsgCmdAddImport( "my-app", something, "/vm/something", somethingVars )); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app2.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app2Config.getStatus()); // Remove a top dependency this.processor.processMessage( new MsgCmdRemoveImport( "my-app", database, "/vm/db" )); Assert.assertEquals( InstanceStatus.UNRESOLVED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app1.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2Config.getStatus()); // Add it again this.processor.processMessage( new MsgCmdAddImport( "my-app", database, "/vm/db", vars )); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app2.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app2Config.getStatus()); // Remove the second dependency this.processor.processMessage( new MsgCmdRemoveImport( "my-app", something, "/vm/something" )); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.UNRESOLVED, app2.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2Config.getStatus()); // Add it again this.processor.processMessage( new MsgCmdAddImport( "my-app", something, "/vm/something", somethingVars )); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app2.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app2Config.getStatus()); // Test undeploy when a dependency is missing this.processor.processMessage( new MsgCmdRemoveImport( "my-app", something, "/vm/something" )); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.UNRESOLVED, app2.getStatus()); Assert.assertEquals( InstanceStatus.WAITING_FOR_ANCESTOR, app2Config.getStatus()); this.processor.processMessage( new MsgCmdChangeInstanceState( app2Config, InstanceStatus.NOT_DEPLOYED )); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.UNRESOLVED, app2.getStatus()); Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app2Config.getStatus()); // Add the missing dependency, the last instance remain not deployed this.processor.processMessage( new MsgCmdAddImport( "my-app", something, "/vm/something", somethingVars )); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, appServer.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app1.getStatus()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, app2.getStatus()); Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, app2Config.getStatus()); } }