Java Code Examples for org.jboss.as.controller.OperationContext#attach()

The following examples show how to use org.jboss.as.controller.OperationContext#attach() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DeploymentUploadUtil.java    From wildfly-core with GNU Lesser General Public License v2.1 6 votes vote down vote up
/**
 * Store the deployment contents and attach a "transformed" slave operation to the operation context.
 *
 * @param context the operation context
 * @param operation the original operation
 * @param contentRepository the content repository
 * @return the hash of the uploaded deployment content
 * @throws IOException
 * @throws OperationFailedException
 */
public static byte[] storeContentAndTransformOperation(OperationContext context, ModelNode operation, ContentRepository contentRepository) throws IOException, OperationFailedException {
    if (!operation.hasDefined(CONTENT)) {
        throw createFailureException(DomainControllerLogger.ROOT_LOGGER.invalidContentDeclaration());
    }
    final ModelNode content = operation.get(CONTENT).get(0);
    if (content.hasDefined(HASH)) {
        // This should be handled as part of the OSH
        throw createFailureException(DomainControllerLogger.ROOT_LOGGER.invalidContentDeclaration());
    }
    final byte[] hash = storeDeploymentContent(context, operation, contentRepository);

    // Clear the contents and update with the hash
    final ModelNode slave = operation.clone();
    slave.get(CONTENT).setEmptyList().add().get(HASH).set(hash);
    // Add the domain op transformer
    List<DomainOperationTransmuter> transformers = context.getAttachment(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS);
    if (transformers == null) {
        context.attach(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS, transformers = new ArrayList<>());
    }
    transformers.add(new CompositeOperationAwareTransmuter(slave));
    return hash;
}
 
Example 2
Source File: DeploymentUploadUtil.java    From wildfly-core with GNU Lesser General Public License v2.1 6 votes vote down vote up
public static byte[] storeEmptyContentAndTransformOperation(OperationContext context, ModelNode operation, ContentRepository contentRepository) throws OperationFailedException {
    final byte[] hash = storeEmptyDeploymentContent(context, contentRepository);

    // Clear the contents and update with the hash
    final ModelNode slave = operation.clone();
    slave.remove(EMPTY.getName());
    ModelNode contentItemNode = new ModelNode();
    contentItemNode.get(CONTENT_HASH.getName()).set(hash);
    contentItemNode.get(CONTENT_ARCHIVE.getName()).set(false);
    slave.get(CONTENT).setEmptyList().add(contentItemNode);
    // Add the domain op transformer
    List<DomainOperationTransmuter> transformers = context.getAttachment(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS);
    if (transformers == null) {
        context.attach(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS, transformers = new ArrayList<>());
    }
    transformers.add(new CompositeOperationAwareTransmuter(slave));
    return hash;
}
 
Example 3
Source File: AffectedDeploymentOverlay.java    From wildfly-core with GNU Lesser General Public License v2.1 6 votes vote down vote up
/**
 * It will look for all the deployments under the deploymentsRootAddress with a runtimeName in the specified list of
 * runtime names and then transform the operation so that every server having those deployments will redeploy the
 * affected deployments.
 *
 * @see #transformOperation
 * @param removeOperation
 * @param context
 * @param deploymentsRootAddress
 * @param runtimeNames
 * @throws OperationFailedException
 */
 public static void redeployLinksAndTransformOperation(OperationContext context, ModelNode removeOperation, PathAddress deploymentsRootAddress, Set<String> runtimeNames) throws OperationFailedException {
    Set<String> deploymentNames = listDeployments(context.readResourceFromRoot(deploymentsRootAddress), runtimeNames);
    Operations.CompositeOperationBuilder opBuilder = Operations.CompositeOperationBuilder.create();
    if (deploymentNames.isEmpty()) {
        for (String s : runtimeNames) {
            ServerLogger.ROOT_LOGGER.debugf("We haven't found any deployment for %s in server-group %s", s, deploymentsRootAddress.getLastElement().getValue());
        }
    }
    if(removeOperation != null) {
         opBuilder.addStep(removeOperation);
    }
    for (String deploymentName : deploymentNames) {
        opBuilder.addStep(addRedeployStep(deploymentsRootAddress.append(DEPLOYMENT, deploymentName)));
    }
    List<DomainOperationTransmuter> transformers = context.getAttachment(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS);
    if (transformers == null) {
        context.attach(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS, transformers = new ArrayList<>());
    }
    final ModelNode slave = opBuilder.build().getOperation();
    transformers.add(new OverlayOperationTransmuter(slave, context.getCurrentAddress()));
}
 
