Skip to content

Commit

Permalink
Merge pull request #881 from kabir/WFCORE-815
Browse files Browse the repository at this point in the history
Trigger validation of includes also when a profile/s-g-b is empty
  • Loading branch information
kabir committed Jul 15, 2015
2 parents c631f22 + e9edcfa commit dda0234
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 111 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -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<String> parentOrderedChildren);

@Message(id = 399, value = "Model references of type '%s' are missing: %s")
OperationFailedException missingReferences(String type, Set<String> 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);
}
Expand Up @@ -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);
Expand Down
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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);
}

}
Expand Down Expand Up @@ -231,48 +231,80 @@ void processResource(ResourceEntry resourceEntry) throws OperationFailedExceptio

void validate(Set<String> 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<String> 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<String, String> subsystems = new HashMap<>();
validateChildrenNotOverridden(profile, subsystems);
List<String> stack = new ArrayList<>();
Map<String, List<String>> reachableChildren = new HashMap<>();
validateChildrenNotOverridden(resourceName, reachableChildren, stack);
}
}

void validateChildrenNotOverridden(String resourceName, Map<String, String> children) throws OperationFailedException {
seen.add(resourceName);
Set<String> 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<String, List<String>> reachableChildren,
List<String> stack) throws OperationFailedException {
stack.add(resourceName);
try {
seen.add(resourceName);
Set<String> includes = resourceIncludes.get(resourceName);
Set<String> children = resourceChildren.get(resourceName);
if (includes.size() == 0 && children.size() == 0) {
return;
}
children.put(child, resourceName);
for (String child : resourceChildren.get(resourceName)) {
List<String> 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<String> stack, String child, List<String> 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<String> 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<String> list) {
return list.get(list.size() - 1);
}

protected abstract OperationFailedException twoParentsWithSameChild(String commonParent, String include1, String include2, String child);

void dfsForMissingOrCyclicIncludes(String resourceName, Set<String> missingEntries) throws OperationFailedException {
onStack.add(resourceName);
try {
Expand All @@ -287,7 +319,7 @@ void dfsForMissingOrCyclicIncludes(String resourceName, Set<String> missingEntri
linkTo.put(include, resourceName);
dfsForMissingOrCyclicIncludes(include, missingEntries);
} else if (onStack.contains(include)) {
throw profileInvolvedInACycle(include);
throw involvedInACycle(include);
}
}
} finally {
Expand All @@ -296,8 +328,8 @@ void dfsForMissingOrCyclicIncludes(String resourceName, Set<String> 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);
}


Expand All @@ -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);
}
}

Expand Down Expand Up @@ -354,21 +391,25 @@ private void addBindings(ResourceEntry groupEntry, Set<String> 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);
}
}
}
Expand Up @@ -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;
Expand Down Expand Up @@ -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<String> 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);

}

0 comments on commit dda0234

Please sign in to comment.