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@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"/>
rhq-commits@lists.fedorahosted.org