Merge remote-tracking branch 'upstream/master'
|
@ -1,27 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<!--
|
|
||||||
~ JBoss, Home of Professional Open Source.
|
|
||||||
~ Copyright 2010, Red Hat, Inc., and individual contributors
|
|
||||||
~ as indicated by the @author tags. See the copyright.txt file in the
|
|
||||||
~ distribution for a full listing of individual contributors.
|
|
||||||
~
|
|
||||||
~ This is free software; you can redistribute it and/or modify it
|
|
||||||
~ under the terms of the GNU Lesser General Public License as
|
|
||||||
~ published by the Free Software Foundation; either version 2.1 of
|
|
||||||
~ the License, or (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ This software is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
~ Lesser General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU Lesser General Public
|
|
||||||
~ License along with this software; if not, write to the Free
|
|
||||||
~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
||||||
~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
@ -86,7 +64,6 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.wildfly.core</groupId>
|
<groupId>org.wildfly.core</groupId>
|
||||||
<artifactId>wildfly-cli</artifactId>
|
<artifactId>wildfly-cli</artifactId>
|
||||||
<version>${wildfly.core.version}</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.picketlink</groupId>
|
<groupId>org.picketlink</groupId>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<artifact name="org.jboss.aesh:aesh:0.33.12"/>
|
<!-- Insert resources here -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<main-class name="org.jboss.as.cli.CommandLineMain"/>
|
<main-class name="org.jboss.as.cli.CommandLineMain"/>
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<resource-root path="wildfly-cli-1.0.0.Alpha11-SNAPSHOT.jar"/>
|
<!-- Insert resources here -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -799,7 +799,7 @@ keycloak-war-dist-all-&project.version;/
|
||||||
<title>Using CLI and CLI GUI with the Keycloak Subsystem</title>
|
<title>Using CLI and CLI GUI with the Keycloak Subsystem</title>
|
||||||
<para>
|
<para>
|
||||||
Servers can also be added/removed or enabled/disabled at runtime using the <ulink url="https://developer.jboss.org/wiki/CommandLineInterface">CLI</ulink> or
|
Servers can also be added/removed or enabled/disabled at runtime using the <ulink url="https://developer.jboss.org/wiki/CommandLineInterface">CLI</ulink> or
|
||||||
<ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> tool. These are tools that ship with WildFly and also with
|
<ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> tool. These are tools that ship with WildFly/EAP and also with
|
||||||
the Keycloak Appliance installation. See <ulink url="https://developer.jboss.org/wiki/CommandLineInterface">CLI</ulink> or
|
the Keycloak Appliance installation. See <ulink url="https://developer.jboss.org/wiki/CommandLineInterface">CLI</ulink> or
|
||||||
<ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> documentation to learn more about how to start the tools,
|
<ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> documentation to learn more about how to start the tools,
|
||||||
issue commands, and create CLI scripts.
|
issue commands, and create CLI scripts.
|
||||||
|
@ -812,7 +812,7 @@ cd <APPLIANCE_INSTALL_DIR>/keycloak/bin
|
||||||
or
|
or
|
||||||
./jboss.cli.bat --gui]]>
|
./jboss.cli.bat --gui]]>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<note>Your Keycloak server must be running to start in --gui mode.</note>
|
<note>Your server must be running to start in --gui mode.</note>
|
||||||
</para>
|
</para>
|
||||||
<section>
|
<section>
|
||||||
<title>Basic CLI Commands</title>
|
<title>Basic CLI Commands</title>
|
||||||
|
@ -842,7 +842,7 @@ The Keycloak server will be immediately deployed or undeployed, but not deleted.
|
||||||
<title>Uploading extra configuration using CLI</title>
|
<title>Uploading extra configuration using CLI</title>
|
||||||
<para>
|
<para>
|
||||||
The WildFly Keycloak subsystem allows you to upload keycloak-server.json, provider jars, and theme jars to a Keycloak server instance. The
|
The WildFly Keycloak subsystem allows you to upload keycloak-server.json, provider jars, and theme jars to a Keycloak server instance. The
|
||||||
CLI operations for this are "update-server-config" and "add-provider". You may use plain or CLI scripts for these operations. The following
|
CLI operations for this are "update-server-config" and "add-provider". You may use CLI, CLI GUI, or CLI scripts for these operations. The following
|
||||||
examples are shown using <ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> for clarity.
|
examples are shown using <ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> for clarity.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
|
@ -874,6 +874,39 @@ The Keycloak server will be immediately deployed or undeployed, but not deleted.
|
||||||
<imagedata fileref="images/add-provider-dialog.png"/>
|
<imagedata fileref="images/add-provider-dialog.png"/>
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
<section>
|
||||||
|
<title>Working with overlays</title>
|
||||||
|
<para>
|
||||||
|
When you upload a provider jar, theme jar, or keycloak-server.json file, you are creating an overlay. That is, the file is "overlayed"
|
||||||
|
onto the Keycloak server at deploy time. There are two additional operations that help you manage these overlays. They are "list-overlays" and
|
||||||
|
"remove-overlay". Here are CLI examples of these operations.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
/subsystem=keycloak/auth-server=my-auth-server/:list-overlays
|
||||||
|
{
|
||||||
|
"outcome" => "success",
|
||||||
|
"result" => [
|
||||||
|
"/WEB-INF/classes/META-INF/keycloak-server.json",
|
||||||
|
"/WEB-INF/lib/federation-properties-example.jar"
|
||||||
|
],
|
||||||
|
}</programlisting>
|
||||||
|
<programlisting>
|
||||||
|
/subsystem=keycloak/auth-server=my-auth-server/:remove-overlay(overlay-file-path=/WEB-INF/lib/federation-properties-example.jar,redeploy=true)
|
||||||
|
{
|
||||||
|
"outcome" => "success",
|
||||||
|
}</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<note>
|
||||||
|
Notice in the "list-overlays" operation, the full path to the server config is
|
||||||
|
/WEB-INF/classes/META-INF/keycloak-server.json. This is always the uploaded path for an "update-server-config" operation.
|
||||||
|
If you remove this overlay, the Keycloak server will revert to its default keycloak-server.json. If you have a
|
||||||
|
keycloak-server.json file in your <WILDFLY_HOME>/standalone/configuration directory, it will always take precedence
|
||||||
|
over both the default and the overlay.
|
||||||
|
</note>
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<title>Adding a Keycloak server in Domain Mode</title>
|
<title>Adding a Keycloak server in Domain Mode</title>
|
||||||
|
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 80 KiB |
|
@ -21,12 +21,11 @@ import org.jboss.as.controller.OperationContext;
|
||||||
import org.jboss.as.controller.OperationFailedException;
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
import org.jboss.as.controller.OperationStepHandler;
|
import org.jboss.as.controller.OperationStepHandler;
|
||||||
import org.jboss.as.controller.PathAddress;
|
import org.jboss.as.controller.PathAddress;
|
||||||
import org.jboss.as.controller.PathElement;
|
|
||||||
import org.jboss.as.controller.ProcessType;
|
import org.jboss.as.controller.ProcessType;
|
||||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT_OVERLAY;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
|
||||||
import org.jboss.as.controller.operations.common.Util;
|
import org.jboss.as.controller.operations.common.Util;
|
||||||
import org.jboss.as.controller.registry.Resource;
|
import org.jboss.as.controller.registry.Resource;
|
||||||
import org.jboss.dmr.ModelNode;
|
import org.jboss.dmr.ModelNode;
|
||||||
|
@ -48,21 +47,39 @@ public abstract class AbstractAddOverlayHandler implements OperationStepHandler
|
||||||
.setAllowNull(false)
|
.setAllowNull(false)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
static final SimpleAttributeDefinition REDEPLOY_SERVER =
|
||||||
|
new SimpleAttributeDefinitionBuilder("redeploy", ModelType.BOOLEAN, true)
|
||||||
|
.setXmlName("redeploy")
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setDefaultValue(new ModelNode(false))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
protected static final SimpleAttributeDefinition OVERWRITE =
|
||||||
|
new SimpleAttributeDefinitionBuilder("overwrite", ModelType.BOOLEAN, true)
|
||||||
|
.setXmlName("overwrite")
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setDefaultValue(new ModelNode(false))
|
||||||
|
.build();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(final OperationContext context, final ModelNode operation) throws OperationFailedException {
|
public void execute(final OperationContext context, final ModelNode operation) throws OperationFailedException {
|
||||||
//System.out.println("*** execute operation ***");
|
//System.out.println("*** execute operation ***");
|
||||||
//System.out.println(scrub(operation));
|
//System.out.println(scrub(operation));
|
||||||
|
|
||||||
String uploadFileName = operation.get(UPLOADED_FILE_OP_NAME).asString();
|
String uploadFileName = operation.get(UPLOADED_FILE_OP_NAME).asString();
|
||||||
String overlayPath = getOverlayPath(uploadFileName);
|
boolean isRedeploy = isRedeploy(context, operation);
|
||||||
String overlayName = AuthServerUtil.getAuthServerName(operation) + "-keycloak-overlay";
|
boolean isOverwrite = getBooleanFromOperation(operation, OVERWRITE);
|
||||||
PathAddress overlayAddress = PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT_OVERLAY, overlayName));
|
|
||||||
|
|
||||||
boolean isOverlayExists = isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
|
String overlayPath = getOverlayPath(uploadFileName);
|
||||||
|
String overlayName = AuthServerUtil.getOverlayName(operation);
|
||||||
|
PathAddress overlayAddress = AuthServerUtil.getOverlayAddress(overlayName);
|
||||||
|
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
||||||
|
|
||||||
|
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
|
||||||
if (!isOverlayExists) {
|
if (!isOverlayExists) {
|
||||||
addOverlay(context, overlayAddress);
|
addOverlay(context, overlayAddress);
|
||||||
if (!isHostController(context)) {
|
if (!isHostController(context)) {
|
||||||
addDeploymentToOverlay(context, overlayAddress, AuthServerUtil.getDeploymentName(operation));
|
addDeploymentToOverlay(context, overlayAddress, deploymentName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,36 +87,42 @@ public abstract class AbstractAddOverlayHandler implements OperationStepHandler
|
||||||
addOverlayToServerGroups(context, overlayAddress, operation, overlayName);
|
addOverlayToServerGroups(context, overlayAddress, operation, overlayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is no way to do an overwrite of content from here because it involves
|
|
||||||
// removing the overlay service in the runtime phase. You have to remove
|
|
||||||
// the content in a seperate operation.
|
|
||||||
if (isOverlayExists && isContentExists(context, overlayAddress, overlayPath)) {
|
if (isOverlayExists && isContentExists(context, overlayAddress, overlayPath)) {
|
||||||
throw new OperationFailedException(pathExistsMessage(overlayAddress, overlayPath));
|
if (isOverwrite) {
|
||||||
|
removeContent(context, overlayAddress, overlayPath);
|
||||||
|
} else {
|
||||||
|
throw new OperationFailedException(pathExistsMessage(overlayAddress, overlayPath));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addContent(context, overlayAddress, operation.get(BYTES_TO_UPLOAD.getName()).asBytes(), overlayPath);
|
addContent(context, overlayAddress, operation.get(BYTES_TO_UPLOAD.getName()).asBytes(), overlayPath);
|
||||||
|
|
||||||
context.restartRequired();
|
if (isRedeploy) AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName);
|
||||||
|
if (!isRedeploy) context.restartRequired();
|
||||||
context.completeStep(OperationContext.ResultHandler.NOOP_RESULT_HANDLER);
|
context.completeStep(OperationContext.ResultHandler.NOOP_RESULT_HANDLER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void removeContent(OperationContext context, PathAddress overlayAddress, String overlayPath) {
|
||||||
|
PathAddress contentAddress = overlayAddress.append("content", overlayPath);
|
||||||
|
ModelNode operation = Util.createRemoveOperation(contentAddress);
|
||||||
|
context.addStep(operation, getHandler(context, contentAddress, REMOVE), OperationContext.Stage.MODEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isRedeploy(OperationContext context, ModelNode operation) {
|
||||||
|
return isAuthServerEnabled(context) && getBooleanFromOperation(operation, REDEPLOY_SERVER);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isHostController(OperationContext context) {
|
private boolean isHostController(OperationContext context) {
|
||||||
return context.getProcessType() == ProcessType.HOST_CONTROLLER;
|
return context.getProcessType() == ProcessType.HOST_CONTROLLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String pathExistsMessage(PathAddress overlayAddress, String overlayPath) {
|
private String pathExistsMessage(PathAddress overlayAddress, String overlayPath) {
|
||||||
PathAddress contentAddress = overlayAddress.append("content", overlayPath);
|
PathAddress contentAddress = overlayAddress.append("content", overlayPath);
|
||||||
String msg = "Can not update overlay. ";
|
String msg = "Can not update overlay at " + contentAddress.toCLIStyleString();
|
||||||
msg += "First remove the overlay with CLI using the following command with the content path in double quotes: ";
|
msg += " You may try your request again using the " + OVERWRITE.getName() + " attribute.";
|
||||||
msg += contentAddress.toCLIStyleString() + ":remove";
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isOverlayExists(OperationContext context, String overlayName, PathAddress address) {
|
|
||||||
Resource resource = context.readResourceFromRoot(address);
|
|
||||||
return resource.getChildrenNames("deployment-overlay").contains(overlayName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isContentExists(OperationContext context, PathAddress overlayAddress, String overlayPath) {
|
private boolean isContentExists(OperationContext context, PathAddress overlayAddress, String overlayPath) {
|
||||||
Resource resource = context.readResourceFromRoot(overlayAddress);
|
Resource resource = context.readResourceFromRoot(overlayAddress);
|
||||||
return resource.getChildrenNames("content").contains(overlayPath);
|
return resource.getChildrenNames("content").contains(overlayPath);
|
||||||
|
@ -124,7 +147,7 @@ public abstract class AbstractAddOverlayHandler implements OperationStepHandler
|
||||||
ModelNode serverGroupModel = context.readResourceFromRoot(address).getModel();
|
ModelNode serverGroupModel = context.readResourceFromRoot(address).getModel();
|
||||||
if (serverGroupModel.get("profile").asString().equals(myProfile)) {
|
if (serverGroupModel.get("profile").asString().equals(myProfile)) {
|
||||||
PathAddress serverGroupOverlayAddress = address.append(overlayAddress);
|
PathAddress serverGroupOverlayAddress = address.append(overlayAddress);
|
||||||
boolean isOverlayExists = isOverlayExists(context, overlayName, address);
|
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, address);
|
||||||
if (!isOverlayExists) {
|
if (!isOverlayExists) {
|
||||||
addOverlay(context, serverGroupOverlayAddress);
|
addOverlay(context, serverGroupOverlayAddress);
|
||||||
addDeploymentToOverlay(context, serverGroupOverlayAddress, AuthServerUtil.getDeploymentName(operation));
|
addDeploymentToOverlay(context, serverGroupOverlayAddress, AuthServerUtil.getDeploymentName(operation));
|
||||||
|
@ -160,6 +183,23 @@ public abstract class AbstractAddOverlayHandler implements OperationStepHandler
|
||||||
context.addStep(operation, getHandler(context, address, ADD), OperationContext.Stage.MODEL);
|
context.addStep(operation, getHandler(context, address, ADD), OperationContext.Stage.MODEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isAuthServerEnabled(OperationContext context) {
|
||||||
|
boolean defaultValue = AuthServerDefinition.ENABLED.getDefaultValue().asBoolean();
|
||||||
|
ModelNode authServerModel = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().clone();
|
||||||
|
String attrName = AuthServerDefinition.ENABLED.getName();
|
||||||
|
if (!authServerModel.get(attrName).isDefined()) return defaultValue;
|
||||||
|
return authServerModel.get(attrName).asBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean getBooleanFromOperation(ModelNode operation, SimpleAttributeDefinition definition) {
|
||||||
|
boolean defaultValue = definition.getDefaultValue().asBoolean();
|
||||||
|
if (!operation.get(definition.getName()).isDefined()) {
|
||||||
|
return defaultValue;
|
||||||
|
} else {
|
||||||
|
return operation.get(definition.getName()).asBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// used for debugging
|
// used for debugging
|
||||||
private ModelNode scrub(ModelNode op) {
|
private ModelNode scrub(ModelNode op) {
|
||||||
ModelNode scrubbed = op.clone();
|
ModelNode scrubbed = op.clone();
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.keycloak.subsystem.extension.authserver;
|
package org.keycloak.subsystem.extension.authserver;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import org.jboss.as.controller.OperationDefinition;
|
import org.jboss.as.controller.OperationDefinition;
|
||||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||||
|
@ -46,8 +45,12 @@ public class AddProviderHandler extends AbstractAddOverlayHandler {
|
||||||
public static OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OP, AuthServerDefinition.rscDescriptionResolver)
|
public static OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OP, AuthServerDefinition.rscDescriptionResolver)
|
||||||
.addParameter(BYTES_TO_UPLOAD)
|
.addParameter(BYTES_TO_UPLOAD)
|
||||||
.addParameter(UPLOADED_FILE_NAME)
|
.addParameter(UPLOADED_FILE_NAME)
|
||||||
|
.addParameter(REDEPLOY_SERVER)
|
||||||
|
.addParameter(OVERWRITE)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
private AddProviderHandler() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getOverlayPath(String fileName) {
|
String getOverlayPath(String fileName) {
|
||||||
if (!fileName.toLowerCase().endsWith(".jar")) {
|
if (!fileName.toLowerCase().endsWith(".jar")) {
|
||||||
|
|
|
@ -95,6 +95,8 @@ public class AuthServerDefinition extends SimpleResourceDefinition {
|
||||||
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
|
resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
|
||||||
resourceRegistration.registerOperationHandler(AddProviderHandler.DEFINITION, AddProviderHandler.INSTANCE);
|
resourceRegistration.registerOperationHandler(AddProviderHandler.DEFINITION, AddProviderHandler.INSTANCE);
|
||||||
resourceRegistration.registerOperationHandler(OverlayKeycloakServerJsonHandler.DEFINITION, OverlayKeycloakServerJsonHandler.INSTANCE);
|
resourceRegistration.registerOperationHandler(OverlayKeycloakServerJsonHandler.DEFINITION, OverlayKeycloakServerJsonHandler.INSTANCE);
|
||||||
|
resourceRegistration.registerOperationHandler(ListOverlaysHandler.DEFINITION, ListOverlaysHandler.INSTANCE);
|
||||||
|
resourceRegistration.registerOperationHandler(RemoveOverlayHandler.DEFINITION, RemoveOverlayHandler.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -31,6 +31,7 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ARC
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOY;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOY;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT_OVERLAY;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ENABLED;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ENABLED;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PERSISTENT;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PERSISTENT;
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
|
||||||
|
@ -40,6 +41,7 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.UND
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.URL;
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.URL;
|
||||||
import org.jboss.as.controller.operations.common.Util;
|
import org.jboss.as.controller.operations.common.Util;
|
||||||
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
|
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
|
||||||
|
import org.jboss.as.controller.registry.Resource;
|
||||||
import org.jboss.dmr.ModelNode;
|
import org.jboss.dmr.ModelNode;
|
||||||
import org.jboss.modules.Module;
|
import org.jboss.modules.Module;
|
||||||
import org.jboss.modules.ModuleIdentifier;
|
import org.jboss.modules.ModuleIdentifier;
|
||||||
|
@ -108,7 +110,7 @@ public class AuthServerUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
void addStepToUploadAuthServer(OperationContext context, boolean isEnabled) throws OperationFailedException {
|
void addStepToUploadAuthServer(OperationContext context, boolean isEnabled) throws OperationFailedException {
|
||||||
PathAddress deploymentAddress = deploymentAddress();
|
PathAddress deploymentAddress = deploymentAddress(deploymentName);
|
||||||
ModelNode op = Util.createOperation(ADD, deploymentAddress);
|
ModelNode op = Util.createOperation(ADD, deploymentAddress);
|
||||||
op.get(ENABLED).set(isEnabled);
|
op.get(ENABLED).set(isEnabled);
|
||||||
op.get(PERSISTENT).set(false); // prevents writing this deployment out to standalone.xml
|
op.get(PERSISTENT).set(false); // prevents writing this deployment out to standalone.xml
|
||||||
|
@ -137,26 +139,27 @@ public class AuthServerUtil {
|
||||||
return contentItem;
|
return contentItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addStepToRedeployAuthServer(OperationContext context) {
|
static void addStepToRedeployAuthServer(OperationContext context, String deploymentName) {
|
||||||
addDeploymentAction(context, REDEPLOY);
|
addDeploymentAction(context, REDEPLOY, deploymentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addStepToUndeployAuthServer(OperationContext context) {
|
static void addStepToUndeployAuthServer(OperationContext context, String deploymentName) {
|
||||||
addDeploymentAction(context, UNDEPLOY);
|
addDeploymentAction(context, UNDEPLOY, deploymentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addStepToDeployAuthServer(OperationContext context) {
|
static void addStepToDeployAuthServer(OperationContext context, String deploymentName) {
|
||||||
addDeploymentAction(context, DEPLOY);
|
addDeploymentAction(context, DEPLOY, deploymentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDeploymentAction(OperationContext context, String operation) {
|
private static void addDeploymentAction(OperationContext context, String operation, String deploymentName) {
|
||||||
PathAddress deploymentAddress = deploymentAddress();
|
if (!context.isNormalServer()) return;
|
||||||
|
PathAddress deploymentAddress = deploymentAddress(deploymentName);
|
||||||
ModelNode op = Util.createOperation(operation, deploymentAddress);
|
ModelNode op = Util.createOperation(operation, deploymentAddress);
|
||||||
op.get(RUNTIME_NAME).set(deploymentName);
|
op.get(RUNTIME_NAME).set(deploymentName);
|
||||||
context.addStep(op, getHandler(context, deploymentAddress, operation), OperationContext.Stage.MODEL);
|
context.addStep(op, getHandler(context, deploymentAddress, operation), OperationContext.Stage.MODEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PathAddress deploymentAddress() {
|
private static PathAddress deploymentAddress(String deploymentName) {
|
||||||
return PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT, deploymentName));
|
return PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT, deploymentName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,4 +186,17 @@ public class AuthServerUtil {
|
||||||
return PathAddress.pathAddress(operation.get(ADDRESS));
|
return PathAddress.pathAddress(operation.get(ADDRESS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PathAddress getOverlayAddress(String overlayName) {
|
||||||
|
return PathAddress.pathAddress(PathElement.pathElement(DEPLOYMENT_OVERLAY, overlayName));
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getOverlayName(ModelNode operation) {
|
||||||
|
return AuthServerUtil.getAuthServerName(operation) + "-keycloak-overlay";
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isOverlayExists(OperationContext context, String overlayName, PathAddress address) {
|
||||||
|
Resource resource = context.readResourceFromRoot(address);
|
||||||
|
return resource.getChildrenNames(DEPLOYMENT_OVERLAY).contains(overlayName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,23 +50,23 @@ public class AuthServerWriteAttributeHandler extends ModelOnlyWriteAttributeHand
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthServerUtil authServerUtil = new AuthServerUtil(operation);
|
|
||||||
boolean isEnabled = isEnabled(model); // is server currently enabled?
|
boolean isEnabled = isEnabled(model); // is server currently enabled?
|
||||||
|
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
||||||
|
|
||||||
if (attributeName.equals(AuthServerDefinition.WEB_CONTEXT.getName())) {
|
if (attributeName.equals(AuthServerDefinition.WEB_CONTEXT.getName())) {
|
||||||
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
|
||||||
KeycloakAdapterConfigService.INSTANCE.removeServerDeployment(deploymentName);
|
KeycloakAdapterConfigService.INSTANCE.removeServerDeployment(deploymentName);
|
||||||
KeycloakAdapterConfigService.INSTANCE.addServerDeployment(deploymentName, newValue.asString());
|
KeycloakAdapterConfigService.INSTANCE.addServerDeployment(deploymentName, newValue.asString());
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
authServerUtil.addStepToRedeployAuthServer(context);
|
AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributeName.equals(AuthServerDefinition.ENABLED.getName())) {
|
if (attributeName.equals(AuthServerDefinition.ENABLED.getName())) {
|
||||||
if (!isEnabled) { // we are disabling
|
if (!isEnabled) { // we are disabling
|
||||||
authServerUtil.addStepToUndeployAuthServer(context);
|
AuthServerUtil.addStepToUndeployAuthServer(context, deploymentName);
|
||||||
} else { // we are enabling
|
} else { // we are enabling
|
||||||
authServerUtil.addStepToDeployAuthServer(context);
|
AuthServerUtil.addStepToDeployAuthServer(context, deploymentName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.subsystem.extension.authserver;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import org.jboss.as.controller.OperationContext;
|
||||||
|
import org.jboss.as.controller.OperationDefinition;
|
||||||
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
|
import org.jboss.as.controller.OperationStepHandler;
|
||||||
|
import org.jboss.as.controller.PathAddress;
|
||||||
|
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
|
||||||
|
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT_OVERLAY;
|
||||||
|
import org.jboss.as.controller.registry.Resource;
|
||||||
|
import org.jboss.dmr.ModelNode;
|
||||||
|
import org.jboss.dmr.ModelType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation to list all of the provider jars, theme jars, and keycloak-server.json that
|
||||||
|
* have been uploaded to the auth server.
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class ListOverlaysHandler implements OperationStepHandler {
|
||||||
|
static final String LIST_OVERLAYS_OPERATION = "list-overlays";
|
||||||
|
|
||||||
|
static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(LIST_OVERLAYS_OPERATION, AuthServerDefinition.rscDescriptionResolver)
|
||||||
|
.setReadOnly()
|
||||||
|
.setRuntimeOnly()
|
||||||
|
.setReplyType(ModelType.LIST)
|
||||||
|
.setReplyValueType(ModelType.STRING)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
static final OperationStepHandler INSTANCE = new ListOverlaysHandler();
|
||||||
|
|
||||||
|
private ListOverlaysHandler() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
|
||||||
|
final ModelNode result = context.getResult();
|
||||||
|
result.setEmptyList();
|
||||||
|
|
||||||
|
String overlayName = AuthServerUtil.getOverlayName(operation);
|
||||||
|
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
|
||||||
|
if (isOverlayExists) {
|
||||||
|
Set<String> overlays = new TreeSet<String>(getOverlayNames(context, overlayName));
|
||||||
|
for (final String key : overlays) {
|
||||||
|
result.add(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.stepCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getOverlayNames(OperationContext context, String overlayName) {
|
||||||
|
PathAddress overlayAddr = PathAddress.pathAddress(DEPLOYMENT_OVERLAY, overlayName);
|
||||||
|
Resource resource = context.readResourceFromRoot(overlayAddr);
|
||||||
|
return resource.getChildrenNames(CONTENT);
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,8 +33,12 @@ public class OverlayKeycloakServerJsonHandler extends AbstractAddOverlayHandler
|
||||||
|
|
||||||
public static OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OP, AuthServerDefinition.rscDescriptionResolver)
|
public static OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OP, AuthServerDefinition.rscDescriptionResolver)
|
||||||
.addParameter(BYTES_TO_UPLOAD)
|
.addParameter(BYTES_TO_UPLOAD)
|
||||||
|
.addParameter(REDEPLOY_SERVER)
|
||||||
|
.addParameter(OVERWRITE)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
private OverlayKeycloakServerJsonHandler() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getOverlayPath(String fileName) {
|
String getOverlayPath(String fileName) {
|
||||||
return "/WEB-INF/classes/META-INF/keycloak-server.json";
|
return "/WEB-INF/classes/META-INF/keycloak-server.json";
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.subsystem.extension.authserver;
|
||||||
|
|
||||||
|
import org.jboss.as.controller.OperationContext;
|
||||||
|
import org.jboss.as.controller.OperationDefinition;
|
||||||
|
import org.jboss.as.controller.OperationFailedException;
|
||||||
|
import org.jboss.as.controller.OperationStepHandler;
|
||||||
|
import org.jboss.as.controller.PathAddress;
|
||||||
|
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||||
|
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||||
|
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
|
||||||
|
import org.jboss.dmr.ModelNode;
|
||||||
|
import org.jboss.dmr.ModelType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation to remove a provider jars, theme jars, or keycloak-server.json that
|
||||||
|
* has been uploaded to the auth server.
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class RemoveOverlayHandler implements OperationStepHandler {
|
||||||
|
static final String REMOVE_OVERLAY_OPERATION = "remove-overlay";
|
||||||
|
|
||||||
|
protected static final SimpleAttributeDefinition OVERLAY_FILE_PATH =
|
||||||
|
new SimpleAttributeDefinitionBuilder("overlay-file-path", ModelType.STRING, false)
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setAllowNull(false)
|
||||||
|
.setDefaultValue(new ModelNode().set("/WEB-INF/lib/myprovider.jar"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(REMOVE_OVERLAY_OPERATION, AuthServerDefinition.rscDescriptionResolver)
|
||||||
|
.addParameter(OVERLAY_FILE_PATH)
|
||||||
|
.addParameter(AbstractAddOverlayHandler.REDEPLOY_SERVER)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
static final OperationStepHandler INSTANCE = new RemoveOverlayHandler();
|
||||||
|
|
||||||
|
private RemoveOverlayHandler() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
|
||||||
|
String overlayName = AuthServerUtil.getOverlayName(operation);
|
||||||
|
boolean isOverlayExists = AuthServerUtil.isOverlayExists(context, overlayName, PathAddress.EMPTY_ADDRESS);
|
||||||
|
String overlayPath = operation.get(OVERLAY_FILE_PATH.getName()).asString();
|
||||||
|
if (isOverlayExists) {
|
||||||
|
PathAddress overlayAddress = AuthServerUtil.getOverlayAddress(overlayName);
|
||||||
|
AbstractAddOverlayHandler.removeContent(context, overlayAddress, overlayPath);
|
||||||
|
} else {
|
||||||
|
context.setRollbackOnly();
|
||||||
|
throw new OperationFailedException("Overlay path " + overlayPath + " not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isRedeploy = AbstractAddOverlayHandler.isRedeploy(context, operation);
|
||||||
|
String deploymentName = AuthServerUtil.getDeploymentName(operation);
|
||||||
|
if (isRedeploy) AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName);
|
||||||
|
if (!isRedeploy) context.restartRequired();
|
||||||
|
|
||||||
|
context.stepCompleted();
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,9 +12,16 @@ keycloak.auth-server.remove=Remove an Auth Server from the subsystem.
|
||||||
keycloak.auth-server.add-provider=Add a provider service jar to the Keycloak auth server.
|
keycloak.auth-server.add-provider=Add a provider service jar to the Keycloak auth server.
|
||||||
keycloak.auth-server.add-provider.uploaded-file-name=The file name of the provider service jar to be added or updated.
|
keycloak.auth-server.add-provider.uploaded-file-name=The file name of the provider service jar to be added or updated.
|
||||||
keycloak.auth-server.add-provider.bytes-to-upload=The bytes of the provider service jar to be added or updated.
|
keycloak.auth-server.add-provider.bytes-to-upload=The bytes of the provider service jar to be added or updated.
|
||||||
|
keycloak.auth-server.add-provider.redeploy=Redeploy the auth server after adding the provider. Ignored if auth server is disabled.
|
||||||
|
keycloak.auth-server.add-provider.overwrite=Overwrite even if the uploaded-file-name already exists as an overlay.
|
||||||
|
keycloak.auth-server.list-overlays=List the overlays uploaded for this auth server.
|
||||||
|
keycloak.auth-server.remove-overlay=Remove a provider jar, theme jar, or keycloak-server.json that has been uploaded to the auth server.
|
||||||
|
keycloak.auth-server.remove-overlay.overlay-file-path=The uploaded path and file name of the overlay to be removed.
|
||||||
|
keycloak.auth-server.remove-overlay.redeploy=Redeploy the auth server after removing the overlay.
|
||||||
keycloak.auth-server.update-server-config=Upload a new keycloak-server.json configuration file for the Keycloak auth server.
|
keycloak.auth-server.update-server-config=Upload a new keycloak-server.json configuration file for the Keycloak auth server.
|
||||||
keycloak.auth-server.update-server-config.uploaded-file-name=Should be the name keycloak-server.json.
|
|
||||||
keycloak.auth-server.update-server-config.bytes-to-upload=The bytes of the keycloak-server.json file to be added or updated.
|
keycloak.auth-server.update-server-config.bytes-to-upload=The bytes of the keycloak-server.json file to be added or updated.
|
||||||
|
keycloak.auth-server.update-server-config.redeploy=Redeploy the auth server after updating the server config.
|
||||||
|
keycloak.auth-server.update-server-config.overwrite=Overwrite even if keycloak-server.json already exitss as an overlay.
|
||||||
keycloak.auth-server.enabled=Enable or disable the Auth Server.
|
keycloak.auth-server.enabled=Enable or disable the Auth Server.
|
||||||
keycloak.auth-server.web-context=Web context the auth-server will use. Also, the module name of the auth-server deployment.
|
keycloak.auth-server.web-context=Web context the auth-server will use. Also, the module name of the auth-server deployment.
|
||||||
|
|
||||||
|
|
7
pom.xml
|
@ -36,7 +36,7 @@
|
||||||
<slf4j.version>1.5.10</slf4j.version>
|
<slf4j.version>1.5.10</slf4j.version>
|
||||||
<jboss.version>7.1.1.Final</jboss.version>
|
<jboss.version>7.1.1.Final</jboss.version>
|
||||||
<wildfly.version>8.1.0.Final</wildfly.version>
|
<wildfly.version>8.1.0.Final</wildfly.version>
|
||||||
<wildfly.core.version>1.0.0.Alpha9</wildfly.core.version>
|
<wildfly.core.version>1.0.0.Alpha12</wildfly.core.version>
|
||||||
<servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
|
<servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
|
||||||
<google.zxing.version>2.2</google.zxing.version>
|
<google.zxing.version>2.2</google.zxing.version>
|
||||||
<google.client.version>1.14.1-beta</google.client.version>
|
<google.client.version>1.14.1-beta</google.client.version>
|
||||||
|
@ -470,6 +470,11 @@
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<version>${wildfly.core.version}</version>
|
<version>${wildfly.core.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wildfly.core</groupId>
|
||||||
|
<artifactId>wildfly-cli</artifactId>
|
||||||
|
<version>${wildfly.core.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.wildfly.core</groupId>
|
<groupId>org.wildfly.core</groupId>
|
||||||
<artifactId>wildfly-core-feature-pack</artifactId>
|
<artifactId>wildfly-core-feature-pack</artifactId>
|
||||||
|
|