/** * Copyright (C) 2008 Progress Software, Inc. All rights reserved. * http://fusesource.com * * The software in this package is published under the terms of the AGPL license * a copy of which has been included with this distribution in the license.txt file. */ package org.fusesource.cloudmix.agent.karaf; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.*; import junit.framework.TestCase; import org.apache.felix.karaf.admin.AdminService; import org.apache.felix.karaf.admin.Instance; import org.apache.felix.karaf.admin.InstanceSettings; import org.easymock.EasyMock; import org.fusesource.cloudmix.agent.Feature; import org.fusesource.cloudmix.common.GridClient; import org.fusesource.cloudmix.common.dto.ProvisioningAction; import org.fusesource.cloudmix.common.util.FileUtils; /** * Test cases for using the Karaf agent to create new Karaf instances on the fly */ public class KarafAgentInstancesTest extends TestCase { private static final String ORIGINAL_REPOSITORY = "mvn:org.apache.felix.karaf/features/RELEASE/xml/features"; private static final String REPOSITORY = "mvn:org.fusesource.cloudmix/features/1.3-SNAPSHOT/xml/features"; private static final String ORIGINAL_FEATURE = "webconsole"; private static final String FEATURE = "cloudmix.agent"; private GridClient cl; private AdminService service; private KarafAgent agent; private List<Feature> agentFeatures = new LinkedList<Feature>(); private File workdir; @Override protected void setUp() throws Exception { cl = EasyMock.createNiceMock(GridClient.class); EasyMock.replay(cl); agent = new KarafAgent() { @Override public GridClient getClient() { return cl; } @Override protected void addAgentFeature(Feature feature) { super.addAgentFeature(feature); agentFeatures.add(feature); } }; workdir = new File("testworkdir"); FileUtils.createDirectory(workdir); service = new MockAdminService(); agent.setAdminService(service); agent.setWorkDirectory(workdir); agent.setDetailsPropertyFilePath(workdir.getAbsolutePath() + "/agent.properties"); } @Override protected void tearDown() throws Exception { if (workdir != null) { FileUtils.deleteDirectory(workdir); } } /* * Test creating a new Karaf instance through the AdminService */ public void testCreateNewInstance() throws Exception { ProvisioningAction action = new ProvisioningAction(); action.setId("my-action-id"); action.setFeature("my-feature-name"); agent.installFeatures(action, null, "karaf:instance"); assertEquals("One instance should have been created", 1, service.getInstances().length); assertEquals("One agent feature should have registered", 1, agentFeatures.size()); Instance instance = service.getInstances()[0]; assertEquals("Instance should have been started", Instance.STARTED, instance.getState()); // now, let's uninstall the agent feature to destroy the instance agent.uninstallFeature(agentFeatures.get(0)); assertEquals("Instance should have been stopped", Instance.STOPPED, instance.getState()); assertEquals("Instance should have been destroyed", 0, service.getInstances().length); } /* * Test creating a new Karaf instance through the AdminService, specifying the initial list of feature * repositories and features to be installed from them */ public void testCreateNewInstanceWithFeature() throws Exception { ProvisioningAction action = new ProvisioningAction(); action.setId("my-action-id"); action.setFeature("my-feature-name"); agent.installFeatures(action, null, "karaf:instance " + REPOSITORY + " " + FEATURE); assertEquals("One instance should have been created", 1, service.getInstances().length); assertEquals("One agent feature should have registered", 1, agentFeatures.size()); Instance instance = service.getInstances()[0]; assertEquals("Instance should have been started", Instance.STARTED, instance.getState()); File etc = new File(instance.getLocation(), "etc"); Properties config = new Properties(); config.load(new FileInputStream(new File(etc, "org.apache.felix.karaf.features.cfg"))); assertTrue("Features repository url should have been added", config .getProperty(KarafAgent.FEATURES_REPOSITORIES).contains(REPOSITORY)); assertEquals("There should be two repositories listed in total", 2, config .getProperty(KarafAgent.FEATURES_REPOSITORIES).split(",").length); assertTrue("Boot feature should have been added", config.getProperty(KarafAgent.FEATURES_BOOT) .contains(FEATURE)); assertEquals("There should be two boot features listed in total", 2, config .getProperty(KarafAgent.FEATURES_BOOT).split(",").length); // now, let's uninstall the agent feature to destroy the instance agent.uninstallFeature(agentFeatures.get(0)); assertEquals("Instance should have been stopped", Instance.STOPPED, instance.getState()); assertEquals("Instance should have been destroyed", 0, service.getInstances().length); } /* * Test the conversion of a feature name into a valid Karaf instance name */ public void testGetInstanceName() throws Exception { assertEquals("Replace : by _ when determining the instance name", "ceffbab3-bc3d-4c72-a89c-154ab2052971_my-feature", agent .getInstanceName("ceffbab3-bc3d-4c72-a89c-154ab2052971:my-feature")); } /* * Mock AdminService implementation */ private class MockAdminService implements AdminService { private final class MockAdminInstance implements Instance { private final String name; private String state; private File location; private MockAdminInstance(String name) { this.name = name; location = new File("target/instances/" + name); } public void stop() throws Exception { state = STOPPED; } public void start(String arg0) throws Exception { state = STARTED; } public String getState() throws Exception { return state; } public int getPort() { return 0; } public int getPid() { return 0; } public String getName() { return name; } public String getLocation() { return location.getAbsolutePath(); } public void destroy() throws Exception { instances.remove(getName()); } public void changePort(int arg0) throws Exception { throw new UnsupportedOperationException("Not implemented"); } public boolean isRoot() { return false; } } private Map<String, Instance> instances = new HashMap<String, Instance>(); public Instance createInstance(String name, InstanceSettings settings) throws Exception { assertEquals("The agent should not assign a port number", 0, settings.getPort()); assertNull("The agent should not assign a location", settings.getLocation()); Instance instance = new MockAdminInstance(name); createInstanceLocation(instance); instances.put(name, instance); return instance; } private void createInstanceLocation(Instance instance) throws IOException { File etc = new File(instance.getLocation(), "etc"); etc.mkdirs(); Properties properties = new Properties(); properties.setProperty(KarafAgent.FEATURES_REPOSITORIES, ORIGINAL_REPOSITORY); properties.setProperty(KarafAgent.FEATURES_BOOT, ORIGINAL_FEATURE); properties.store(new FileOutputStream(new File(etc, "org.apache.felix.karaf.features.cfg")), "Default repository and feature created from mock AdminService"); } public Instance getInstance(String name) { return instances.get(name); } public Instance[] getInstances() { return instances.values().toArray(new Instance[] {}); } } }