Example 4
Source File: DeploymentUploadUtil.java    From wildfly-core with GNU Lesser General Public License v2.1 6 votes vote down vote up
/**
 * Remove contents from the deployment and attach a "transformed" slave operation to the operation context.
 *
 * @param context the operation context
 * @param operation the original operation
 * @param contentRepository the content repository
 * @return the hash of the uploaded deployment content
 * @throws IOException
 * @throws OperationFailedException
 */
public static byte[] removeContentFromExplodedAndTransformOperation(OperationContext context, ModelNode operation, ContentRepository contentRepository) throws OperationFailedException, ExplodedContentException {
    final Resource deploymentResource = context.readResource(PathAddress.EMPTY_ADDRESS);
    ModelNode contentItemNode = getContentItem(deploymentResource);
    final byte[] oldHash = CONTENT_HASH.resolveModelAttribute(context, contentItemNode).asBytes();
    final List<String> paths = REMOVED_PATHS.unwrap(context, operation);
    final byte[] hash = contentRepository.removeContentFromExploded(oldHash, paths);

    // Clear the contents and update with the hash
    final ModelNode slave = operation.clone();
    slave.get(CONTENT).setEmptyList().add().get(HASH).set(hash);
    slave.get(CONTENT).add().get(ARCHIVE).set(false);
    // Add the domain op transformer
    List<DomainOperationTransmuter> transformers = context.getAttachment(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS);
    if (transformers == null) {
        context.attach(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS, transformers = new ArrayList<>());
    }
    transformers.add(new CompositeOperationAwareTransmuter(slave));
    return hash;
}
 
Example 5
Source File: ManagementInterfaceAddStepHandler.java    From wildfly-core with GNU Lesser General Public License v2.1 6 votes vote down vote up
@Override
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
    List<ServiceName> failures = new ArrayList<>();
    ServiceRegistry registry = context.getServiceRegistry(false);
    for (ServiceName serviceName : requiredServices) {
        try {
            ServiceController<?> controller = registry.getService(serviceName);
            if (controller == null || State.UP != controller.getState()) {
                failures.add(serviceName);
            }
        } catch (ServiceNotFoundException ex) {
            failures.add(serviceName);
        }
    }
    if (!failures.isEmpty()) {
        Boolean attachment = context.getAttachment(MANAGEMENT_INTERFACE_KEY);
        if (attachment == null || !context.getAttachment(MANAGEMENT_INTERFACE_KEY)) {
            context.attach(MANAGEMENT_INTERFACE_KEY, false);
            context.addStep(new VerifyInstallationStep(), OperationContext.Stage.VERIFY);
        }
    } else {
        context.attach(MANAGEMENT_INTERFACE_KEY, true);
    }
}
 
Example 6
Source File: Transformers.java    From wildfly-core with GNU Lesser General Public License v2.1 6 votes vote down vote up
/**
 * Obtains a set of {@code TransformationInputs} from the given operation context. If the
 * context's {@link OperationContext#getCurrentStage() current stage} is
 * {@link org.jboss.as.controller.OperationContext.Stage#DOMAIN} any inputs cached with
 * the context as an attachment will be used, and if none are cached, then the created inputs
 * will be cached.
 *
 * @param context the operation context. Cannot be {@code null}
 * @return the inputs. Will not be {@code null}
 */
