blob: 0638b669007b19e548e9f53b96da33e4847f2126 [file] [log] [blame]
/*
* 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.management.internal.cli.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.apache.geode.cache.configuration.CacheConfig;
import org.apache.geode.cache.configuration.CacheElement;
import org.apache.geode.cache.query.management.configuration.QueryConfigService;
import org.apache.geode.distributed.ConfigurationPersistenceService;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.management.cli.SingleGfshCommand;
import org.apache.geode.management.internal.cli.functions.AlterQueryServiceFunction;
import org.apache.geode.management.internal.cli.result.model.ResultModel;
import org.apache.geode.management.internal.functions.CliFunctionResult;
import org.apache.geode.management.internal.security.ResourceOperation;
import org.apache.geode.security.ResourcePermission;
public class AlterQueryServiceCommand extends SingleGfshCommand {
static final String COMMAND_NAME = "alter query-service";
private static final String COMMAND_HELP = "Alter configuration parameters for the query service";
static final String AUTHORIZER_NAME = "method-authorizer";
private static final String METHOD_AUTHORIZER_NAME_HELP =
"The name of the class to be used for OQL method authorization";
static final String AUTHORIZER_PARAMETERS = "authorizer-parameters";
private static final String AUTHORIZER_PARAMETERS_HELP =
"A semicolon separated list of all parameter values for the specified method authorizer.";
static final String FORCE_UPDATE = "force-update";
private static final String FORCE_UPDATE_HELP =
"Flag to indicate whether to forcibly update the currently configured authorizer, even when there are continuous queries registered (use with caution)";
static final String NO_MEMBERS_FOUND_MESSAGE = "No members found.";
public static final String PARTIAL_FAILURE_MESSAGE =
"In the event of a partial failure of this command, re-running the command or restarting failing members should restore consistency.";
static final String SPLITTING_REGEX = ";";
private final AlterQueryServiceFunction alterQueryServiceFunction =
new AlterQueryServiceFunction();
@CliCommand(value = COMMAND_NAME, help = COMMAND_HELP)
@ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
operation = ResourcePermission.Operation.MANAGE)
public ResultModel execute(
@CliOption(key = AUTHORIZER_NAME, help = METHOD_AUTHORIZER_NAME_HELP,
mandatory = true) String methodAuthorizerName,
@CliOption(key = AUTHORIZER_PARAMETERS, help = AUTHORIZER_PARAMETERS_HELP,
optionContext = "splittingRegex=" + SPLITTING_REGEX) String[] authorizerParameters,
@CliOption(key = FORCE_UPDATE, help = FORCE_UPDATE_HELP, specifiedDefaultValue = "true",
unspecifiedDefaultValue = "false") boolean forceUpdate) {
ResultModel result;
Set<String> parametersSet = new HashSet<>();
QueryConfigService queryConfigService = getQueryConfigService();
if (authorizerParameters != null) {
parametersSet.addAll(Arrays.asList(authorizerParameters));
}
populateMethodAuthorizer(methodAuthorizerName, parametersSet, queryConfigService);
Set<DistributedMember> targetMembers = findMembers(null, null);
if (targetMembers.isEmpty()) {
result = ResultModel.createInfo(NO_MEMBERS_FOUND_MESSAGE);
} else {
String footer = null;
Object[] args = new Object[] {forceUpdate, methodAuthorizerName, parametersSet};
List<CliFunctionResult> functionResults =
executeAndGetFunctionResult(alterQueryServiceFunction, args, targetMembers);
if (functionResults.stream().anyMatch(CliFunctionResult::isSuccessful)
&& functionResults.stream().anyMatch(functionResult -> !functionResult.isSuccessful())) {
footer = PARTIAL_FAILURE_MESSAGE;
}
result = ResultModel.createMemberStatusResult(functionResults, null, footer, false, true);
}
result.setConfigObject(queryConfigService);
return result;
}
void populateMethodAuthorizer(String methodAuthorizerName, Set<String> parameterSet,
QueryConfigService queryConfigService) {
QueryConfigService.MethodAuthorizer methodAuthorizer =
new QueryConfigService.MethodAuthorizer();
methodAuthorizer.setClassName(methodAuthorizerName);
if (!parameterSet.isEmpty()) {
List<QueryConfigService.MethodAuthorizer.Parameter> parameterList = new ArrayList<>();
for (String value : parameterSet) {
QueryConfigService.MethodAuthorizer.Parameter parameter =
new QueryConfigService.MethodAuthorizer.Parameter();
parameter.setParameterValue(value);
parameterList.add(parameter);
}
methodAuthorizer.setParameters(parameterList);
}
queryConfigService.setMethodAuthorizer(methodAuthorizer);
}
QueryConfigService getQueryConfigService() {
ConfigurationPersistenceService configService = getConfigurationPersistenceService();
if (configService != null) {
CacheConfig cacheConfig = configService.getCacheConfig(null);
if (cacheConfig != null) {
QueryConfigService queryConfigService = cacheConfig
.findCustomCacheElement(QueryConfigService.ELEMENT_ID, QueryConfigService.class);
if (queryConfigService != null) {
return queryConfigService;
}
}
}
return new QueryConfigService();
}
@Override
public boolean updateConfigForGroup(String group, CacheConfig config, Object configObject) {
if (configObject instanceof QueryConfigService) {
List<CacheElement> elements = config.getCustomCacheElements();
elements.removeIf(e -> e instanceof QueryConfigService);
elements.add((QueryConfigService) configObject);
return true;
}
return false;
}
}