/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat Middleware LLC, 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. */ package org.jboss.as.test.integration.domain.mixed; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.BLOCKING; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CHILD_TYPE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CLONE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.COMPOSITE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CORE_SERVICE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.EXTENSION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HOST; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.IGNORED_RESOURCES; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.IGNORED_RESOURCE_TYPE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INCLUDE_ALIASES; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INCLUDE_RUNTIME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INTERFACE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MANAGEMENT_CLIENT_CONTENT; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAMES; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PROFILE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PROXIES; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_CHILDREN_NAMES_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RECURSIVE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESTART; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESTART_SERVERS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNNING_SERVER; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_CONFIG; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_GROUP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SOCKET_BINDING_GROUP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.STEPS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SYSTEM_PROPERTY; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.TO_PROFILE; import static org.jboss.as.test.integration.domain.management.util.DomainTestSupport.validateResponse; import static org.junit.Assert.assertEquals; import java.net.URL; import java.net.URLConnection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.jboss.as.clustering.jgroups.subsystem.JGroupsSubsystemResourceDefinition; import org.jboss.as.clustering.jgroups.subsystem.ProtocolResourceDefinition; import org.jboss.as.clustering.jgroups.subsystem.StackResourceDefinition; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.client.helpers.domain.DomainClient; import org.jboss.as.controller.descriptions.ModelDescriptionConstants; import org.jboss.as.controller.operations.common.Util; import org.jboss.as.controller.operations.global.MapOperations; import org.jboss.as.model.test.ModelTestUtils; import org.jboss.as.security.Constants; import org.jboss.as.security.SecurityExtension; import org.jboss.as.test.integration.domain.management.util.DomainLifecycleUtil; import org.jboss.as.test.integration.domain.management.util.DomainTestSupport; import org.jboss.as.test.integration.domain.management.util.DomainTestUtils; import org.jboss.as.test.shared.TestSuiteEnvironment; import org.jboss.dmr.ModelNode; import org.jboss.dmr.Property; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; import org.xnio.IoUtils; /** * * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public abstract class SimpleMixedDomainTest { private static final String ACTIVE_PROFILE = "full-ha"; MixedDomainTestSupport support; Version.AsVersion version; @Before public void init() throws Exception { support = MixedDomainTestSuite.getSupport(this.getClass()); version = MixedDomainTestSuite.getVersion(this.getClass()); } @AfterClass public static synchronized void afterClass() { MixedDomainTestSuite.afterClass(); } @Test public void test00001_ServerRunning() throws Exception { URLConnection connection = new URL("http://" + TestSuiteEnvironment.formatPossibleIpv6Address(DomainTestSupport.slaveAddress) + ":8080").openConnection(); connection.connect(); } @Test public void test00002_Versioning() throws Exception { if (version == Version.AsVersion.EAP_6_2_0 || version == Version.AsVersion.EAP_7_0_0) { //6.2.0 (https://issues.jboss.org/browse/WFLY-3228) and //7.0.0 (https://issues.jboss.org/browse/WFCORE-401) // have the slave report back its own version, rather than the one from the DC, //which is what should happen return; } DomainClient masterClient = support.getDomainMasterLifecycleUtil().createDomainClient(); ModelNode masterModel; try { masterModel = readDomainModelForVersions(masterClient); } finally { IoUtils.safeClose(masterClient); } DomainClient slaveClient = support.getDomainSlaveLifecycleUtil().createDomainClient(); ModelNode slaveModel; try { slaveModel = readDomainModelForVersions(slaveClient); } finally { IoUtils.safeClose(slaveClient); } cleanupKnownDifferencesInModelsForVersioningCheck(masterModel, slaveModel); //The version fields should be the same assertEquals(masterModel, slaveModel); } @Test public void test00009_SecurityTransformers() throws Exception { final DomainClient masterClient = support.getDomainMasterLifecycleUtil().createDomainClient(); final DomainClient slaveClient = support.getDomainSlaveLifecycleUtil().createDomainClient(); try { PathAddress subsystem = PathAddress.pathAddress(PathElement.pathElement(PROFILE, ACTIVE_PROFILE), PathElement.pathElement(SUBSYSTEM, SecurityExtension.SUBSYSTEM_NAME)); PathAddress webPolicy = subsystem.append(Constants.SECURITY_DOMAIN, "jboss-web-policy").append(Constants.AUTHORIZATION, Constants.CLASSIC); ModelNode options = new ModelNode(); options.add("a", "b"); ModelNode op = Util.getWriteAttributeOperation(webPolicy.append(Constants.POLICY_MODULE, "Delegating"), Constants.MODULE_OPTIONS, options); DomainTestUtils.executeForResult(op, masterClient); //TODO check the resources //System.out.println(DomainTestUtils.executeForResult(Util.createOperation(READ_RESOURCE_OPERATION, address), modelControllerClient)); PathAddress jaspi = subsystem.append(Constants.SECURITY_DOMAIN, "jaspi-test").append(Constants.AUTHENTICATION, Constants.JASPI); PathAddress jaspiLoginStack = jaspi.append(Constants.LOGIN_MODULE_STACK, "lm-stack"); op = Util.createAddOperation(jaspiLoginStack.append(Constants.LOGIN_MODULE, "test2")); op.get(Constants.CODE).set("UserRoles"); op.get(Constants.FLAG).set("required"); op.get(Constants.MODULE).set("test-jaspi"); DomainTestUtils.executeForResult(op, masterClient); op = Util.createAddOperation(jaspi.append(Constants.AUTH_MODULE, "Delegating")); op.get(Constants.CODE).set("Delegating"); op.get(Constants.LOGIN_MODULE_STACK_REF).set("lm-stack"); op.get(Constants.FLAG).set("optional"); DomainTestUtils.executeForResult(op, masterClient); op = new ModelNode(); op.get(OP).set(READ_RESOURCE_OPERATION); op.get(OP_ADDR).set(jaspi.toModelNode()); op.get(INCLUDE_ALIASES).set(false); op.get(RECURSIVE).set(true); ModelNode masterResource = DomainTestUtils.executeForResult(op, masterClient); ModelNode slaveResource = DomainTestUtils.executeForResult(op, slaveClient); ModelTestUtils.compare(masterResource, slaveResource, true); } finally { try { //The server will be in restart-required mode, so restart it to get rid of the changes PathAddress serverAddress = PathAddress.pathAddress(HOST, "slave").append(SERVER_CONFIG, "server-one"); ModelNode op = Util.createOperation(RESTART, PathAddress.pathAddress(serverAddress)); op.get(BLOCKING).set(true); Assert.assertEquals("STARTED", validateResponse(slaveClient.execute(op), true).asString()); } finally { IoUtils.safeClose(slaveClient); IoUtils.safeClose(masterClient); } } } @Test public void test00010_JgroupsTransformers() throws Exception { final DomainClient masterClient = support.getDomainMasterLifecycleUtil().createDomainClient(); try { // Check composite operation final ModelNode compositeOp = new ModelNode(); compositeOp.get(OP).set(COMPOSITE); compositeOp.get(OP_ADDR).setEmptyList(); compositeOp.get(STEPS).add(createProtocolPutPropertyOperation("tcp", "MPING", "send_on_all_interfaces", "true")); compositeOp.get(STEPS).add(createProtocolPutPropertyOperation("tcp", "MPING", "receive_on_all_interfaces", "true")); DomainTestUtils.executeForResult(compositeOp, masterClient); } finally { IoUtils.safeClose(masterClient); } } /** * Tests test-connection-in-pool() of ExampleDS. * * @throws Exception */ @Test public void test00011_ExampleDSConnection() throws Exception{ if (version == Version.AsVersion.EAP_6_2_0) { // see: https://issues.jboss.org/browse/WFLY-7792 return; } PathAddress exampleDSAddress = PathAddress.pathAddress(PathElement.pathElement(HOST, "slave"), PathElement.pathElement(RUNNING_SERVER, "server-one"), PathElement.pathElement(SUBSYSTEM, "datasources"), PathElement.pathElement("data-source", "ExampleDS")); DomainClient masterClient = support.getDomainMasterLifecycleUtil().createDomainClient(); try { ModelNode op = Util.createOperation("test-connection-in-pool", PathAddress.pathAddress(exampleDSAddress)); ModelNode response = masterClient.execute(op); assertEquals(op.toString() + '\n' + response.toString(), SUCCESS, response.get(OUTCOME).asString()); } finally { IoUtils.safeClose(masterClient); } } //Do this one last since it changes the host model of the slaves @Test public void test99999_ProfileClone() throws Exception { if (version.getMajor() == 6) { //EAP 6 does not have the clone operation profileCloneEap6x(); } else { //EAP 7 does not have the clone operation profileCloneEap7x(); } } private void profileCloneEap6x() throws Exception { //EAP 6 does not have the clone operation //For an EAP 7 slave we will need another test since EAP 7 allows the clone operation. // However EAP 7 will need to take into account the ignore-unused-configuration // setting which does not exist in 6.x final DomainClient masterClient = support.getDomainMasterLifecycleUtil().createDomainClient(); final DomainClient slaveClient = support.getDomainSlaveLifecycleUtil().createDomainClient(); try { final PathAddress newProfileAddress = PathAddress.pathAddress(PROFILE, "new-profile"); //Create a new profile (so that we can ignore it on the host later) DomainTestUtils.executeForResult(Util.createAddOperation(newProfileAddress), masterClient); //Attempt to clone it. It should fail since the transformers reject it. final ModelNode clone = Util.createEmptyOperation(CLONE, newProfileAddress); clone.get(TO_PROFILE).set("cloned"); DomainTestUtils.executeForFailure(clone, masterClient); //Ignore the new profile on the slave and reload final PathAddress ignoredResourceAddress = PathAddress.pathAddress(HOST, "slave") .append(CORE_SERVICE, IGNORED_RESOURCES).append(IGNORED_RESOURCE_TYPE, PROFILE); final ModelNode ignoreNewProfile = Util.createAddOperation(ignoredResourceAddress); ignoreNewProfile.get(NAMES).add("new-profile"); DomainTestUtils.executeForResult(ignoreNewProfile, slaveClient); //Reload slave so ignore takes effect reloadHost(support.getDomainSlaveLifecycleUtil(), "slave"); //Clone should work now that the new profile is ignored DomainTestUtils.executeForResult(clone, masterClient); //Adding a subsystem to the cloned profile should fail since the profile does not exist on the slave DomainTestUtils.executeForFailure(Util.createAddOperation(PathAddress.pathAddress(PROFILE, "cloned").append(SUBSYSTEM, "jmx")), masterClient); //Reload slave reloadHost(support.getDomainSlaveLifecycleUtil(), "slave"); //Reloading should have brought over the cloned profile, so adding a subsystem should now work DomainTestUtils.executeForResult(Util.createAddOperation(PathAddress.pathAddress(PROFILE, "cloned").append(SUBSYSTEM, "jmx")), masterClient); } finally { IoUtils.safeClose(slaveClient); IoUtils.safeClose(masterClient); } } private void profileCloneEap7x() throws Exception { // EAP 7 allows the clone operation. // However EAP 7 will need to take into account the ignore-unused-configuration // setting which does not exist in 6.x final DomainClient masterClient = support.getDomainMasterLifecycleUtil().createDomainClient(); final DomainClient slaveClient = support.getDomainSlaveLifecycleUtil().createDomainClient(); try { final PathAddress newProfileAddress = PathAddress.pathAddress(PROFILE, "new-profile"); //Create a new profile (so that we can ignore it on the host later) DomainTestUtils.executeForResult(Util.createAddOperation(newProfileAddress), masterClient); //Attempt to clone it. It should work but not exist on the slave since unused configuration is ignored final ModelNode clone = Util.createEmptyOperation(CLONE, newProfileAddress); clone.get(TO_PROFILE).set("cloned"); DomainTestUtils.executeForResult(clone, masterClient); //Check the new profile does not exist on the slave final ModelNode readChildrenNames = Util.createEmptyOperation(READ_CHILDREN_NAMES_OPERATION, PathAddress.EMPTY_ADDRESS); readChildrenNames.get(CHILD_TYPE).set(PROFILE); ModelNode result = DomainTestUtils.executeForResult(readChildrenNames, slaveClient); List<ModelNode> list = result.asList(); Assert.assertEquals(1, list.size()); Assert.assertEquals(list.toString(), "full-ha", list.get(0).asString()); //Update the server group to use the new profile DomainTestUtils.executeForResult( Util.getWriteAttributeOperation(PathAddress.pathAddress(SERVER_GROUP, "other-server-group"), PROFILE, "new-profile"), masterClient); //Check the profiles result = DomainTestUtils.executeForResult(readChildrenNames, slaveClient); list = result.asList(); Assert.assertEquals(1, list.size()); Assert.assertEquals(list.toString(), "new-profile", list.get(0).asString()); } finally { IoUtils.safeClose(slaveClient); IoUtils.safeClose(masterClient); } } /* !!!!!!!!! ADD TESTS IN NUMERICAL ORDER !!!!!!!!!! Please observe the test<5 digits>_ pattern for the names to ensure the order */ private DomainClient reloadHost(DomainLifecycleUtil lifecycleUtil, String host) throws Exception { ModelNode reload = Util.createEmptyOperation("reload", PathAddress.pathAddress(HOST, host)); reload.get(RESTART_SERVERS).set(false); lifecycleUtil.executeAwaitConnectionClosed(reload); lifecycleUtil.connect(); lifecycleUtil.awaitHostController(System.currentTimeMillis()); return lifecycleUtil.createDomainClient(); } private static ModelNode createProtocolPutPropertyOperation(String stackName, String protocolName, String propertyName, String propertyValue) { PathAddress address = PathAddress.pathAddress(PathElement.pathElement(PROFILE, ACTIVE_PROFILE)) .append(JGroupsSubsystemResourceDefinition.PATH) .append(StackResourceDefinition.pathElement(stackName)) .append(ProtocolResourceDefinition.pathElement(protocolName)); ModelNode operation = Util.createOperation(MapOperations.MAP_PUT_DEFINITION, address); operation.get(ModelDescriptionConstants.NAME).set("properties"); operation.get("key").set(propertyName); operation.get(ModelDescriptionConstants.VALUE).set(propertyValue); return operation; } private Set<ModelNode> getAllChildren(ModelNode modules) { HashSet<ModelNode> set = new HashSet<ModelNode>(); for (Property prop : modules.asPropertyList()) { set.add(prop.getValue()); } return set; } private void cleanupKnownDifferencesInModelsForVersioningCheck(ModelNode masterModel, ModelNode slaveModel) { //First get rid of any undefined crap cleanUndefinedNodes(masterModel); cleanUndefinedNodes(slaveModel); } private void cleanUndefinedNodes(ModelNode model) { Set<String> removals = new HashSet<String>(); for (String key : model.keys()) { if (!model.hasDefined(key)) { removals.add(key); } } for (String key : removals) { model.remove(key); } } private ModelNode readDomainModelForVersions(DomainClient domainClient) throws Exception { ModelNode op = new ModelNode(); op.get(OP).set(READ_RESOURCE_OPERATION); op.get(OP_ADDR).setEmptyList(); op.get(RECURSIVE).set(true); op.get(INCLUDE_RUNTIME).set(false); op.get(PROXIES).set(false); ModelNode model = DomainTestUtils.executeForResult(op, domainClient); model.remove(EXTENSION); model.remove(HOST); model.remove(INTERFACE); model.remove(MANAGEMENT_CLIENT_CONTENT); model.remove(PROFILE); model.remove(SERVER_GROUP); model.remove(SOCKET_BINDING_GROUP); model.remove(SYSTEM_PROPERTY); model.remove(CORE_SERVICE); return model; } }