/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You 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.apache.geode.internal.cache.extension.mock; import org.apache.geode.cache.Cache; import org.apache.geode.cache.CacheFactory; import org.apache.geode.cache.Region; import org.apache.geode.cache.execute.Function; import org.apache.geode.cache.execute.ResultCollector; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.management.cli.Result; import org.apache.geode.management.cli.Result.Status; import org.apache.geode.management.internal.cli.CliUtil; import org.apache.geode.management.internal.cli.commands.AbstractCommandsSupport; import org.apache.geode.management.internal.cli.functions.CliFunctionResult; import org.apache.geode.management.internal.cli.result.ResultBuilder; import org.apache.geode.management.internal.cli.result.TabularResultData; import org.apache.geode.management.internal.configuration.domain.XmlEntity; import org.apache.geode.management.internal.security.ResourceOperation; import org.apache.geode.security.ResourcePermission.Operation; import org.apache.geode.security.ResourcePermission.Resource; import org.springframework.shell.core.annotation.CliCommand; import org.springframework.shell.core.annotation.CliOption; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; /** * Mock Extension gfsh commands. * * * @since GemFire 8.1 */ public class MockExtensionCommands extends AbstractCommandsSupport { public static final String OPTION_VALUE = "value"; public static final String OPTION_REGION_NAME = "region-name"; public static final String CREATE_MOCK_REGION_EXTENSION = "create mock region extension"; public static final String ALTER_MOCK_REGION_EXTENSION = "alter mock region extension"; public static final String DESTROY_MOCK_REGION_EXTENSION = "destroy mock region extension"; public static final String CREATE_MOCK_CACHE_EXTENSION = "create mock cache extension"; public static final String ALTER_MOCK_CACHE_EXTENSION = "alter mock cache extension"; public static final String DESTROY_MOCK_CACHE_EXTENSION = "destroy mock cache extension"; /** * Creates a {@link MockRegionExtension} on the given <code>regionName</code>. * * @param regionName {@link Region} name on which to create {@link MockRegionExtension} . * @param value {@link String} value to set on {@link MockRegionExtension#setValue(String)}. * @return {@link Result} * @since GemFire 8.1 */ @CliCommand(value = CREATE_MOCK_REGION_EXTENSION) @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) public Result createMockRegionExtension( @CliOption(key = OPTION_REGION_NAME, mandatory = true) final String regionName, @CliOption(key = OPTION_VALUE, mandatory = true) final String value) { return executeFunctionOnAllMembersTabulateResultPersist( CreateMockRegionExtensionFunction.INSTANCE, true, CreateMockRegionExtensionFunction.toArgs(regionName, value)); } /** * Alters a {@link MockRegionExtension} on the given <code>regionName</code>. * * @param regionName {@link Region} name on which to create {@link MockRegionExtension} . * @param value {@link String} value to set on {@link MockRegionExtension#setValue(String)}. * @return {@link Result} * @since GemFire 8.1 */ @CliCommand(value = ALTER_MOCK_REGION_EXTENSION) @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) public Result alterMockRegionExtension( @CliOption(key = OPTION_REGION_NAME, mandatory = true) final String regionName, @CliOption(key = OPTION_VALUE, mandatory = true) final String value) { return executeFunctionOnAllMembersTabulateResultPersist( AlterMockRegionExtensionFunction.INSTANCE, true, AlterMockRegionExtensionFunction.toArgs(regionName, value)); } /** * Destroy the {@link MockRegionExtension} on the given <code>regionName</code>. * * @param regionName {@link Region} name on which to create {@link MockRegionExtension} . * @return {@link Result} * @since GemFire 8.1 */ @CliCommand(value = DESTROY_MOCK_REGION_EXTENSION) @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) public Result destroyMockRegionExtension( @CliOption(key = OPTION_REGION_NAME, mandatory = true) final String regionName) { return executeFunctionOnAllMembersTabulateResultPersist( DestroyMockRegionExtensionFunction.INSTANCE, true, DestroyMockRegionExtensionFunction.toArgs(regionName)); } /** * Creates a {@link MockCacheExtension}. * * @param value {@link String} value to set on {@link MockCacheExtension#setValue(String)}. * @return {@link Result} * @since GemFire 8.1 */ @CliCommand(value = CREATE_MOCK_CACHE_EXTENSION) @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) public Result createMockCacheExtension( @CliOption(key = OPTION_VALUE, mandatory = true) final String value) { return executeFunctionOnAllMembersTabulateResultPersist( CreateMockCacheExtensionFunction.INSTANCE, true, CreateMockCacheExtensionFunction.toArgs(value)); } /** * Alter a {@link MockCacheExtension}. * * @param value {@link String} value to set on {@link MockCacheExtension#setValue(String)}. * @return {@link Result} * @since GemFire 8.1 */ @CliCommand(value = ALTER_MOCK_CACHE_EXTENSION) @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) public Result alterMockCacheExtension( @CliOption(key = OPTION_VALUE, mandatory = true) final String value) { return executeFunctionOnAllMembersTabulateResultPersist( AlterMockCacheExtensionFunction.INSTANCE, true, AlterMockCacheExtensionFunction.toArgs(value)); } /** * Destroy a {@link MockCacheExtension}. * * @return {@link Result} * @since GemFire 8.1 */ @CliCommand(value = DESTROY_MOCK_CACHE_EXTENSION) @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) public Result destroyMockCacheExtension() { return executeFunctionOnAllMembersTabulateResultPersist( DestroyMockCacheExtensionFunction.INSTANCE, false); } /** * Call <code>function</code> with <code>args</code> on all members, tabulate results and persist * shared config if changed. * * @param function {@link Function} to execute. * @param addXmlElement If <code>true</code> then add result {@link XmlEntity} to the config, * otherwise delete it. * @param args Arguments to pass to function. * @return {@link TabularResultData} * @since GemFire 8.1 */ protected Result executeFunctionOnAllMembersTabulateResultPersist(final Function function, final boolean addXmlElement, final Object... args) { final Cache cache = CacheFactory.getAnyInstance(); final Set<DistributedMember> members = CliUtil.getAllNormalMembers(cache); @SuppressWarnings("unchecked") final ResultCollector<CliFunctionResult, List<CliFunctionResult>> resultCollector = (ResultCollector<CliFunctionResult, List<CliFunctionResult>>) CliUtil .executeFunction(function, args, members); final List<CliFunctionResult> functionResults = (List<CliFunctionResult>) resultCollector.getResult(); AtomicReference<XmlEntity> xmlEntity = new AtomicReference<>(); final TabularResultData tabularResultData = ResultBuilder.createTabularResultData(); final String errorPrefix = "ERROR: "; for (CliFunctionResult functionResult : functionResults) { boolean success = functionResult.isSuccessful(); tabularResultData.accumulate("Member", functionResult.getMemberIdOrName()); if (success) { tabularResultData.accumulate("Status", functionResult.getMessage()); xmlEntity.set(functionResult.getXmlEntity()); } else { tabularResultData.accumulate("Status", errorPrefix + functionResult.getMessage()); tabularResultData.setStatus(Status.ERROR); } } final Result result = ResultBuilder.buildResult(tabularResultData); System.out.println("MockExtensionCommands: persisting xmlEntity=" + xmlEntity); if (null != xmlEntity.get()) { if (addXmlElement) { persistClusterConfiguration(result, () -> getSharedConfiguration().addXmlEntity(xmlEntity.get(), null)); } else { persistClusterConfiguration(result, () -> getSharedConfiguration().deleteXmlEntity(xmlEntity.get(), null)); } } return result; } }