mirror of https://github.com/apache/nifi.git
NIFI-7380 - fix for controller service validation in NiFi Stateless
This closes #4264. Signed-off-by: Matthieu Cauffiez <matthieu.cauffiez@bell.ca> Signed-off-by: Mark Payne <markap14@hotmail.com>
This commit is contained in:
parent
a3cc2c58ff
commit
179675f0b4
|
@ -16,7 +16,8 @@
|
|||
*/
|
||||
package org.apache.nifi.stateless.core;
|
||||
|
||||
import org.apache.nifi.parameter.ParameterLookup;
|
||||
import org.apache.nifi.controller.PropertyConfiguration;
|
||||
import org.apache.nifi.parameter.ParameterContext;
|
||||
import org.apache.nifi.components.PropertyDescriptor;
|
||||
import org.apache.nifi.components.PropertyValue;
|
||||
import org.apache.nifi.controller.ConfigurationContext;
|
||||
|
@ -24,43 +25,56 @@ import org.apache.nifi.controller.ControllerService;
|
|||
import org.apache.nifi.controller.ControllerServiceLookup;
|
||||
import org.apache.nifi.registry.VariableRegistry;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class StatelessConfigurationContext implements ConfigurationContext {
|
||||
|
||||
private final Map<PropertyDescriptor, String> properties;
|
||||
private final Map<PropertyDescriptor, PropertyConfiguration> properties;
|
||||
private final ControllerServiceLookup serviceLookup;
|
||||
private final ControllerService service;
|
||||
private final VariableRegistry variableRegistry;
|
||||
private final ParameterLookup parameterLookup;
|
||||
private final ParameterContext parameterContext;
|
||||
|
||||
public StatelessConfigurationContext(final ControllerService service,
|
||||
final Map<PropertyDescriptor, String> properties,
|
||||
final Map<PropertyDescriptor, PropertyConfiguration> properties,
|
||||
final ControllerServiceLookup serviceLookup,
|
||||
final VariableRegistry variableRegistry,
|
||||
final ParameterLookup parameterLookup) {
|
||||
final ParameterContext parameterLookup) {
|
||||
this.service = service;
|
||||
this.properties = properties;
|
||||
this.serviceLookup = serviceLookup;
|
||||
this.variableRegistry = variableRegistry;
|
||||
this.parameterLookup = parameterLookup;
|
||||
this.parameterContext = parameterLookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyValue getProperty(final PropertyDescriptor property) {
|
||||
String value = properties.get(property);
|
||||
if (value == null) {
|
||||
value = getActualDescriptor(property).getDefaultValue();
|
||||
}
|
||||
return new StatelessPropertyValue(value, serviceLookup, parameterLookup, variableRegistry);
|
||||
final PropertyConfiguration setPropertyValue = properties.get(property);
|
||||
final String propValue = (setPropertyValue == null) ? getActualDescriptor(property).getDefaultValue() : setPropertyValue.getEffectiveValue(parameterContext);
|
||||
return new StatelessPropertyValue(propValue, serviceLookup, parameterContext, variableRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<PropertyDescriptor, String> getProperties() {
|
||||
return new HashMap<>(this.properties);
|
||||
final List<PropertyDescriptor> supported = service.getPropertyDescriptors();
|
||||
|
||||
final Map<PropertyDescriptor, String> effectiveValues = new LinkedHashMap<>();
|
||||
for (final PropertyDescriptor descriptor : supported) {
|
||||
effectiveValues.put(descriptor, null);
|
||||
}
|
||||
|
||||
for (final Map.Entry<PropertyDescriptor, PropertyConfiguration> entry : properties.entrySet()) {
|
||||
final PropertyDescriptor descriptor = entry.getKey();
|
||||
final PropertyConfiguration configuration = entry.getValue();
|
||||
final String value = configuration.getEffectiveValue(parameterContext);
|
||||
|
||||
effectiveValues.put(descriptor, value);
|
||||
}
|
||||
|
||||
return effectiveValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.apache.nifi.stateless.core;
|
|||
|
||||
import org.apache.nifi.components.PropertyDescriptor;
|
||||
import org.apache.nifi.controller.ControllerService;
|
||||
import org.apache.nifi.controller.PropertyConfiguration;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -31,7 +32,7 @@ public class StatelessControllerServiceConfiguration {
|
|||
|
||||
private final AtomicBoolean enabled = new AtomicBoolean(false);
|
||||
private String annotationData;
|
||||
private Map<PropertyDescriptor, String> properties = new HashMap<>();
|
||||
private Map<PropertyDescriptor, PropertyConfiguration> properties = new HashMap<>();
|
||||
|
||||
public StatelessControllerServiceConfiguration(final ControllerService service, final String name) {
|
||||
this.service = service;
|
||||
|
@ -50,20 +51,20 @@ public class StatelessControllerServiceConfiguration {
|
|||
return this.enabled.get();
|
||||
}
|
||||
|
||||
public void setProperties(final Map<PropertyDescriptor, String> props) {
|
||||
public void setProperties(final Map<PropertyDescriptor, PropertyConfiguration> props) {
|
||||
this.properties = new HashMap<>(props);
|
||||
}
|
||||
|
||||
public void setProperty(final PropertyDescriptor key, final String value) {
|
||||
public void setProperty(final PropertyDescriptor key, final PropertyConfiguration value) {
|
||||
this.properties.put(key, value);
|
||||
}
|
||||
|
||||
public String getProperty(final PropertyDescriptor descriptor) {
|
||||
final String value = properties.get(descriptor);
|
||||
final PropertyConfiguration value = properties.get(descriptor);
|
||||
if (value == null) {
|
||||
return descriptor.getDefaultValue();
|
||||
} else {
|
||||
return value;
|
||||
return value.getRawValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +76,7 @@ public class StatelessControllerServiceConfiguration {
|
|||
return annotationData;
|
||||
}
|
||||
|
||||
public Map<PropertyDescriptor, String> getProperties() {
|
||||
public Map<PropertyDescriptor, PropertyConfiguration> getProperties() {
|
||||
return Collections.unmodifiableMap(properties);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,12 @@ import org.apache.nifi.components.state.StateManager;
|
|||
import org.apache.nifi.controller.ConfigurationContext;
|
||||
import org.apache.nifi.controller.ControllerService;
|
||||
import org.apache.nifi.controller.ControllerServiceLookup;
|
||||
import org.apache.nifi.controller.PropertyConfiguration;
|
||||
import org.apache.nifi.parameter.ExpressionLanguageAgnosticParameterParser;
|
||||
import org.apache.nifi.parameter.ExpressionLanguageAwareParameterParser;
|
||||
import org.apache.nifi.parameter.ParameterContext;
|
||||
import org.apache.nifi.parameter.ParameterParser;
|
||||
import org.apache.nifi.parameter.ParameterTokenList;
|
||||
import org.apache.nifi.registry.VariableRegistry;
|
||||
import org.apache.nifi.reporting.InitializationException;
|
||||
|
||||
|
@ -128,10 +133,10 @@ public class StatelessControllerServiceLookup implements ControllerServiceLookup
|
|||
public void enableControllerServices(final VariableRegistry variableRegistry) {
|
||||
for (final StatelessControllerServiceConfiguration config : controllerServiceMap.values()) {
|
||||
final ControllerService service = config.getService();
|
||||
final Collection<ValidationResult> validationResults = validate(service, config.getName(), variableRegistry);
|
||||
final Collection<ValidationResult> validationResults = validate(service, config, variableRegistry);
|
||||
if (!validationResults.isEmpty()) {
|
||||
throw new RuntimeException("Failed to enable Controller Service {id=" + service.getIdentifier() + ", name=" + config.getName() + ", type=" + service.getClass() + "} because " +
|
||||
"validation failed: " + validationResults);
|
||||
"validation failed: " + validationResults);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -142,10 +147,11 @@ public class StatelessControllerServiceLookup implements ControllerServiceLookup
|
|||
}
|
||||
}
|
||||
|
||||
public Collection<ValidationResult> validate(final ControllerService service, final String serviceName, final VariableRegistry variableRegistry) {
|
||||
public Collection<ValidationResult> validate(final ControllerService service, final StatelessControllerServiceConfiguration serviceName, final VariableRegistry variableRegistry) {
|
||||
final StateManager stateManager = controllerServiceStateManagers.get(service.getIdentifier());
|
||||
final SLF4JComponentLog logger = controllerServiceLoggers.get(service.getIdentifier());
|
||||
final StatelessProcessContext processContext = new StatelessProcessContext(service, this, serviceName, logger, stateManager, variableRegistry, parameterContext);
|
||||
final StatelessProcessContext processContext = new StatelessProcessContext(service, this, serviceName.getName(), logger, stateManager, variableRegistry, parameterContext);
|
||||
serviceName.getProperties().forEach((k,v) -> processContext.setProperty(k,v.getRawValue()));
|
||||
final StatelessValidationContext validationContext = new StatelessValidationContext(processContext, this, stateManager, variableRegistry, parameterContext);
|
||||
return service.validate(validationContext);
|
||||
}
|
||||
|
@ -192,18 +198,27 @@ public class StatelessControllerServiceLookup implements ControllerServiceLookup
|
|||
throw new IllegalStateException("Controller service " + service + " has not been added to this TestRunner via the #addControllerService method");
|
||||
}
|
||||
|
||||
final ValidationContext validationContext = new StatelessValidationContext(context, this, serviceStateManager, registry, parameterContext).getControllerServiceValidationContext(service);
|
||||
final ValidationContext validationContext = new StatelessValidationContext(context, this, serviceStateManager, registry, parameterContext);
|
||||
final ValidationResult validationResult = property.validate(value, validationContext);
|
||||
|
||||
final StatelessControllerServiceConfiguration configuration = getControllerServiceConfigToUpdate(service);
|
||||
final String oldValue = configuration.getProperties().get(property);
|
||||
configuration.setProperty(property, value);
|
||||
final PropertyConfiguration oldValue = configuration.getProperties().get(property);
|
||||
final PropertyConfiguration propertyConfiguration = createPropertyConfiguration(value, property.isExpressionLanguageSupported());
|
||||
configuration.setProperty(property, propertyConfiguration);
|
||||
|
||||
if ((value == null && oldValue != null) || (value != null && !value.equals(oldValue))) {
|
||||
service.onPropertyModified(property, oldValue, value);
|
||||
if (oldValue == null && value != null) {
|
||||
service.onPropertyModified(property, null, value);
|
||||
} else if ((value == null && oldValue.getRawValue() != null) || (value != null && !value.equals(oldValue.getRawValue()))) {
|
||||
service.onPropertyModified(property, oldValue.getRawValue(), value);
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
private PropertyConfiguration createPropertyConfiguration(final String value, final boolean supportsEl) {
|
||||
final ParameterParser parameterParser = supportsEl ? new ExpressionLanguageAwareParameterParser() : new ExpressionLanguageAgnosticParameterParser();
|
||||
final ParameterTokenList parameterTokenList = parameterParser.parseTokens(value);
|
||||
return new PropertyConfiguration(value, parameterTokenList, parameterTokenList.toReferenceList());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue