Skip to content
Permalink
Browse files
AMBARI-25037. Allow skipping parts of Add Service request validation (#…
  • Loading branch information
adoroszlai committed Dec 13, 2018
1 parent eb226e1 commit 2411ccf6d633aa97cf48d181b6254f3ac36d5f89
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 49 deletions.
@@ -71,15 +71,17 @@ public class AddServiceRequest {
private static final String STACK_VERSION = "stack_version";
private static final String SERVICES = "services";
private static final String COMPONENTS = "components";
private static final String VALIDATION = "validation";

public static final Set<String> TOP_LEVEL_PROPERTIES = ImmutableSet.of(
OPERATION_TYPE, CONFIG_RECOMMENDATION_STRATEGY, PROVISION_ACTION_PROPERTY,
OPERATION_TYPE, CONFIG_RECOMMENDATION_STRATEGY, PROVISION_ACTION_PROPERTY, VALIDATION,
STACK_NAME, STACK_VERSION, SERVICES, COMPONENTS, CONFIGURATIONS
);

private final OperationType operationType;
private final ConfigRecommendationStrategy recommendationStrategy;
private final ProvisionAction provisionAction;
private final ValidationType validationType;
private final String stackName;
private final String stackVersion;
private final Set<Service> services;
@@ -93,6 +95,7 @@ public AddServiceRequest(
@JsonProperty(OPERATION_TYPE) OperationType operationType,
@JsonProperty(CONFIG_RECOMMENDATION_STRATEGY) ConfigRecommendationStrategy recommendationStrategy,
@JsonProperty(PROVISION_ACTION_PROPERTY) ProvisionAction provisionAction,
@JsonProperty(VALIDATION) ValidationType validationType,
@JsonProperty(STACK_NAME) String stackName,
@JsonProperty(STACK_VERSION) String stackVersion,
@JsonProperty(SERVICES) Set<Service> services,
@@ -101,7 +104,7 @@ public AddServiceRequest(
@JsonProperty(CREDENTIALS) Set<Credential> credentials,
@JsonProperty(CONFIGURATIONS) Collection<? extends Map<String, ?>> configs
) {
this(operationType, recommendationStrategy, provisionAction, stackName, stackVersion, services, components,
this(operationType, recommendationStrategy, provisionAction, validationType, stackName, stackVersion, services, components,
security, credentials,
ConfigurableHelper.parseConfigs(configs)
);
@@ -111,6 +114,7 @@ private AddServiceRequest(
OperationType operationType,
ConfigRecommendationStrategy recommendationStrategy,
ProvisionAction provisionAction,
ValidationType validationType,
String stackName,
String stackVersion,
Set<Service> services,
@@ -122,6 +126,7 @@ private AddServiceRequest(
this.operationType = null != operationType ? operationType : OperationType.ADD_SERVICE;
this.recommendationStrategy = null != recommendationStrategy ? recommendationStrategy : ConfigRecommendationStrategy.NEVER_APPLY;
this.provisionAction = null != provisionAction ? provisionAction : ProvisionAction.INSTALL_AND_START;
this.validationType = validationType != null ? validationType : ValidationType.DEFAULT;
this.stackName = stackName;
this.stackVersion = stackVersion;
this.services = null != services ? services : emptySet();
@@ -160,6 +165,12 @@ public ProvisionAction getProvisionAction() {
return provisionAction;
}

@JsonProperty(VALIDATION)
@ApiModelProperty(name = VALIDATION)
public ValidationType getValidationType() {
return validationType;
}

@JsonProperty(STACK_NAME)
@ApiModelProperty(name = STACK_NAME)
public String getStackName() {
@@ -233,6 +244,7 @@ public boolean equals(Object obj) {
AddServiceRequest other = (AddServiceRequest) obj;

return Objects.equals(operationType, other.operationType) &&
Objects.equals(validationType, other.validationType) &&
Objects.equals(recommendationStrategy, other.recommendationStrategy) &&
Objects.equals(provisionAction, other.provisionAction) &&
Objects.equals(stackName, other.stackName) &&
@@ -246,7 +258,7 @@ public boolean equals(Object obj) {

@Override
public int hashCode() {
return Objects.hash(operationType, recommendationStrategy, provisionAction, stackName, stackVersion,
return Objects.hash(operationType, validationType, recommendationStrategy, provisionAction, stackName, stackVersion,
services, components, configuration, security);
// credentials is ignored for hashcode, since it's not serialized
}
@@ -255,6 +267,7 @@ public int hashCode() {
public String toString() {
return MoreObjects.toStringHelper(this)
.add(OPERATION_TYPE, operationType)
.add(VALIDATION, validationType)
.add(CONFIG_RECOMMENDATION_STRATEGY, recommendationStrategy)
.add(PROVISION_ACTION_PROPERTY, provisionAction)
.add(STACK_NAME, stackName)
@@ -273,6 +286,32 @@ public enum OperationType {
ADD_SERVICE, DELETE_SERVICE, MOVE_SERVICE
}

public enum ValidationType {
/**
* Perform all validation checks.
*/
STRICT {
@Override
public boolean strictValidation() {
return true;
}
},
/**
* Skip the parts of validation that are not strictly necessary.
*/
PERMISSIVE {
@Override
public boolean strictValidation() {
return false;
}
},
;

public static final ValidationType DEFAULT = STRICT;

public abstract boolean strictValidation();
}

public static final class Component {

static final String COMPONENT_NAME = "name";
@@ -43,6 +43,7 @@
import org.apache.ambari.server.state.StackId;
import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
import org.apache.ambari.server.state.kerberos.KerberosDescriptorFactory;
import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
import org.apache.ambari.server.topology.Configuration;
import org.apache.ambari.server.topology.SecurityConfigurationFactory;
import org.apache.ambari.server.topology.StackFactory;
@@ -134,7 +135,7 @@ void setState(State state) {
@VisibleForTesting
void validateSecurity() {
request.getSecurity().ifPresent(requestSecurity -> {
CHECK.checkArgument(requestSecurity.getType() == cluster.getSecurityType(),
CHECK.checkArgument(!strictValidation() || requestSecurity.getType() == cluster.getSecurityType(),
"Security type in the request (%s), if specified, should match cluster's security type (%s)",
requestSecurity.getType(), cluster.getSecurityType()
);
@@ -162,13 +163,17 @@ void validateSecurity() {

KerberosDescriptor descriptor = kerberosDescriptorFactory.createInstance(descriptorMap);

Set<String> servicesWithNewDescriptor = descriptor.getServices().keySet();
Set<String> newServices = state.getNewServices().keySet();
Set<String> nonNewServices = ImmutableSet.copyOf(Sets.difference(servicesWithNewDescriptor, newServices));
if (strictValidation()) {
Map<String, KerberosServiceDescriptor> descriptorServices = descriptor.getServices();
Set<String> servicesWithNewDescriptor = descriptorServices != null ? descriptorServices.keySet() : ImmutableSet.of();
Set<String> newServices = state.getNewServices().keySet();
Set<String> nonNewServices = ImmutableSet.copyOf(Sets.difference(servicesWithNewDescriptor, newServices));

CHECK.checkArgument(nonNewServices.isEmpty(),
"Kerberos descriptor should be provided only for new services, but found other services: %s",
nonNewServices);
CHECK.checkArgument(nonNewServices.isEmpty(),
"Kerberos descriptor should be provided only for new services, but found other services: %s",
nonNewServices
);
}

try {
descriptor.toMap();
@@ -238,8 +243,10 @@ void validateServicesAndComponents() {
void validateConfiguration() {
Configuration config = request.getConfiguration();

for (String type : NOT_ALLOWED_CONFIG_TYPES) {
CHECK.checkArgument(!config.getProperties().containsKey(type), "Cannot change '%s' configuration in Add Service request", type);
if (strictValidation()) {
for (String type : NOT_ALLOWED_CONFIG_TYPES) {
CHECK.checkArgument(!config.getProperties().containsKey(type), "Cannot change '%s' configuration in Add Service request", type);
}
}

Configuration clusterConfig = getClusterDesiredConfigs();
@@ -262,6 +269,10 @@ void validateHosts() {
"Requested host not associated with cluster %s: %s", cluster.getClusterName(), unknownHosts);
}

private boolean strictValidation() {
return request.getValidationType().strictValidation();
}

private Configuration getClusterDesiredConfigs() {
try {
return Configuration.of(configHelper.calculateExistingConfigs(cluster));
@@ -21,6 +21,8 @@
import static org.apache.ambari.server.controller.AddServiceRequest.Component;
import static org.apache.ambari.server.controller.AddServiceRequest.OperationType.ADD_SERVICE;
import static org.apache.ambari.server.controller.AddServiceRequest.Service;
import static org.apache.ambari.server.controller.AddServiceRequest.ValidationType.PERMISSIVE;
import static org.apache.ambari.server.controller.AddServiceRequest.ValidationType.STRICT;
import static org.apache.ambari.server.controller.internal.ProvisionAction.INSTALL_AND_START;
import static org.apache.ambari.server.controller.internal.ProvisionAction.INSTALL_ONLY;
import static org.apache.ambari.server.topology.ConfigRecommendationStrategy.ALWAYS_APPLY;
@@ -86,6 +88,7 @@ public void testDeserialize_basic() throws Exception {
assertEquals(ADD_SERVICE, request.getOperationType());
assertEquals(ALWAYS_APPLY, request.getRecommendationStrategy());
assertEquals(INSTALL_ONLY, request.getProvisionAction());
assertEquals(PERMISSIVE, request.getValidationType());
assertEquals("HDP", request.getStackName());
assertEquals("3.0", request.getStackVersion());

@@ -134,6 +137,7 @@ public void testDeserialize_defaultAndEmptyValues() throws Exception {
assertEquals(ADD_SERVICE, request.getOperationType());
assertEquals(NEVER_APPLY, request.getRecommendationStrategy());
assertEquals(INSTALL_AND_START, request.getProvisionAction());
assertEquals(STRICT, request.getValidationType());
assertNull(request.getStackName());
assertNull(request.getStackVersion());
assertEquals(Optional.empty(), request.getSecurity());

0 comments on commit 2411ccf

Please sign in to comment.