public static TransformationInputs getOrCreate(OperationContext context) {
    TransformationInputs result;
    if (context.getCurrentStage() == OperationContext.Stage.DOMAIN) {
        // Stage.DOMAIN means the model is not going to change, so we can safely cache.
        // We want to cache because reading the entire model is expensive, so we don't
        // want to do it for every process we need to interact with in a domain roll out.
        result = context.getAttachment(KEY);
        if (result == null) {
            result = new TransformationInputs(context);
            context.attach(KEY, result);
        }
    } else {
        result = new TransformationInputs(context);
    }
    return result;
}
 
Example 7
Source File: ServerOperationResolver.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
private static ModelNode getOriginalDomainModel(OperationContext context) {
    ModelNode model = context.getAttachment(ORIGINAL_DOMAIN_MODEL_ATTACHMENT);
    if (model == null) {
        model = Resource.Tools.readModel(context.getOriginalRootResource());
        context.attach(ORIGINAL_DOMAIN_MODEL_ATTACHMENT, model);
    }
    return model;
}
 
Example 8
Source File: DeploymentOverlayContentAdd.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
@Override
protected void populateModel(final OperationContext context, final ModelNode operation, final Resource resource) throws OperationFailedException {
    final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR));
    final String path = address.getLastElement().getValue();
    final String name = address.getElement(address.size() - 2).getValue();
    final ModelNode content = DeploymentOverlayContentDefinition.CONTENT_PARAMETER.validateOperation(operation);
    validateOnePieceOfContent(content);
    final byte[] hash;
    if (content.hasDefined(HASH)) {
        hash = content.require(HASH).asBytes();
        addFromHash(hash, name, path, address, context);
    } else {
        hash = addFromContentAdditionParameter(context, content);

        final ModelNode slave = operation.clone();
        slave.get(CONTENT).clear();
        slave.get(CONTENT).get(HASH).set(hash);

        List<DomainOperationTransmuter> transformers = context.getAttachment(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS);
        if(transformers == null) {
            context.attach(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS, transformers = new ArrayList<DomainOperationTransmuter>());
        }
        transformers.add(new CompositeOperationAwareTransmuter(slave));
    }
    contentRepository.addContentReference(ModelContentReference.fromModelAddress(address, hash));

    ModelNode modified = operation.clone();
    modified.get(CONTENT).clone();
    modified.get(CONTENT).set(hash);
    for (AttributeDefinition attr : DeploymentOverlayContentDefinition.attributes()) {
        attr.validateAndSet(modified, resource.getModel());
    }
    if (!contentRepository.syncContent(ModelContentReference.fromModelAddress(address, hash))) {
        throw ServerLogger.ROOT_LOGGER.noSuchDeploymentContent(Arrays.toString(hash));
    }
}
 
Example 9
Source File: AffectedDeploymentOverlay.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
/**
 * It will look for all the deployments (in every server-group) with a runtimeName in the specified list of runtime
 * names and then transform the operation so that every server in those server groups will redeploy the affected
 * deployments.
 *
 * @param removeOperation
 * @see #transformOperation
 * @param context
 * @param runtimeNames
 * @throws OperationFailedException
 */
