modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
| 31 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java
| 56 +++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.java
| 82 ++++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceFactoryManagerBeanTest.java
| 165 ++++++++--
modules/enterprise/server/jar/src/test/resources/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml
| 2
5 files changed, 305 insertions(+), 31 deletions(-)
New commits:
commit 7de3b23b2a9b65af0733086da19636c50d3a7789
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed May 30 16:48:32 2012 -0400
[BZ 814305] throw RuntimeExceptions in SLSB methods for manual-add and create-child if
1) the new Resource's type is a singleton and a child Resource with that type already
exists or 2) the new Resource's type does not support manual-add or the appropriate
flavor of create-child; add new unit tests to verify the RuntimeExceptions are thrown
(
https://bugzilla.redhat.com/show_bug.cgi?id=814305)
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
index ce4e6a7..a7a6408 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -61,6 +61,7 @@ import org.rhq.core.clientapi.server.discovery.StaleTypeException;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.discovery.MergeResourceResponse;
import org.rhq.core.domain.discovery.ResourceSyncInfo;
import org.rhq.core.domain.resource.Agent;
@@ -438,9 +439,18 @@ public class DiscoveryBossBean implements DiscoveryBossLocal,
DiscoveryBossRemot
+ " to manually add child resources.");
}
+ Resource parentResource = this.resourceManager.getResourceById(user,
parentResourceId);
+
+ if (!resourceType.isSupportsManualAdd()) {
+ throw new RuntimeException("Cannot manually add " + resourceType +
" child Resource under parent "
+ + parentResource + ", since the " +
resourceType
+ + " type does not support manual add.");
+ }
+
+ abortResourceManualAddIfExistingSingleton(parentResource, resourceType);
+
MergeResourceResponse mergeResourceResponse;
try {
- Resource parentResource = this.resourceManager.getResourceById(user,
parentResourceId);
AgentClient agentClient =
this.agentManager.getAgentClient(parentResource.getAgent());
mergeResourceResponse =
agentClient.getDiscoveryAgentService().manuallyAddResource(resourceType,
parentResourceId, pluginConfiguration, user.getId());
@@ -1060,4 +1070,21 @@ public class DiscoveryBossBean implements DiscoveryBossLocal,
DiscoveryBossRemot
return newValue != null && (oldValue == null ||
!newValue.equals(oldValue));
}
+ private void abortResourceManualAddIfExistingSingleton(Resource parentResource,
ResourceType resourceType) {
+ if (resourceType.isSingleton()) {
+ ResourceCriteria resourceCriteria = new ResourceCriteria();
+ resourceCriteria.addFilterParentResourceId(parentResource.getId());
+ resourceCriteria.addFilterResourceTypeId(resourceType.getId());
+ PageList<Resource> childResourcesOfType =
resourceManager.findResourcesByCriteria(subjectManager.getOverlord(),
+ resourceCriteria);
+ if (childResourcesOfType.size() >= 1) {
+ throw new RuntimeException("Cannot manually add " +
resourceType + " child Resource under parent "
+ + parentResource + ", since " + resourceType
+ + " is a singleton type, and there is already a child
Resource of that type. "
+ + "If the existing child Resource corresponds to a managed
Resource which no longer exists, "
+ + "uninventory it and then try again.");
+ }
+ }
+ }
+
}
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java
index b612c5e..8a9257f 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceFactoryManagerBean.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -51,6 +51,7 @@ import org.rhq.core.domain.content.InstalledPackage;
import org.rhq.core.domain.content.PackageType;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.content.transfer.ResourcePackageDetails;
+import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.resource.Agent;
import org.rhq.core.domain.resource.CreateResourceHistory;
import org.rhq.core.domain.resource.CreateResourceStatus;
@@ -58,6 +59,7 @@ import org.rhq.core.domain.resource.DeleteResourceHistory;
import org.rhq.core.domain.resource.DeleteResourceStatus;
import org.rhq.core.domain.resource.InventoryStatus;
import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCreationDataType;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.server.PersistenceUtility;
import org.rhq.core.domain.util.PageControl;
@@ -170,7 +172,7 @@ public class ResourceFactoryManagerBean implements
ResourceFactoryManagerLocal,
// There is some inconsistency if we're completing a request that was not in
the database
if (history == null) {
- log.error("Attemping to complete a request that was not found in the
database: " + response.getRequestId());
+ log.error("Attempting to complete a request that was not found in the
database: " + response.getRequestId());
return;
}
@@ -437,6 +439,14 @@ public class ResourceFactoryManagerBean implements
ResourceFactoryManagerLocal,
ResourceType newResourceType = entityManager.find(ResourceType.class,
newResourceTypeId);
PackageType newPackageType =
contentManager.getResourceCreationPackageType(newResourceTypeId);
+ if (!newResourceType.isCreatable() || (newResourceType.getCreationDataType() !=
ResourceCreationDataType.CONTENT)) {
+ throw new RuntimeException("Cannot create " + newResourceType +
" child Resource under parent "
+ + parentResource + ", since the " + newResourceType
+ + " type does not support content-based Resource
creation.");
+ }
+
+ abortResourceCreationIfExistingSingleton(parentResource, newResourceType);
+
// unless version is set start versioning the package by timestamp
packageVersionNumber = (null == packageVersionNumber) ?
Long.toString(System.currentTimeMillis())
: packageVersionNumber;
@@ -477,15 +487,23 @@ public class ResourceFactoryManagerBean implements
ResourceFactoryManagerLocal,
+ " of type: " + resourceTypeId);
ResourceType resourceType = entityManager.find(ResourceType.class,
resourceTypeId);
- Resource resource = entityManager.find(Resource.class, parentResourceId);
- Agent agent = resource.getAgent();
+ Resource parentResource = entityManager.find(Resource.class, parentResourceId);
+ Agent agent = parentResource.getAgent();
// Check permissions first
- if (!authorizationManager.hasResourcePermission(user,
Permission.CREATE_CHILD_RESOURCES, resource.getId())) {
+ if (!authorizationManager.hasResourcePermission(user,
Permission.CREATE_CHILD_RESOURCES, parentResource.getId())) {
throw new PermissionException("User [" + user.getName()
- + "] does not have permission to create a child resource for
resource [" + resource + "]");
+ + "] does not have permission to create a child resource for
resource [" + parentResource + "]");
+ }
+
+ if (!resourceType.isCreatable() || (resourceType.getCreationDataType() !=
ResourceCreationDataType.CONFIGURATION)) {
+ throw new RuntimeException("Cannot create " + resourceType + "
child Resource under parent "
+ + parentResource + ", since the " + resourceType
+ + " type does not support configuration-based Resource
creation.");
}
+ abortResourceCreationIfExistingSingleton(parentResource, resourceType);
+
// Persist in separate transaction so it is committed immediately, before the
request is sent to the agent
CreateResourceHistory persistedHistory =
resourceFactoryManager.persistCreateHistory(user, parentResourceId,
resourceTypeId, resourceName, resourceConfiguration);
@@ -573,6 +591,14 @@ public class ResourceFactoryManagerBean implements
ResourceFactoryManagerLocal,
ResourceType newResourceType = entityManager.find(ResourceType.class,
newResourceTypeId);
PackageVersion packageVersion = entityManager.find(PackageVersion.class,
packageVersionId);
+ if (!newResourceType.isCreatable() || (newResourceType.getCreationDataType() !=
ResourceCreationDataType.CONTENT)) {
+ throw new RuntimeException("Cannot create " + newResourceType +
" child Resource under parent "
+ + parentResource + ", since the " + newResourceType
+ + " type does not support content-based Resource
creation.");
+ }
+
+ abortResourceCreationIfExistingSingleton(parentResource, newResourceType);
+
return doCreatePackageBackedResource(subject, parentResource, newResourceType,
newResourceName,
pluginConfiguration, deploymentTimeConfiguration, packageVersion, timeout);
}
@@ -672,4 +698,22 @@ public class ResourceFactoryManagerBean implements
ResourceFactoryManagerLocal,
throw new RuntimeException("Error while sending delete resource request
to agent service", e);
}
}
+
+ private void abortResourceCreationIfExistingSingleton(Resource parentResource,
ResourceType resourceType) {
+ if (resourceType.isSingleton()) {
+ ResourceCriteria resourceCriteria = new ResourceCriteria();
+ resourceCriteria.addFilterParentResourceId(parentResource.getId());
+ resourceCriteria.addFilterResourceTypeId(resourceType.getId());
+ PageList<Resource> childResourcesOfType =
resourceManager.findResourcesByCriteria(subjectManager.getOverlord(),
+ resourceCriteria);
+ if (childResourcesOfType.size() >= 1) {
+ throw new RuntimeException("Cannot create " + resourceType +
" child Resource under parent "
+ + parentResource + ", since " + resourceType
+ + " is a singleton type, and there is already a child
Resource of that type. "
+ + "If the existing child Resource corresponds to a managed
Resource which no longer exists, "
+ + "uninventory it and then try again.");
+ }
+ }
+ }
+
}
diff --git
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.java
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.java
index 0dc28aa..1625480 100644
---
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.java
+++
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -25,7 +25,9 @@ import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.util.List;
import java.util.Random;
+import java.util.UUID;
+import javax.ejb.EJBException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.persistence.EntityManager;
@@ -42,6 +44,9 @@ import org.dbunit.ext.oracle.Oracle10DataTypeFactory;
import org.dbunit.ext.oracle.OracleDataTypeFactory;
import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
import org.dbunit.operation.DatabaseOperation;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
@@ -50,20 +55,38 @@ import org.xml.sax.InputSource;
import org.jboss.mx.util.MBeanServerLocator;
+import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService;
import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.discovery.MergeResourceResponse;
import org.rhq.core.domain.discovery.ResourceSyncInfo;
import org.rhq.core.domain.resource.Agent;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.core.comm.ServerCommunicationsService;
import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.util.ResourceTreeHelper;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.when;
+
+/**
+ * A unit test for {@link DiscoveryBossBean}.
+ */
public class DiscoveryBossBeanTest extends AbstractEJB3Test {
+
private DiscoveryBossLocal discoveryBoss;
+ private SubjectManagerLocal subjectManager;
+
+ private ResourceManagerLocal resourceManager;
+
private MBeanServer dummyJBossMBeanServer;
private ResourceType platformType;
@@ -76,9 +99,13 @@ public class DiscoveryBossBeanTest extends AbstractEJB3Test {
private Agent agent;
+ private TestServerCommunicationsService agentServiceContainer;
+
@BeforeClass
public void beforeClass() throws Exception {
discoveryBoss = LookupUtil.getDiscoveryBoss();
+ subjectManager = LookupUtil.getSubjectManager();
+ resourceManager = LookupUtil.getResourceManager();
}
@BeforeMethod
@@ -95,6 +122,26 @@ public class DiscoveryBossBeanTest extends AbstractEJB3Test {
serviceType1 = getEntityManager().find(ResourceType.class, 3);
serviceType2 = getEntityManager().find(ResourceType.class, 4);
agent = getEntityManager().find(Agent.class, 1);
+
+ agentServiceContainer = prepareForTestAgents();
+ agentServiceContainer.discoveryService =
Mockito.mock(DiscoveryAgentService.class);
+
when(agentServiceContainer.discoveryService.manuallyAddResource(any(ResourceType.class),
anyInt(),
+ any(Configuration.class), anyInt())).thenAnswer(new
Answer<MergeResourceResponse>() {
+ public MergeResourceResponse answer(InvocationOnMock invocation) throws
Throwable {
+ Resource resource = new Resource(1000000);
+ resource.setUuid(UUID.randomUUID().toString());
+ ResourceType resourceType = (ResourceType) invocation.getArguments()[0];
+ resource.setResourceType(resourceType);
+ long randomLong = UUID.randomUUID().getLeastSignificantBits();
+ resource.setResourceKey(String.valueOf("key-" + randomLong));
+ resource.setName("name-" + randomLong);
+ int parentResourceId = (Integer)invocation.getArguments()[1];
+ Resource parentResource =
resourceManager.getResource(subjectManager.getOverlord(), parentResourceId);
+ resource.setParentResource(parentResource);
+ Integer ownerSubjectId = (Integer) invocation.getArguments()[3];
+ return discoveryBoss.addResource(resource, ownerSubjectId);
+ }
+ });
}
@AfterMethod(alwaysRun = true)
@@ -158,6 +205,39 @@ public class DiscoveryBossBeanTest extends AbstractEJB3Test {
assert syncInfo != null;
}
+ @Test(groups = "integration.ejb3")
+ public void testManuallyAddResource() throws Exception {
+ InventoryReport inventoryReport = new InventoryReport(agent);
+
+ Resource platform = new Resource("alpha", "platform",
platformType);
+ Resource server = new Resource("bravo", "server",
serverType);
+ platform.addChildResource(server);
+ Resource service2 = new Resource("delta", "service 2",
serviceType2);
+ server.addChildResource(service2);
+
+ platform.setUuid("" + new Random().nextInt());
+ server.setUuid("" + new Random().nextInt());
+ service2.setUuid("" + new Random().nextInt());
+
+ inventoryReport.addAddedRoot(platform);
+
+ ResourceSyncInfo syncInfo =
discoveryBoss.mergeInventoryReport(serialize(inventoryReport));
+ assert syncInfo != null;
+
+ ResourceSyncInfo serverSyncInfo =
syncInfo.getChildSyncInfos().iterator().next();
+ Resource resource1 =
discoveryBoss.manuallyAddResource(subjectManager.getOverlord(), serviceType2.getId(),
+ serverSyncInfo.getId(), new Configuration());
+
+ try {
+ Resource resource2 =
discoveryBoss.manuallyAddResource(subjectManager.getOverlord(), serviceType2.getId(),
+ serverSyncInfo.getId(), new Configuration());
+ fail("Manually adding a singleton that already existed succeeded: "
+ resource2);
+ } catch (EJBException e) {
+ assertEquals(String.valueOf(e.getCause()), RuntimeException.class,
e.getCause().getClass());
+ assertTrue(String.valueOf(e.getCause()),
e.getCause().getMessage().contains("singleton"));
+ }
+ }
+
/**
* Use this to fake like your remoting objects. Can be used to keep your own copy of
objects locally transient.
*
diff --git
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceFactoryManagerBeanTest.java
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceFactoryManagerBeanTest.java
index fdb6607..cbcf1dc 100644
---
a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceFactoryManagerBeanTest.java
+++
b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/test/ResourceFactoryManagerBeanTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -23,7 +23,9 @@ import java.net.URL;
import java.util.List;
import java.util.Random;
import java.util.Set;
+import java.util.UUID;
+import javax.ejb.EJBException;
import javax.persistence.EntityManager;
import org.testng.annotations.AfterMethod;
@@ -42,6 +44,7 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.content.PackageCategory;
import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.resource.CreateDeletePolicy;
import org.rhq.core.domain.resource.CreateResourceHistory;
import org.rhq.core.domain.resource.CreateResourceStatus;
import org.rhq.core.domain.resource.DeleteResourceHistory;
@@ -49,9 +52,11 @@ import org.rhq.core.domain.resource.DeleteResourceStatus;
import org.rhq.core.domain.resource.InventoryStatus;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceCreationDataType;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.discovery.DiscoveryBossLocal;
import org.rhq.enterprise.server.resource.ResourceFactoryManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
@@ -60,13 +65,19 @@ import
org.rhq.enterprise.server.test.TestServerCommunicationsService;
import org.rhq.enterprise.server.util.LookupUtil;
/**
+ * A unit test for {@link
org.rhq.enterprise.server.resource.ResourceFactoryManagerBean}.
+ *
* @author Jason Dobies
*/
public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test {
+
+ private static final String TEST_PLUGIN_NAME = "TestPlugin";
+
// Attributes --------------------------------------------
private ResourceFactoryManagerLocal resourceFactoryManager;
private ResourceManagerLocal resourceManager;
+ private DiscoveryBossLocal discoveryBoss;
private Subject overlord;
private MockResourceFactoryAgentService mockAgentService = new
MockResourceFactoryAgentService();
@@ -74,7 +85,9 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test {
// Populated during setupResourceEnvironment
private Resource parentResource;
private ResourceType parentResourceType;
- private ResourceType childResourceType;
+ private ResourceType contentBackedChildResourceType;
+ private ResourceType configBackedChildResourceType1;
+ private ResourceType configBackedChildResourceType2;
private PackageType packageType;
// Setup --------------------------------------------
@@ -83,6 +96,7 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test {
public void setupBeforeClass() throws Exception {
resourceFactoryManager = LookupUtil.getResourceFactoryManager();
resourceManager = LookupUtil.getResourceManager();
+ discoveryBoss = LookupUtil.getDiscoveryBoss();
overlord = LookupUtil.getSubjectManager().getOverlord();
}
@@ -123,7 +137,7 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
resourceConfiguration.put(new PropertySimple("property1",
"value1"));
// Test
- resourceFactoryManager.createResource(overlord, parentResource.getId(),
childResourceType.getId(),
+ resourceFactoryManager.createResource(overlord, parentResource.getId(),
configBackedChildResourceType1.getId(),
"newResource", null, resourceConfiguration);
// Verify
@@ -164,7 +178,7 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
resourceConfiguration.put(new PropertySimple("property1",
"value1"));
// Test
- resourceFactoryManager.createResource(overlord, parentResource.getId(),
childResourceType.getId(),
+ resourceFactoryManager.createResource(overlord, parentResource.getId(),
configBackedChildResourceType1.getId(),
"newResource", null, resourceConfiguration);
// Verify
@@ -192,7 +206,70 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
}
@Test
- public void createResourceViaPackage() throws Exception {
+ public void createSingletonResourceViaConfiguration() throws Exception {
+ // Setup
+ mockAgentService.setCreateReturnStatus(CreateResourceStatus.SUCCESS);
+
+ // Assemble call parameters
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ Configuration resourceConfiguration = new Configuration();
+ resourceConfiguration.put(new PropertySimple("property1",
"value1"));
+
+ // Test
+ CreateResourceHistory history1 = resourceFactoryManager.createResource(overlord,
parentResource.getId(), configBackedChildResourceType2.getId(),
+ "newResource", null, resourceConfiguration);
+
+ // Verify
+ EntityManager entityManager = null;
+ try {
+ getTransactionManager().begin();
+ entityManager = getEntityManager();
+
+ Resource parent = entityManager.find(Resource.class,
parentResource.getId());
+ List<CreateResourceHistory> historyList =
parent.getCreateChildResourceRequests();
+
+ assert historyList.size() == 1 : "Incorrect number of children found.
Expected: 1, Found: "
+ + historyList.size();
+
+ CreateResourceHistory historyItem = historyList.get(0);
+
+ assert historyItem.getStatus() == CreateResourceStatus.SUCCESS :
"Incorrect status for history item. Expected: Success, Found: "
+ + historyItem.getStatus();
+ assert historyItem.getNewResourceKey().equals("mockResourceKey") :
"Incorrect resource key for history item. Expected: mockResourceKey, Found: "
+ + historyItem.getNewResourceKey();
+ assert historyItem.getErrorMessage() == null : "Error message found for
successful call";
+ assert historyItem.getConfiguration() != null : "Null configuration
found for history item";
+ } finally {
+ getTransactionManager().rollback();
+ entityManager.close();
+ }
+
+ // Invoke the same callbacks the plugin container would to actually commit the
new Resource to inventory.
+ resourceFactoryManager.completeCreateResource(new
CreateResourceResponse(history1.getId(), "newResource", "key",
+ CreateResourceStatus.SUCCESS, null, new Configuration()));
+ Resource resource = new Resource(1000000);
+ resource.setUuid(UUID.randomUUID().toString());
+ resource.setResourceType(configBackedChildResourceType2);
+ long randomLong = UUID.randomUUID().getLeastSignificantBits();
+ resource.setResourceKey(String.valueOf("key-" + randomLong));
+ resource.setName("name-" + randomLong);
+ resource.setParentResource(parentResource);
+ discoveryBoss.addResource(resource, overlord.getId());
+
+ // Now try to create another Resource of the same singleton type - this should
fail.
+ try {
+ CreateResourceHistory history2 =
resourceFactoryManager.createResource(overlord, parentResource.getId(),
+ configBackedChildResourceType2.getId(), "newResource2",
null, resourceConfiguration);
+ fail("Creating a singleton that already existed succeeded: " +
history2);
+ } catch (EJBException e) {
+ assertEquals(String.valueOf(e.getCause()), RuntimeException.class,
e.getCause().getClass());
+ assertTrue(String.valueOf(e.getCause()),
e.getCause().getMessage().contains("singleton"));
+ }
+ }
+
+ @Test
+ public void createSingletonResourceViaPackage() throws Exception {
// Setup
mockAgentService.setCreateReturnStatus(CreateResourceStatus.SUCCESS);
@@ -212,9 +289,9 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
InputStream packageInputStream = contentResource.openStream();
// Test
- resourceFactoryManager.createResource(overlord, parentResource.getId(),
childResourceType.getId(),
- "newResource", null, packageName, packageVersion, architectureId,
deploymentTimeConfiguration,
- packageInputStream);
+ CreateResourceHistory history1 = resourceFactoryManager.createResource(overlord,
parentResource.getId(), contentBackedChildResourceType.getId(),
+ "newResource", null, packageName, packageVersion,
architectureId, deploymentTimeConfiguration,
+ packageInputStream);
// Verify
EntityManager entityManager = null;
@@ -239,6 +316,29 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
getTransactionManager().rollback();
entityManager.close();
}
+
+ // Invoke the same callbacks the plugin container would to actually commit the
new Resource to inventory.
+ resourceFactoryManager.completeCreateResource(new
CreateResourceResponse(history1.getId(), "newResource", "key",
+ CreateResourceStatus.SUCCESS, null, new Configuration()));
+ Resource resource = new Resource(2000000);
+ resource.setUuid(UUID.randomUUID().toString());
+ resource.setResourceType(contentBackedChildResourceType);
+ long randomLong = UUID.randomUUID().getLeastSignificantBits();
+ resource.setResourceKey(String.valueOf("key-" + randomLong));
+ resource.setName("name-" + randomLong);
+ resource.setParentResource(parentResource);
+ discoveryBoss.addResource(resource, overlord.getId());
+
+ // Now try to create another Resource of the same singleton type - this should
fail.
+ try {
+ CreateResourceHistory history2 =
resourceFactoryManager.createResource(overlord, parentResource.getId(),
+ contentBackedChildResourceType.getId(), "newResource2",
null, packageName, packageVersion,
+ architectureId, deploymentTimeConfiguration, packageInputStream);
+ fail("Creating a singleton that already existed succeeded: " +
history2);
+ } catch (EJBException e) {
+ assertEquals(String.valueOf(e.getCause()), RuntimeException.class,
e.getCause().getClass());
+ assertTrue(String.valueOf(e.getCause()),
e.getCause().getMessage().contains("singleton"));
+ }
}
@Test
@@ -323,17 +423,17 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
resourceConfiguration = new Configuration();
resourceConfiguration.getMap();
- resourceFactoryManager.createResource(overlord, parentResource.getId(),
childResourceType.getId(), "resource1",
+ resourceFactoryManager.createResource(overlord, parentResource.getId(),
configBackedChildResourceType1.getId(), "resource1",
(Configuration) null, resourceConfiguration);
resourceConfiguration = new Configuration();
resourceConfiguration.getMap();
- resourceFactoryManager.createResource(overlord, parentResource.getId(),
childResourceType.getId(), "resource2",
- (Configuration) null, resourceConfiguration);
+ resourceFactoryManager.createResource(overlord, parentResource.getId(),
configBackedChildResourceType1.getId(), "resource2",
+ (Configuration) null, resourceConfiguration);
resourceConfiguration = new Configuration();
resourceConfiguration.getMap();
- resourceFactoryManager.createResource(overlord, parentResource.getId(),
childResourceType.getId(), "resource3",
+ resourceFactoryManager.createResource(overlord, parentResource.getId(),
configBackedChildResourceType1.getId(), "resource3",
(Configuration) null, resourceConfiguration);
// Verify
@@ -395,7 +495,7 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
Configuration resourceConfiguration = new Configuration();
resourceConfiguration.getMap();
- resourceFactoryManager.createResource(overlord, parentResource.getId(),
childResourceType.getId(),
+ resourceFactoryManager.createResource(overlord, parentResource.getId(),
configBackedChildResourceType1.getId(),
"NewResource", null, resourceConfiguration);
PageList<CreateResourceHistory> historyList =
resourceFactoryManager.findCreateChildResourceHistory(overlord,
parentResource.getId(), null, null, new PageControl(0, 1000));
@@ -425,14 +525,17 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
try {
try {
// Create parent resource type
- parentResourceType = new ResourceType("platform-" +
System.currentTimeMillis(), "TestPlugin",
+ parentResourceType = new ResourceType("platform-" +
System.currentTimeMillis(), TEST_PLUGIN_NAME,
ResourceCategory.PLATFORM, null);
em.persist(parentResourceType);
// Create child resource type to parent. Artifact type lives under this
resource type.
- childResourceType = new ResourceType("server-" +
System.currentTimeMillis(), "TestPlugin",
- ResourceCategory.SERVER, parentResourceType);
- em.persist(childResourceType);
+ contentBackedChildResourceType = new ResourceType("service-" +
System.currentTimeMillis(), TEST_PLUGIN_NAME,
+ ResourceCategory.SERVICE, parentResourceType);
+
contentBackedChildResourceType.setCreateDeletePolicy(CreateDeletePolicy.BOTH);
+
contentBackedChildResourceType.setCreationDataType(ResourceCreationDataType.CONTENT);
+ contentBackedChildResourceType.setSingleton(true);
+ em.persist(contentBackedChildResourceType);
// Create artifact type under child resource type that is marked as the
creation artifact type
packageType = new PackageType();
@@ -441,11 +544,24 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
packageType.setCategory(PackageCategory.DEPLOYABLE);
packageType.setDisplayName("TestResourceArtifact");
packageType.setCreationData(true);
- packageType.setResourceType(childResourceType);
+ packageType.setResourceType(contentBackedChildResourceType);
em.persist(packageType);
// Link artifact type and child resource type
- childResourceType.addPackageType(packageType);
+ contentBackedChildResourceType.addPackageType(packageType);
+
+ configBackedChildResourceType1 = new ResourceType("service1-" +
System.currentTimeMillis(), TEST_PLUGIN_NAME,
+ ResourceCategory.SERVICE, parentResourceType);
+
configBackedChildResourceType1.setCreateDeletePolicy(CreateDeletePolicy.BOTH);
+
configBackedChildResourceType1.setCreationDataType(ResourceCreationDataType.CONFIGURATION);
+ em.persist(configBackedChildResourceType1);
+
+ configBackedChildResourceType2 = new ResourceType("service2-" +
System.currentTimeMillis(), TEST_PLUGIN_NAME,
+ ResourceCategory.SERVICE, parentResourceType);
+
configBackedChildResourceType2.setCreateDeletePolicy(CreateDeletePolicy.BOTH);
+
configBackedChildResourceType2.setCreationDataType(ResourceCreationDataType.CONFIGURATION);
+ configBackedChildResourceType2.setSingleton(true);
+ em.persist(configBackedChildResourceType2);
// Create parent resource off of which to hang created resources
parentResource = new Resource("parent" +
System.currentTimeMillis(), "name", parentResourceType);
@@ -479,8 +595,14 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
getTransactionManager().begin();
EntityManager em = getEntityManager();
try {
- // Remove the child first.
- ResourceType deleteMeType = em.find(ResourceType.class,
childResourceType.getId());
+ // Remove the children first.
+ ResourceType deleteMeType = em.find(ResourceType.class,
contentBackedChildResourceType.getId());
+ em.remove(deleteMeType);
+
+ deleteMeType = em.find(ResourceType.class,
configBackedChildResourceType1.getId());
+ em.remove(deleteMeType);
+
+ deleteMeType = em.find(ResourceType.class,
configBackedChildResourceType2.getId());
em.remove(deleteMeType);
deleteMeType = em.find(ResourceType.class, parentResourceType.getId());
@@ -617,4 +739,5 @@ public class ResourceFactoryManagerBeanTest extends AbstractEJB3Test
{
return null;
}
}
+
}
\ No newline at end of file
diff --git
a/modules/enterprise/server/jar/src/test/resources/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml
b/modules/enterprise/server/jar/src/test/resources/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml
index b21cc8d..4891276 100644
---
a/modules/enterprise/server/jar/src/test/resources/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml
+++
b/modules/enterprise/server/jar/src/test/resources/org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml
@@ -52,7 +52,7 @@
creation_data_type="CONFIGURATION"
create_delete_policy="BOTH"
supports_manual_add="1"
- singleton="0"
+ singleton="1"
plugin="test"
deleted="0"/>