/*
* RHQ Management Platform
* Copyright (C) 2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.plugins.augeas.test;
import static org.testng.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.augeas.jna.Aug;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pc.PluginContainer;
import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.pc.configuration.ConfigurationManager;
import org.rhq.core.pc.inventory.InventoryManager;
import org.rhq.core.pc.plugin.FileSystemPluginFinder;
import org.rhq.core.pc.plugin.PluginManager;
import org.rhq.core.pluginapi.util.FileUtils;
import org.rhq.core.util.file.FileUtil;
import org.rhq.plugins.augeas.AugeasConfigurationComponent;
/**
* A base class for integration tests for instances of {@link AugeasConfigurationComponent}.
*
* @author Ian Springer
*/
public abstract class AbstractAugeasConfigurationComponentTest {
public static final String TEST_GROUP = "linux-config";
private static final File ITEST_DIR = new File("target/itest");
private static final long ONE_WEEK_IN_SECONDS = 60L * 60 * 24;
protected static final boolean IS_WINDOWS = (File.separatorChar == '\\');
protected static final File AUGEAS_ROOT;
static {
String tmpDirPath = System.getProperty("java.io.tmpdir");
File tmpDir = new File(tmpDirPath);
AUGEAS_ROOT = new File(tmpDir, "rhq-itest-augeas-root-path");
}
private final Log log = LogFactory.getLog(this.getClass());
@BeforeClass(groups = TEST_GROUP)
public void start() {
if (!isResourceConfigSupported()) {
String message;
if (IS_WINDOWS) {
message = "Augeas is not available on Windows. Augeas-based configuration functionality will *not* be tested.";
} else {
message = "Augeas not found. If on Fedora or RHEL, `yum install augeas`. Augeas-based configuration functionality will *not* be tested.";
}
System.out.println(message);
}
try {
PluginContainerConfiguration pcConfig = createPluginContainerConfiguration();
PluginContainer.getInstance().setConfiguration(pcConfig);
System.out.println("Starting plugin container...");
PluginContainer pluginContainer = PluginContainer.getInstance();
pluginContainer.initialize();
Set<String> pluginNames = pluginContainer.getPluginManager().getMetadataManager().getPluginNames();
System.out.println("Plugin container started with the following plugins: " + pluginNames);
System.out.println("Updating Augeas root in default plugin config...");
boolean deleteRoot = true;
for (ResourceType resourceType : getResourceTypes(getPluginName())) {
ConfigurationDefinition pluginConfigDef = resourceType.getPluginConfigurationDefinition();
ConfigurationTemplate defaultPluginConfigTemplate = pluginConfigDef.getDefaultTemplate();
Configuration defaultPluginConfig = defaultPluginConfigTemplate.getConfiguration();
tweakDefaultPluginConfig(defaultPluginConfig);
resetConfigFiles(defaultPluginConfig, deleteRoot);
deleteRoot = false;
}
InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
System.out.println("Executing server discovery scan...");
inventoryManager.executeServerScanImmediately();
System.out.println("Executing service discovery scan...");
inventoryManager.executeServiceScanImmediately();
} catch (Exception e) {
e.printStackTrace();
fail("Failed to initialize the plugin container.", e);
}
}
@AfterMethod(groups = TEST_GROUP)
public void resetConfigFiles() throws IOException {
boolean deleteRoot = true;
for (Resource res : getResources()) {
resetConfigFiles(res.getPluginConfiguration(), deleteRoot);
deleteRoot = false;
}
}
@Test(groups = TEST_GROUP)
public void testResourceConfigLoad() throws Exception {
ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
Configuration resourceConfig;
try {
for (Resource resource : getResources()) {
resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
Configuration expectedResourceConfig = getExpectedResourceConfig();
assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
}
} catch (PluginContainerException e) {
if (isResourceConfigSupported()) {
throw e;
}
}
}
@Test(groups = TEST_GROUP)
public void testResourceConfigUpdate() throws Exception {
ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
for (Resource resource : getResources()) {
Configuration updatedResourceConfig = getUpdatedResourceConfig();
ConfigurationUpdateRequest updateRequest = new ConfigurationUpdateRequest(0, updatedResourceConfig,
resource.getId());
configurationManager.executeUpdateResourceConfigurationImmediately(updateRequest);
if (isResourceConfigSupported()) {
Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
assert resourceConfig.equals(updatedResourceConfig) :
"Unexpected Resource configuration - \nExpected:\n\t"
+ updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
}
}
}
@AfterClass(groups = TEST_GROUP)
public void stop() {
deleteAugeasRootDir();
System.out.println("Stopping plugin container...");
PluginContainer.getInstance().shutdown();
System.out.println("Plugin container stopped.");
}
protected abstract String getPluginName();
protected abstract String getResourceTypeName();
protected abstract Configuration getExpectedResourceConfig();
protected abstract Configuration getUpdatedResourceConfig();
protected PluginContainerConfiguration createPluginContainerConfiguration() throws IOException {
PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
File pluginsDir = new File(ITEST_DIR, "plugins");
pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
pcConfig.setPluginDirectory(pluginsDir);
pcConfig.setInsideAgent(false);
pcConfig.setCreateResourceClassloaders(true);
// Set initial delays for all scheduled scans to one week to effectively disable them.
pcConfig.setServerDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
pcConfig.setServiceDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
pcConfig.setAvailabilityScanInitialDelay(ONE_WEEK_IN_SECONDS);
pcConfig.setConfigurationDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
pcConfig.setContentDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
File tmpDir = new File(ITEST_DIR, "tmp");
tmpDir.mkdirs();
if (!tmpDir.isDirectory() || !tmpDir.canWrite()) {
throw new IOException("Failed to create temporary directory (" + tmpDir + ").");
}
pcConfig.setTemporaryDirectory(tmpDir);
File dataDir = new File(ITEST_DIR, "plugin-data");
dataDir.mkdirs();
if (!dataDir.isDirectory() || !dataDir.canWrite()) {
throw new IOException("Failed to create data directory (" + dataDir + ").");
}
pcConfig.setDataDirectory(dataDir);
return pcConfig;
}
protected static Set<ResourceType> getResourceTypes(String pluginName) {
Set<ResourceType> ret = new HashSet<ResourceType>();
PluginManager pluginManager = PluginContainer.getInstance().getPluginManager();
PluginMetadataManager pluginMetadataManager = pluginManager.getMetadataManager();
for (ResourceType res : pluginMetadataManager.getAllTypes()) {
if (pluginName.equals(res.getPlugin())) {
ret.add(res);
}
}
return ret;
}
protected static ResourceType getResourceType(String resourceTypeName, String pluginName) {
PluginManager pluginManager = PluginContainer.getInstance().getPluginManager();
PluginMetadataManager pluginMetadataManager = pluginManager.getMetadataManager();
return pluginMetadataManager.getType(resourceTypeName, pluginName);
}
protected final ResourceType getResourceType() {
return getResourceType(getResourceTypeName(), getPluginName());
}
protected Set<Resource> getResources() {
InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
ResourceType resourceType = getResourceType();
Set<Resource> resources = inventoryManager.getResourcesWithType(resourceType);
return resources;
}
protected void resetConfigFiles(Configuration pluginConfig, boolean deleteRoot) throws IOException {
if (deleteRoot) {
deleteAugeasRootDir();
}
AUGEAS_ROOT.mkdirs();
String includes = pluginConfig.getSimpleValue(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, null);
if (includes != null) {
List<String> includeGlobs = new ArrayList<String>();
includeGlobs.addAll(Arrays.asList(includes.split("\\s*\\|\\s*")));
for (String includeGlob : includeGlobs) {
String resourcePath;
if (IS_WINDOWS) {
resourcePath = includeGlob.replace('\\', '/');
int colonIndex = resourcePath.indexOf(':');
if (colonIndex != -1) {
resourcePath = resourcePath.substring(colonIndex + 1);
}
} else {
resourcePath = includeGlob;
}
InputStream inputStream = this.getClass().getResourceAsStream(resourcePath);
if (inputStream != null) {
File outputFile = new File(AUGEAS_ROOT, resourcePath);
outputFile.getParentFile().mkdirs();
FileUtil.writeFile(inputStream, outputFile);
}
}
}
}
protected boolean isResourceConfigSupported() {
return isAugeasAvailable();
}
protected void tweakDefaultPluginConfig(Configuration defaultPluginConfig) {
PropertySimple rootPathProp = new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
AUGEAS_ROOT);
defaultPluginConfig.put(rootPathProp);
}
private boolean isAugeasAvailable() {
try {
Aug aug = Aug.INSTANCE;
return true;
} catch (Error e) {
return false;
}
}
private void deleteAugeasRootDir() {
try {
FileUtils.purge(AUGEAS_ROOT, true);
} catch (IOException e) {
log.warn("Failed to delete Augeas root dir (" + AUGEAS_ROOT + ").");
}
}
}