diff --git a/controller/src/main/java/org/jboss/as/controller/logging/ControllerLogger.java b/controller/src/main/java/org/jboss/as/controller/logging/ControllerLogger.java index 976576f92df..28caec8c980 100644 --- a/controller/src/main/java/org/jboss/as/controller/logging/ControllerLogger.java +++ b/controller/src/main/java/org/jboss/as/controller/logging/ControllerLogger.java @@ -36,6 +36,7 @@ import java.util.List; import java.util.Set; import java.util.concurrent.CancellationException; + import javax.xml.namespace.QName; import javax.xml.stream.Location; import javax.xml.stream.XMLStreamException; @@ -3332,35 +3333,17 @@ XMLStreamException discoveryOptionsMustBeDeclared(String adminOnlyCmd, String po @Message(id = 398, value = "An attempt was made to rename the resource found at %s to %s. However, '%s' is one of the resource types defined to be ordered on the parent resource %s") OperationFailedRuntimeException orderedChildTypeRenamed(PathAddress read, PathAddress transformed, String type, Set parentOrderedChildren); - @Message(id = 399, value = "Model references of type '%s' are missing: %s") - OperationFailedException missingReferences(String type, Set missing); - - @Message(id = 400, value = "Profile '%s' is involved in a cycle") - OperationFailedException profileInvolvedInACycle(String profile); - - @Message(id = 401, value = "Profile '%s' defines subsystem '%s' which is also defined in its ancestor profile '%s'. Overriding subsystems is not supported") - OperationFailedException profileAttemptingToOverrideSubsystem(String existingSubsystemProfile, String subsystem, String profileName); - - @Message(id = 402, value = "Socket binding group '%s' is involved in a cycle") - OperationFailedException socketBindingGroupInvolvedInACycle(String include); - - @Message(id = 403, value = "Socket binding group %s defines socket binding %s which is also defined in its ancestor socket binding group %s. Overriding socket bindings is not supported") - OperationFailedException socketBindingGroupAttemptingToOverrideSocketBinding(String existingSubsystemProfile, String child, String resourceName); - - @Message(id = 404, value = "The binding name '%s' in socket binding group '%s' is not unique. Names must be unique across socket-binding, local-destination-outbound-socket-binding and remote-destination-outbound-socket-binding") - OperationFailedException bindingNameNotUnique(String name, String groupName); - - @Message(id = 405, value = "The capability '%s' required by capability '%s' in context '%s' is available in one or " + + @Message(id = 399, value = "The capability '%s' required by capability '%s' in context '%s' is available in one or " + "more socket binding groups, but not all socket binding capabilities required by '%s' can be resolved from a " + "single socket binding group, so this configuration is invalid") String inconsistentCapabilityContexts(String requiredName, String dependentName, String dependentContext, String dependentContextAgain); @LogMessage(level = Level.ERROR) - @Message(id = 406, value = "Capability '%s' in context '%s' associated with resource '%s' requires capability '%s'. " + + @Message(id = 400, value = "Capability '%s' in context '%s' associated with resource '%s' requires capability '%s'. " + "It is available in one or more socket binding groups, but not all socket binding capabilities required by " + "'%s' can be resolved from a single socket binding group, so this configuration is invalid") void inconsistentCapabilityContexts(String dependentName, String dependentContext, String address, String requiredName, String dependentContextAgain); - @Message(id = 407, value = "Couldn't build the report") + @Message(id = 401, value = "Couldn't build the report") RuntimeException failedToBuildReport(@Cause Throwable t); } diff --git a/controller/src/test/java/org/jboss/as/controller/SocketCapabilityResolutionUnitTestCase.java b/controller/src/test/java/org/jboss/as/controller/SocketCapabilityResolutionUnitTestCase.java index 5649ee3d7fe..dba57fc1ae0 100644 --- a/controller/src/test/java/org/jboss/as/controller/SocketCapabilityResolutionUnitTestCase.java +++ b/controller/src/test/java/org/jboss/as/controller/SocketCapabilityResolutionUnitTestCase.java @@ -325,7 +325,7 @@ private static void validateInconsistentFailureDesc(ModelNode response, String s assertTrue(response.toString(), response.hasDefined(FAILURE_DESCRIPTION)); String failDesc = response.get(RESULT, step, FAILURE_DESCRIPTION).asString(); int lastLoc = -1; - int loc = failDesc.indexOf("WFLYCTL0405"); + int loc = failDesc.indexOf("WFLYCTL0399"); assertTrue(response.toString(), loc > lastLoc); lastLoc = loc; loc = failDesc.indexOf(req); diff --git a/host-controller/src/main/java/org/jboss/as/domain/controller/operations/DomainModelReferenceValidator.java b/host-controller/src/main/java/org/jboss/as/domain/controller/operations/DomainModelReferenceValidator.java index 635ca699226..f3397abca73 100644 --- a/host-controller/src/main/java/org/jboss/as/domain/controller/operations/DomainModelReferenceValidator.java +++ b/host-controller/src/main/java/org/jboss/as/domain/controller/operations/DomainModelReferenceValidator.java @@ -53,9 +53,9 @@ import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.ProcessType; -import org.jboss.as.controller.logging.ControllerLogger; import org.jboss.as.controller.registry.Resource; import org.jboss.as.controller.registry.Resource.ResourceEntry; +import org.jboss.as.host.controller.logging.HostControllerLogger; import org.jboss.dmr.ModelNode; /** @@ -150,19 +150,19 @@ public void validate(final OperationContext context) throws OperationFailedExcep } // If we are missing a server group if (!serverGroups.isEmpty()) { - throw ControllerLogger.ROOT_LOGGER.missingReferences(SERVER_GROUP, serverGroups); + throw HostControllerLogger.ROOT_LOGGER.missingReferences(SERVER_GROUP, serverGroups); } // We are missing a profile if (!missingProfiles.isEmpty()) { - throw ControllerLogger.ROOT_LOGGER.missingReferences(PROFILE, missingProfiles); + throw HostControllerLogger.ROOT_LOGGER.missingReferences(PROFILE, missingProfiles); } // Process socket-binding groups if (!missingSocketBindingGroups.isEmpty()) { - throw ControllerLogger.ROOT_LOGGER.missingReferences(SOCKET_BINDING_GROUP, missingSocketBindingGroups); + throw HostControllerLogger.ROOT_LOGGER.missingReferences(SOCKET_BINDING_GROUP, missingSocketBindingGroups); } //We are missing an interface if (!interfaces.isEmpty()) { - throw ControllerLogger.ROOT_LOGGER.missingReferences(INTERFACE, interfaces); + throw HostControllerLogger.ROOT_LOGGER.missingReferences(INTERFACE, interfaces); } } @@ -231,48 +231,80 @@ void processResource(ResourceEntry resourceEntry) throws OperationFailedExceptio void validate(Set missingEntries) throws OperationFailedException { //Look for cycles - for (String profileName : resourceIncludes.keySet()) { - if (!seen.contains(profileName)) { - dfsForMissingOrCyclicIncludes(profileName, missingEntries); + for (String resourceName : resourceIncludes.keySet()) { + if (!seen.contains(resourceName)) { + dfsForMissingOrCyclicIncludes(resourceName, missingEntries); } } if (missingEntries.size() > 0) { - //We are missing some profiles, don't continue with the validation since it has failed + //We are missing some entries, don't continue with the validation since it has failed return; } - //Check that subsystems are not overridden, by traversing them in the order child->parent + //Check that children are not overridden, by traversing them in the order child->parent //using the reverse post-order of the dfs seen.clear(); for (ListIterator it = post.listIterator(post.size()) ; it.hasPrevious() ; ) { - String profile = it.previous(); - if (seen.contains(profile)) { + String resourceName = it.previous(); + if (seen.contains(resourceName)) { continue; } - Map subsystems = new HashMap<>(); - validateChildrenNotOverridden(profile, subsystems); + List stack = new ArrayList<>(); + Map> reachableChildren = new HashMap<>(); + validateChildrenNotOverridden(resourceName, reachableChildren, stack); } } - void validateChildrenNotOverridden(String resourceName, Map children) throws OperationFailedException { - seen.add(resourceName); - Set includes = resourceIncludes.get(resourceName); - if (includes.size() == 0 && children.size() == 0) { - return; - } - for (String child : resourceChildren.get(resourceName)) { - String existingSubsystemProfile = children.get(child); - if (existingSubsystemProfile != null) { - throw profileAttemptingToOverrideSubsystem(existingSubsystemProfile, child, resourceName); + void validateChildrenNotOverridden(String resourceName, Map> reachableChildren, + List stack) throws OperationFailedException { + stack.add(resourceName); + try { + seen.add(resourceName); + Set includes = resourceIncludes.get(resourceName); + Set children = resourceChildren.get(resourceName); + if (includes.size() == 0 && children.size() == 0) { + return; } - children.put(child, resourceName); + for (String child : resourceChildren.get(resourceName)) { + List existingChildParentStack = reachableChildren.get(child); + if (existingChildParentStack != null) { + logError(resourceName, stack, child, existingChildParentStack); + } + reachableChildren.put(child, new ArrayList<>(stack)); + } + for (String include : includes) { + validateChildrenNotOverridden(include, reachableChildren, stack); + } + } finally { + stack.remove(stack.size() - 1); } - for (String include : includes) { - validateChildrenNotOverridden(include, children); + } + + private void logError(String resourceName, List stack, String child, List existingChildParentStack) throws OperationFailedException { + //Now figure out if this is a direct override, or no override but including two parents + //with the same child + for (ListIterator it = stack.listIterator(stack.size()) ; it.hasPrevious() ; ) { + String commonParent = it.previous(); + if (existingChildParentStack.contains(commonParent)) { + if (!getLastElement(existingChildParentStack).equals(commonParent)) { + //This is not an override but 'commonParent' includes two parents with the same child + throw twoParentsWithSameChild(commonParent, getLastElement(stack), getLastElement(existingChildParentStack), child); + } + } } + //It is a direct override + //Alternatively, something went wrong when trying to determine the cause, in which case this message + //will not be 100% correct, but it is better to get an error than not. + throw attemptingToOverride(getLastElement(existingChildParentStack), child, resourceName); } + private String getLastElement(List list) { + return list.get(list.size() - 1); + } + + protected abstract OperationFailedException twoParentsWithSameChild(String commonParent, String include1, String include2, String child); + void dfsForMissingOrCyclicIncludes(String resourceName, Set missingEntries) throws OperationFailedException { onStack.add(resourceName); try { @@ -287,7 +319,7 @@ void dfsForMissingOrCyclicIncludes(String resourceName, Set missingEntri linkTo.put(include, resourceName); dfsForMissingOrCyclicIncludes(include, missingEntries); } else if (onStack.contains(include)) { - throw profileInvolvedInACycle(include); + throw involvedInACycle(include); } } } finally { @@ -296,8 +328,8 @@ void dfsForMissingOrCyclicIncludes(String resourceName, Set missingEntri post.add(resourceName); } - abstract OperationFailedException profileAttemptingToOverrideSubsystem(String existingSubsystemProfile, String child, String resourceName); - abstract OperationFailedException profileInvolvedInACycle(String profile); + abstract OperationFailedException attemptingToOverride(String parentOfExistingChild, String child, String resourceName); + abstract OperationFailedException involvedInACycle(String profile); } @@ -317,13 +349,18 @@ void processResource(ResourceEntry profileEntry) throws OperationFailedException } @Override - OperationFailedException profileAttemptingToOverrideSubsystem(String existingSubsystemProfile, String child, String resourceName) { - return ControllerLogger.ROOT_LOGGER.profileAttemptingToOverrideSubsystem(existingSubsystemProfile, child, resourceName); + OperationFailedException attemptingToOverride(String parentOfExistingChild, String child, String resourceName) { + return HostControllerLogger.ROOT_LOGGER.profileAttemptingToOverrideSubsystem(parentOfExistingChild, child, resourceName); } @Override - OperationFailedException profileInvolvedInACycle(String include) { - return ControllerLogger.ROOT_LOGGER.profileInvolvedInACycle(include); + OperationFailedException involvedInACycle(String include) { + return HostControllerLogger.ROOT_LOGGER.profileInvolvedInACycle(include); + } + + @Override + protected OperationFailedException twoParentsWithSameChild(String commonParent, String include1, String include2, String child) { + return HostControllerLogger.ROOT_LOGGER.profileIncludesSameSubsystem(commonParent, include1, include2, child); } } @@ -354,21 +391,25 @@ private void addBindings(ResourceEntry groupEntry, Set bindings, String if (groupEntry.hasChildren(bindingType)) { for (String name : groupEntry.getChildrenNames(bindingType)) { if (!bindings.add(name)) { - throw ControllerLogger.ROOT_LOGGER.bindingNameNotUnique(name, groupEntry.getName()); + throw HostControllerLogger.ROOT_LOGGER.bindingNameNotUnique(name, groupEntry.getName()); } } } } @Override - OperationFailedException profileAttemptingToOverrideSubsystem(String existingSubsystemProfile, String child, String resourceName) { - return ControllerLogger.ROOT_LOGGER.socketBindingGroupAttemptingToOverrideSocketBinding(existingSubsystemProfile, child, resourceName); + OperationFailedException attemptingToOverride(String parentOfExistingChild, String child, String resourceName) { + return HostControllerLogger.ROOT_LOGGER.socketBindingGroupAttemptingToOverrideSocketBinding(parentOfExistingChild, child, resourceName); } @Override - OperationFailedException profileInvolvedInACycle(String include) { - return ControllerLogger.ROOT_LOGGER.socketBindingGroupInvolvedInACycle(include); + OperationFailedException involvedInACycle(String include) { + return HostControllerLogger.ROOT_LOGGER.socketBindingGroupInvolvedInACycle(include); } + @Override + protected OperationFailedException twoParentsWithSameChild(String commonParent, String include1, String include2, String child) { + return HostControllerLogger.ROOT_LOGGER.socketBindingGroupIncludesSameSocketBinding(commonParent, include1, include2, child); + } } } diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/logging/HostControllerLogger.java b/host-controller/src/main/java/org/jboss/as/host/controller/logging/HostControllerLogger.java index 593c18b298c..ebca1654af5 100644 --- a/host-controller/src/main/java/org/jboss/as/host/controller/logging/HostControllerLogger.java +++ b/host-controller/src/main/java/org/jboss/as/host/controller/logging/HostControllerLogger.java @@ -27,6 +27,7 @@ import java.net.URI; import java.net.URL; import java.nio.file.Path; +import java.util.Set; import javax.security.sasl.SaslException; import javax.xml.stream.Location; @@ -1226,4 +1227,29 @@ void noDomainControllerConfigurationProvidedForAdminOnly(String policyAttribute, @Message(id = 160, value = "Could not read or create the domain UUID in file: %s") IllegalStateException couldNotObtainDomainUuid(@Cause Throwable cause, Path file); + + @Message(id = 161, value = "Model references of type '%s' are missing: %s") + OperationFailedException missingReferences(String type, Set missing); + + @Message(id = 162, value = "The binding name '%s' in socket binding group '%s' is not unique. Names must be unique across socket-binding, local-destination-outbound-socket-binding and remote-destination-outbound-socket-binding") + OperationFailedException bindingNameNotUnique(String name, String groupName); + + @Message(id = 163, value = "Profile '%s' is involved in a cycle") + OperationFailedException profileInvolvedInACycle(String profile); + + @Message(id = 164, value = "Profile '%s' defines subsystem '%s' which is also defined in its ancestor profile '%s'. Overriding subsystems is not supported") + OperationFailedException profileAttemptingToOverrideSubsystem(String existingSubsystemProfile, String subsystem, String profileName); + + @Message(id = 165, value = "Socket binding group '%s' is involved in a cycle") + OperationFailedException socketBindingGroupInvolvedInACycle(String include); + + @Message(id = 166, value = "Socket binding group '%s' defines socket binding '%s' which is also defined in its ancestor socket binding group '%s'. Overriding socket bindings is not supported") + OperationFailedException socketBindingGroupAttemptingToOverrideSocketBinding(String existingSubsystemProfile, String child, String resourceName); + + @Message(id = 167, value = "Profile '%s' includes profile '%s' and profile '%s'. Both these profiles define subsystem '%s', which is not supported") + OperationFailedException profileIncludesSameSubsystem(String profile, String include1, String include2, String child); + + @Message(id = 168, value = "Socket binding group '%s' includes socket binding group '%s' and socket binding group '%s'. Both these socket binding groups define socket binding '%s', which is not supported") + OperationFailedException socketBindingGroupIncludesSameSocketBinding(String socketBindingGroup, String include1, String include2, String child); + } diff --git a/host-controller/src/test/java/org/jboss/as/domain/controller/operations/ProfileIncludesHandlerTestCase.java b/host-controller/src/test/java/org/jboss/as/domain/controller/operations/ProfileIncludesHandlerTestCase.java index c8a8334ac40..0cda2f288ca 100644 --- a/host-controller/src/test/java/org/jboss/as/domain/controller/operations/ProfileIncludesHandlerTestCase.java +++ b/host-controller/src/test/java/org/jboss/as/domain/controller/operations/ProfileIncludesHandlerTestCase.java @@ -55,6 +55,7 @@ import org.jboss.msc.service.ServiceRegistry; import org.jboss.msc.service.StartException; import org.jboss.threads.AsyncFuture; +import org.junit.Assert; import org.junit.Test; /** @@ -74,7 +75,6 @@ public void testGoodProfileIncludesAdd() throws Exception { } - @Test(expected=OperationFailedException.class) public void testBadProfileIncludesAdd() throws Exception { PathAddress addr = getProfileAddress("test"); ModelNode op = Util.createAddOperation(addr); @@ -156,28 +156,108 @@ public void addAdditionalResources(Resource root) { operationContext.executeNextStep(); } - @Test(expected = OperationFailedException.class) + @Test public void testIncludesWithOverriddenSubsystems() throws Exception { - //Here we test changing the includes attribute value - //Testing what happens when adding subsystems at runtime becomes a bit too hard to mock up - //so we test that in ServerManagementTestCase - PathAddress addr = getProfileAddress("profile-four"); - ModelNode list = new ModelNode().add("profile-three"); - ModelNode op = Util.getWriteAttributeOperation(addr, INCLUDES, list); - MockOperationContext operationContext = getOperationContextForSubsystemIncludes(addr, new RootResourceInitializer() { - @Override - public void addAdditionalResources(Resource root) { - Resource subsystemA = Resource.Factory.create(); - root.getChild(PathElement.pathElement(PROFILE, "profile-three")) - .registerChild(PathElement.pathElement(SUBSYSTEM, "a"), subsystemA); + try { + //Here we test changing the includes attribute value + //Testing what happens when adding subsystems at runtime becomes a bit too hard to mock up + //so we test that in ServerManagementTestCase + PathAddress addr = getProfileAddress("profile-four"); + ModelNode list = new ModelNode().add("profile-three"); + ModelNode op = Util.getWriteAttributeOperation(addr, INCLUDES, list); + MockOperationContext operationContext = getOperationContextForSubsystemIncludes(addr, new RootResourceInitializer() { + @Override + public void addAdditionalResources(Resource root) { + Resource subsystemA = Resource.Factory.create(); + root.getChild(PathElement.pathElement(PROFILE, "profile-three")) + .registerChild(PathElement.pathElement(SUBSYSTEM, "a"), subsystemA); + + Resource subsystemB = Resource.Factory.create(); + Resource profile4 = root.getChild(PathElement.pathElement(PROFILE, "profile-four")); + profile4.registerChild(PathElement.pathElement(SUBSYSTEM, "a"), subsystemB); + } + }); + ProfileResourceDefinition.createReferenceValidationHandler().execute(operationContext, op); + operationContext.executeNextStep(); + Assert.fail("Expected error"); + } catch (OperationFailedException expected) { + Assert.assertTrue(expected.getMessage().contains("164")); + Assert.assertTrue(expected.getMessage().contains("'profile-four'")); + Assert.assertTrue(expected.getMessage().contains("'a'")); + Assert.assertTrue(expected.getMessage().contains("'profile-three'")); + } + } - Resource subsystemB = Resource.Factory.create(); - Resource profile4 = root.getChild(PathElement.pathElement(PROFILE, "profile-four")); - profile4.registerChild(PathElement.pathElement(SUBSYSTEM, "a"), subsystemB); - } - }); - ProfileResourceDefinition.createReferenceValidationHandler().execute(operationContext, op); - operationContext.executeNextStep(); + @Test + public void testProfileWithSubsystemsIncludesSameSubsystems() throws Exception { + try { + //Here we test changing the includes attribute value + //Testing what happens when adding subsystems at runtime becomes a bit too hard to mock up + //so we test that in ServerManagementTestCase + PathAddress addr = getProfileAddress("profile-five"); + ModelNode list = new ModelNode().add("profile-three").add("profile-four"); + ModelNode op = Util.getWriteAttributeOperation(addr, INCLUDES, list); + MockOperationContext operationContext = getOperationContextForSubsystemIncludes(addr, new RootResourceInitializer() { + @Override + public void addAdditionalResources(Resource root) { + Resource subsystemA = Resource.Factory.create(); + root.getChild(PathElement.pathElement(PROFILE, "profile-three")) + .registerChild(PathElement.pathElement(SUBSYSTEM, "a"), subsystemA); + + Resource subsystemB = Resource.Factory.create(); + Resource profile4 = root.getChild(PathElement.pathElement(PROFILE, "profile-four")); + profile4.registerChild(PathElement.pathElement(SUBSYSTEM, "a"), subsystemB); + + Resource subsystemC = Resource.Factory.create(); + Resource profile5 = root.getChild(PathElement.pathElement(PROFILE, "profile-five")); + profile5.registerChild(PathElement.pathElement(SUBSYSTEM, "x"), subsystemC); + } + }); + ProfileResourceDefinition.createReferenceValidationHandler().execute(operationContext, op); + operationContext.executeNextStep(); + Assert.fail("Expected error"); + } catch (OperationFailedException expected) { + Assert.assertTrue(expected.getMessage().contains("167")); + Assert.assertTrue(expected.getMessage().contains("'profile-five'")); + Assert.assertTrue(expected.getMessage().contains("'profile-four'")); + Assert.assertTrue(expected.getMessage().contains("'profile-three'")); + Assert.assertTrue(expected.getMessage().contains("'a'")); + } + } + + @Test + public void testEmptyProfileIncludesSameSubsystems() throws Exception { + try { + //Here we test changing the includes attribute value + //Testing what happens when adding subsystems at runtime becomes a bit too hard to mock up + //so we test that in ServerManagementTestCase + PathAddress addr = getProfileAddress("profile-five"); + ModelNode list = new ModelNode().add("profile-three").add("profile-four"); + ModelNode op = Util.getWriteAttributeOperation(addr, INCLUDES, list); + MockOperationContext operationContext = getOperationContextForSubsystemIncludes(addr, new RootResourceInitializer() { + @Override + public void addAdditionalResources(Resource root) { + Resource subsystemA = Resource.Factory.create(); + root.getChild(PathElement.pathElement(PROFILE, "profile-three")) + .registerChild(PathElement.pathElement(SUBSYSTEM, "a"), subsystemA); + + Resource subsystemB = Resource.Factory.create(); + Resource profile4 = root.getChild(PathElement.pathElement(PROFILE, "profile-four")); + profile4.registerChild(PathElement.pathElement(SUBSYSTEM, "a"), subsystemB); + + //profile-four is empty + } + }); + ProfileResourceDefinition.createReferenceValidationHandler().execute(operationContext, op); + operationContext.executeNextStep(); + Assert.fail("Expected error"); + } catch (OperationFailedException expected) { + Assert.assertTrue(expected.getMessage().contains("167")); + Assert.assertTrue(expected.getMessage().contains("'profile-five'")); + Assert.assertTrue(expected.getMessage().contains("'profile-four'")); + Assert.assertTrue(expected.getMessage().contains("'profile-three'")); + Assert.assertTrue(expected.getMessage().contains("'a'")); + } } private PathAddress getProfileAddress(String profileName) { @@ -209,6 +289,10 @@ MockOperationContext getOperationContextForSubsystemIncludes(final PathAddress o Resource profileFour = Resource.Factory.create(); root.registerChild(PathElement.pathElement(PROFILE, "profile-four"), profileFour); + + Resource profileFive = Resource.Factory.create(); + root.registerChild(PathElement.pathElement(PROFILE, "profile-five"), profileFive); + initializer.addAdditionalResources(root); return new MockOperationContext(root, false, operationAddress, false); } diff --git a/host-controller/src/test/java/org/jboss/as/domain/controller/operations/SocketBindingGroupIncludesHandlerTestCase.java b/host-controller/src/test/java/org/jboss/as/domain/controller/operations/SocketBindingGroupIncludesHandlerTestCase.java index 0a4db3a6526..b7af2dc03ba 100644 --- a/host-controller/src/test/java/org/jboss/as/domain/controller/operations/SocketBindingGroupIncludesHandlerTestCase.java +++ b/host-controller/src/test/java/org/jboss/as/domain/controller/operations/SocketBindingGroupIncludesHandlerTestCase.java @@ -45,6 +45,7 @@ import org.jboss.as.controller.client.OperationResponse; import org.jboss.as.controller.operations.common.Util; import org.jboss.as.controller.registry.Resource; +import org.jboss.as.domain.controller.resources.ProfileResourceDefinition; import org.jboss.as.host.controller.MasterDomainControllerClient; import org.jboss.as.repository.HostFileRepository; import org.jboss.dmr.ModelNode; @@ -57,6 +58,7 @@ import org.jboss.msc.service.ServiceRegistry; import org.jboss.msc.service.StartException; import org.jboss.threads.AsyncFuture; +import org.junit.Assert; import org.junit.Test; /** @@ -160,30 +162,112 @@ public void addAdditionalResources(Resource root) { operationContext.executeNextStep(); } - @Test(expected = OperationFailedException.class) + @Test public void testIncludesWithOverriddenSocketBindings() throws Exception { - //Here we test changing the includes attribute value - //Testing what happens when adding subsystems at runtime becomes a bit too hard to mock up - //so we test that in ServerManagementTestCase - PathAddress addr = getSocketBindingGroupAddress("binding-four"); - ModelNode list = new ModelNode().add("binding-three"); - ModelNode op = Util.getWriteAttributeOperation(addr, INCLUDES, list); - MockOperationContext operationContext = getOperationContextForSocketBindingIncludes(addr, new RootResourceInitializer() { - @Override - public void addAdditionalResources(Resource root) { - Resource subsystemA = Resource.Factory.create(); - root.getChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-three")) - .registerChild(PathElement.pathElement(SOCKET_BINDING, "a"), subsystemA); + try { + //Here we test changing the includes attribute value + //Testing what happens when adding subsystems at runtime becomes a bit too hard to mock up + //so we test that in ServerManagementTestCase + PathAddress addr = getSocketBindingGroupAddress("binding-four"); + ModelNode list = new ModelNode().add("binding-three"); + ModelNode op = Util.getWriteAttributeOperation(addr, INCLUDES, list); + MockOperationContext operationContext = getOperationContextForSocketBindingIncludes(addr, new RootResourceInitializer() { + @Override + public void addAdditionalResources(Resource root) { + Resource subsystemA = Resource.Factory.create(); + root.getChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-three")) + .registerChild(PathElement.pathElement(SOCKET_BINDING, "a"), subsystemA); + + Resource subsystemB = Resource.Factory.create(); + Resource SocketBindingGroup4 = root.getChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-four")); + SocketBindingGroup4.registerChild(PathElement.pathElement(SOCKET_BINDING, "a"), subsystemB); + } + }); + SocketBindingGroupResourceDefinition.createReferenceValidationHandler().execute(operationContext, op); + operationContext.executeNextStep(); + Assert.fail("Expected error"); + } catch (OperationFailedException expected) { + Assert.assertTrue(expected.getMessage().contains("166")); + Assert.assertTrue(expected.getMessage().contains("'binding-four'")); + Assert.assertTrue(expected.getMessage().contains("'binding-three'")); + Assert.assertTrue(expected.getMessage().contains("'a'")); + } + } - Resource subsystemB = Resource.Factory.create(); - Resource SocketBindingGroup4 = root.getChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-four")); - SocketBindingGroup4.registerChild(PathElement.pathElement(SOCKET_BINDING, "a"), subsystemB); - } - }); - SocketBindingGroupResourceDefinition.createReferenceValidationHandler().execute(operationContext, op); - operationContext.executeNextStep(); + + @Test + public void testGroupWithBindingsIncludesSameBindings() throws Exception { + try { + //Here we test changing the includes attribute value + //Testing what happens when adding subsystems at runtime becomes a bit too hard to mock up + //so we test that in ServerManagementTestCase + PathAddress addr = getSocketBindingGroupAddress("binding-five"); + ModelNode list = new ModelNode().add("binding-three").add("binding-four"); + ModelNode op = Util.getWriteAttributeOperation(addr, INCLUDES, list); + MockOperationContext operationContext = getOperationContextForSocketBindingIncludes(addr, new RootResourceInitializer() { + @Override + public void addAdditionalResources(Resource root) { + Resource bindingA = Resource.Factory.create(); + root.getChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-three")) + .registerChild(PathElement.pathElement(SOCKET_BINDING, "a"), bindingA); + + Resource bindingB = Resource.Factory.create(); + Resource group4 = root.getChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-four")); + group4.registerChild(PathElement.pathElement(SOCKET_BINDING, "a"), bindingB); + + Resource bindingC = Resource.Factory.create(); + Resource group5 = root.getChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-five")); + group5.registerChild(PathElement.pathElement(SOCKET_BINDING, "x"), bindingC); + } + }); + ProfileResourceDefinition.createReferenceValidationHandler().execute(operationContext, op); + operationContext.executeNextStep(); + Assert.fail("Expected error"); + } catch (OperationFailedException expected) { + Assert.assertTrue(expected.getMessage().contains("168")); + Assert.assertTrue(expected.getMessage().contains("'binding-five'")); + Assert.assertTrue(expected.getMessage().contains("'binding-four'")); + Assert.assertTrue(expected.getMessage().contains("'binding-three'")); + Assert.assertTrue(expected.getMessage().contains("'a'")); + } } + @Test + public void testEmptyGroupIncludesSameBindings() throws Exception { + try { + //Here we test changing the includes attribute value + //Testing what happens when adding subsystems at runtime becomes a bit too hard to mock up + //so we test that in ServerManagementTestCase + PathAddress addr = getSocketBindingGroupAddress("binding-five"); + ModelNode list = new ModelNode().add("binding-three").add("binding-four"); + ModelNode op = Util.getWriteAttributeOperation(addr, INCLUDES, list); + MockOperationContext operationContext = getOperationContextForSocketBindingIncludes(addr, new RootResourceInitializer() { + @Override + public void addAdditionalResources(Resource root) { + Resource bindingA = Resource.Factory.create(); + root.getChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-three")) + .registerChild(PathElement.pathElement(SOCKET_BINDING, "a"), bindingA); + + Resource bindingB = Resource.Factory.create(); + Resource group4 = root.getChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-four")); + group4.registerChild(PathElement.pathElement(SOCKET_BINDING, "a"), bindingB); + + //binding-five is empty + } + }); + ProfileResourceDefinition.createReferenceValidationHandler().execute(operationContext, op); + operationContext.executeNextStep(); + Assert.fail("Expected error"); + } catch (OperationFailedException expected) { + Assert.assertTrue(expected.getMessage().contains("168")); + Assert.assertTrue(expected.getMessage().contains("'binding-five'")); + Assert.assertTrue(expected.getMessage().contains("'binding-four'")); + Assert.assertTrue(expected.getMessage().contains("'binding-three'")); + Assert.assertTrue(expected.getMessage().contains("'a'")); + } + } + + private PathAddress getSocketBindingGroupAddress(String SocketBindingGroupName) { return PathAddress.pathAddress(SOCKET_BINDING_GROUP, SocketBindingGroupName); } @@ -196,23 +280,28 @@ MockOperationContext getOperationContext(final PathAddress operationAddress) { MockOperationContext getOperationContextWithIncludes(final PathAddress operationAddress) { final Resource root = createRootResource(); - Resource SocketBindingGroupThree = Resource.Factory.create(); - root.registerChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-three"), SocketBindingGroupThree); + Resource socketBindingGroupThree = Resource.Factory.create(); + root.registerChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-three"), socketBindingGroupThree); + + Resource socketBindingGroupFour = Resource.Factory.create(); + socketBindingGroupFour.getModel().get(INCLUDES).add("binding-three"); + root.registerChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-four"), socketBindingGroupFour); - Resource SocketBindingGroupFour = Resource.Factory.create(); - SocketBindingGroupFour.getModel().get(INCLUDES).add("binding-three"); - root.registerChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-four"), SocketBindingGroupFour); return new MockOperationContext(root, false, operationAddress, false); } MockOperationContext getOperationContextForSocketBindingIncludes(final PathAddress operationAddress, RootResourceInitializer initializer) { final Resource root = createRootResource(); - Resource SocketBindingGroupThree = Resource.Factory.create(); - root.registerChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-three"), SocketBindingGroupThree); + Resource socketBindingGroupThree = Resource.Factory.create(); + root.registerChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-three"), socketBindingGroupThree); + + Resource socketBindingGroupFour = Resource.Factory.create(); + root.registerChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-four"), socketBindingGroupFour); + + Resource socketBindingGroupFive = Resource.Factory.create(); + root.registerChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-five"), socketBindingGroupFive); - Resource SocketBindingGroupFour = Resource.Factory.create(); - root.registerChild(PathElement.pathElement(SOCKET_BINDING_GROUP, "binding-four"), SocketBindingGroupFour); initializer.addAdditionalResources(root); return new MockOperationContext(root, false, operationAddress, false); }