public static void redeployLinksAndTransformOperationForDomain(OperationContext context, Set<String> runtimeNames, ModelNode removeOperation) throws OperationFailedException {
    Set<String> serverGroupNames = listServerGroupsReferencingOverlay(context.readResourceFromRoot(PathAddress.EMPTY_ADDRESS), context.getCurrentAddressValue());
    Map<String, Set<String>> deploymentPerServerGroup = new HashMap<>();
    for (String serverGoupName : serverGroupNames) {
        deploymentPerServerGroup.put(serverGoupName,
                listDeployments(context.readResourceFromRoot(PathAddress.pathAddress(PathElement.pathElement(SERVER_GROUP, serverGoupName))),runtimeNames));
    }
    if (deploymentPerServerGroup.isEmpty()) {
        for (String s : runtimeNames) {
            ServerLogger.ROOT_LOGGER.debugf("We haven't found any server-group for %s", s);
        }
    }
    Operations.CompositeOperationBuilder opBuilder = Operations.CompositeOperationBuilder.create();
    if(removeOperation != null) {
         opBuilder.addStep(removeOperation);
    }
    //Add a deploy step for each affected deployment in its server-group.
    for (Map.Entry<String, Set<String>> entry : deploymentPerServerGroup.entrySet()) {
        if ((! entry.getValue().isEmpty())) {
            for (String deploymentName : entry.getValue()) {
                opBuilder.addStep(addRedeployStep(context.getCurrentAddress().getParent().append(SERVER_GROUP, entry.getKey()).append(DEPLOYMENT, deploymentName)));
            }
        }
    }
    // Add the domain op transformer
    List<DomainOperationTransmuter> transformers = context.getAttachment(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS);
    if (transformers == null) {
        context.attach(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS, transformers = new ArrayList<>());
    }
    final ModelNode slave = opBuilder.build().getOperation();
    transformers.add(new OverlayOperationTransmuter(slave, context.getCurrentAddress()));
}
 
Example 10
Source File: EarlyResponseTransactionControl.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
@Override
public void operationPrepared(ModelController.OperationTransaction transaction, final ModelNode preparedResult, OperationContext context) {
    transaction.commit();
    if (context == null || !reload) { // TODO deal with shutdown as well, the handlers for which have some
                                      // subtleties that need thought
        sendResponse(preparedResult);
    } else {
        context.attach(EarlyResponseSendListener.ATTACHMENT_KEY, new EarlyResponseSendListener() {
            @Override
            public void sendEarlyResponse(OperationContext.ResultAction resultAction) {
                sendResponse(preparedResult);
            }
        });
    }
}
 
Example 11
Source File: CredentialReference.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
public static void handleCredentialReferenceUpdate(OperationContext context, ModelNode credentialReference, String credentialReferenceAttributeName) throws OperationFailedException {
    final String credentialStoreName;
    final String credentialType;
    final String secret;
    final String credentialAlias;

    if (credentialReference.isDefined()) {
        credentialStoreName = credentialReferencePartAsStringIfDefined(credentialReference, CredentialReference.STORE);
        credentialAlias = credentialReferencePartAsStringIfDefined(credentialReference, ALIAS);
        credentialType = credentialReferencePartAsStringIfDefined(credentialReference, CredentialReference.TYPE);
        secret = credentialReferencePartAsStringIfDefined(credentialReference, CLEAR_TEXT);
    } else {
        credentialStoreName = null;
        credentialAlias = null;
        credentialType = null;
        secret = null;
    }

    boolean removeSecret = false;
    if (credentialStoreName != null && secret != null) {
        if (credentialAlias != null) {
            removeSecret = true;
        } else if (! (credentialType != null && credentialType.equalsIgnoreCase("COMMAND")) && ! secret.startsWith("MASK-")) {
            credentialReference.get(ALIAS).set(generateAlias());
            removeSecret = true;
        }
        if (removeSecret) {
            // need to remove clear-text attribute from model
            Map<String, CredentialStoreUpdateInfo> credentialStoreUpdateInfoMap = context.getAttachment(CREDENTIAL_STORE_UPDATE_INFO);
            if (credentialStoreUpdateInfoMap == null) {
                credentialStoreUpdateInfoMap = Collections.synchronizedMap(new HashMap<>());
                context.attach(CREDENTIAL_STORE_UPDATE_INFO, credentialStoreUpdateInfoMap);
            }
            credentialStoreUpdateInfoMap.put(getAttachmentMapKey(context, credentialReferenceAttributeName), new CredentialStoreUpdateInfo(secret));
            credentialReference.get(CLEAR_TEXT).set(new ModelNode());
        }
    }
}
 
Example 12
Source File: ProfileDescribeHandler.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
@Override
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
    final AuthorizationResult authResult = context.authorize(operation, DESCRIBE_EFFECTS);
    authResult.failIfDenied(operation, context.getCurrentAddress());

    // WFCORE-1353. If this op is being used as part of a server launch, pass that info
    // to any subsystem describe handlers.
    if (SERVER_LAUNCH.resolveModelAttribute(context, operation).asBoolean()) {
        context.attach(GenericSubsystemDescribeHandler.SERVER_LAUNCH_KEY, Boolean.TRUE);
    }

    super.execute(context, operation);
}
 
Example 13
Source File: ElytronDefinition.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
    if (context.isResourceServiceRestartAllowed()) {
        registerAuthConfigFactory(null);
        SecurityPropertyService securityPropertyService = uninstallSecurityPropertyService(context);
        if (securityPropertyService != null) {
            context.attach(SECURITY_PROPERTY_SERVICE_KEY, securityPropertyService);
        }
        context.removeService(ProviderRegistrationService.SERVICE_NAME);
    } else {
        context.reloadRequired();
    }
}
 
Example 14
Source File: ServerOperationResolver.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
private static ModelNode getDomainModel(OperationContext context) {
    ModelNode model = context.getAttachment(DOMAIN_MODEL_ATTACHMENT);
    if (model == null) {
        model = Resource.Tools.readModel(context.readResourceFromRoot(PathAddress.EMPTY_ADDRESS, true));
        context.attach(DOMAIN_MODEL_ATTACHMENT, model);
    }
    return model;
}
 
Example 15
Source File: ReadMasterDomainOperationsHandler.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
@Override
public void execute(final OperationContext context, final ModelNode operation) throws OperationFailedException {
    context.acquireControllerLock();
    context.attach(PathAddressFilter.KEY, DEFAULT_FILTER);
    context.attach(OrderedChildTypesAttachment.KEY, orderedChildTypesAttachment);
    context.addStep(operation, GenericModelDescribeOperationHandler.INSTANCE, OperationContext.Stage.MODEL, true);
}
 
Example 16
Source File: DeploymentUploadUtil.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
/**
 * Add contents to the deployment and attach a "transformed" slave operation to the operation context.
 *
 * @param context the operation context
 * @param operation the original operation
 * @param contentRepository the content repository
 * @return the hash of the uploaded deployment content
 * @throws IOException
 * @throws OperationFailedException
 */
public static byte[] addContentToExplodedAndTransformOperation(OperationContext context, ModelNode operation, ContentRepository contentRepository) throws OperationFailedException, ExplodedContentException {
    final Resource deploymentResource = context.readResource(PathAddress.EMPTY_ADDRESS);
    ModelNode contentItem = getContentItem(deploymentResource);
    byte[] oldHash = CONTENT_HASH.resolveModelAttribute(context, contentItem).asBytes();
    List<ModelNode> contents = CONTENT_PARAM_ALL_EXPLODED.resolveModelAttribute(context, operation).asList();
    final List<ExplodedContent> addedFiles = new ArrayList<>(contents.size());

    final ModelNode slave = operation.clone();
    ModelNode slaveAddedfiles = slave.get(UPDATED_PATHS.getName()).setEmptyList();
    for(ModelNode content : contents) {
        InputStream in;
        if(hasValidContentAdditionParameterDefined(content)) {
            in = getInputStream(context, content);
        } else {
            in = null;
        }
        String path = TARGET_PATH.resolveModelAttribute(context, content).asString();
        addedFiles.add(new ExplodedContent(path, in));
        slaveAddedfiles.add(path);
    }
    final boolean overwrite = OVERWRITE.resolveModelAttribute(context, operation).asBoolean(true);
    final byte[] hash = contentRepository.addContentToExploded(oldHash, addedFiles, overwrite);

    // Clear the contents and update with the hash
    ModelNode addedContent = new ModelNode().setEmptyObject();
    addedContent.get(HASH).set(hash);
    addedContent.get(TARGET_PATH.getName()).set(".");
    slave.get(CONTENT).setEmptyList().add(addedContent);
    // Add the domain op transformer
    List<DomainOperationTransmuter> transformers = context.getAttachment(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS);
    if (transformers == null) {
        context.attach(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS, transformers = new ArrayList<>());
    }
    transformers.add(new CompositeOperationAwareTransmuter(slave));
    return hash;
}
 
Example 17
Source File: DeploymentUploadUtil.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
/**
 * Explode the deployment contents and attach a "transformed" slave operation to the operation context.
 *
 * @param context the operation context
 * @param operation the original operation
 * @param contentRepository the content repository
 * @return the hash of the uploaded deployment content
 * @throws IOException
 * @throws OperationFailedException
 */
public static byte[] explodeContentAndTransformOperation(OperationContext context, ModelNode operation, ContentRepository contentRepository) throws OperationFailedException, ExplodedContentException {
    final Resource deploymentResource = context.readResource(PathAddress.EMPTY_ADDRESS);
    ModelNode contentItem = getContentItem(deploymentResource);
    ModelNode explodedPath = DEPLOYMENT_CONTENT_PATH.resolveModelAttribute(context, operation);
    byte[] oldHash = CONTENT_HASH.resolveModelAttribute(context, contentItem).asBytes();
    final byte[] hash;
    if (explodedPath.isDefined()) {
        hash = contentRepository.explodeSubContent(oldHash, explodedPath.asString());
    } else {
        hash = contentRepository.explodeContent(oldHash);
    }

    // Clear the contents and update with the hash
    final ModelNode slave = operation.clone();
    ModelNode addedContent = new ModelNode().setEmptyObject();
    addedContent.get(HASH).set(hash);
    addedContent.get(TARGET_PATH.getName()).set("./");
    slave.get(CONTENT).setEmptyList().add(addedContent);
    // Add the domain op transformer
    List<DomainOperationTransmuter> transformers = context.getAttachment(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS);
    if (transformers == null) {
        context.attach(OperationAttachments.SLAVE_SERVER_OPERATION_TRANSMUTERS, transformers = new ArrayList<>());
    }
    transformers.add(new CompositeOperationAwareTransmuter(slave));
    return hash;
}
 
Example 18
Source File: WildcardReadResourceDescriptionAddressHack.java    From wildfly-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
/**
 *
 * @param context
 * @param operation
 */
static void attachAliasAddress(OperationContext context, ModelNode operation) {
    if (operation.get(OP).asString().equals(READ_RESOURCE_DESCRIPTION_OPERATION)) {
        context.attach(ALIAS_ORIGINAL_ADDRESS, PathAddress.pathAddress(operation.get(OP_ADDR)));
    }
}
 
Example 19
Source File: RbacSanityCheckOperation.java    From wildfly-core with GNU Lesser General Public License v2.1 3 votes vote down vote up
/**
 * Add the operation at the end of Stage MODEL if this operation has not already been registered.
 *
 * This operation should be added if any of the following occur: -
 *   - The authorization configuration is removed from a security realm.
 *   - The rbac provider is changed to rbac.
 *   - A role is removed.
 *   - An include is removed from a role.
 *   - A management interface is removed.
 *
 * Note: This list only includes actions that could invalidate the configuration, actions that would not invalidate the
 * configuration do not need this operation registering. e.g. Adding a role, if the configuration was already valid this
 * could not invalidate it.
 *
 * @param context - The OperationContext to use to register the step.
 */
public static void addOperation(final OperationContext context) {
    RbacSanityCheckOperation added = context.getAttachment(KEY);
    if (added == null) {
        // TODO support managed domain
        if (!context.isNormalServer()) return;
        context.addStep(createOperation(), INSTANCE, Stage.MODEL);
        context.attach(KEY, INSTANCE);
    }
}