NIFI-12079 This closes #7750. Remove Variables / Variable Registry

Signed-off-by: Joseph Witt <joewitt@apache.org>
This commit is contained in:
Pierre Villard 2023-09-25 12:33:10 +02:00 committed by Joseph Witt
parent 025109a9d8
commit 43cc5ad122
No known key found for this signature in database
GPG Key ID: 9093BF854F811A1A
516 changed files with 11029 additions and 17541 deletions

View File

@ -87,7 +87,6 @@ public class MiNiFiPropertiesGenerator {
Triple.of(NiFiProperties.FLOW_CONTROLLER_GRACEFUL_SHUTDOWN_PERIOD, "10 sec", EMPTY),
Triple.of(NiFiProperties.WRITE_DELAY_INTERVAL, "500 ms", EMPTY),
Triple.of(NiFiProperties.ADMINISTRATIVE_YIELD_DURATION, "30 sec", EMPTY),
Triple.of(NiFiProperties.VARIABLE_REGISTRY_PROPERTIES, EMPTY, EMPTY),
Triple.of(NiFiProperties.BORED_YIELD_DURATION, "10 millis",
"# If a component has no work to do (is \"bored\"), how long should we wait before checking again for work"),
Triple.of(NiFiProperties.LOGIN_IDENTITY_PROVIDER_CONFIGURATION_FILE, "./conf/login-identity-providers.xml", EMPTY),

View File

@ -23,7 +23,6 @@ Core Properties:
administrative yield duration: 30 sec
bored yield duration: 10 millis
max concurrent threads: 1
variable registry properties: additional.properties
FlowFile Repository:
partitions: 256
checkpoint interval: 2 mins

View File

@ -33,7 +33,6 @@ nifi.ui.autorefresh.interval=30 sec
nifi.nar.library.directory=./lib
nifi.nar.working.directory=./work/nar/
nifi.documentation.working.directory=./work/docs/components
nifi.variable.registry.properties=additional.properties
####################
# State Management #

View File

@ -23,7 +23,6 @@ Core Properties:
administrative yield duration: 30 sec
bored yield duration: 10 millis
max concurrent threads: 1
variable registry properties: ''
FlowFile Repository:
partitions: 256
checkpoint interval: 2 mins
@ -99,4 +98,4 @@ Output Ports: []
Funnels: []
Connections: []
Remote Process Groups: []
NiFi Properties Overrides: {}
NiFi Properties Overrides: {}

View File

@ -23,7 +23,6 @@ Core Properties:
administrative yield duration: 30 sec
bored yield duration: 10 millis
max concurrent threads: 1
variable registry properties: additional.properties
Security Properties:
keystore: /tmp/ssl/localhost-ks.jks
keystore type: JKS

View File

@ -23,7 +23,6 @@ Core Properties:
administrative yield duration: 30 sec
bored yield duration: 10 millis
max concurrent threads: 1
variable registry properties: additional.properties
FlowFile Repository:
partitions: 256
checkpoint interval: 2 mins

View File

@ -23,7 +23,6 @@ Core Properties:
administrative yield duration: 30 sec
bored yield duration: 10 millis
max concurrent threads: 1
variable registry properties: additional.properties
FlowFile Repository:
partitions: 256
checkpoint interval: 2 mins

View File

@ -178,7 +178,6 @@ nifi.minifi.sensitive.props.algorithm=
nifi.flowcontroller.graceful.shutdown.period=10 sec
nifi.flowservice.writedelay.interval=500 ms
nifi.administrative.yield.duration=30 sec
nifi.variable.registry.properties=
nifi.bored.yield.duration=10 millis
# FlowFile Repository
nifi.flowfile.repository.implementation=org.apache.nifi.controller.repository.WriteAheadFlowFileRepository

View File

@ -186,7 +186,6 @@ nifi.minifi.notifier.ingestors.pull.http.truststore.password=badTrustPass
nifi.flowcontroller.graceful.shutdown.period=10 sec
nifi.flowservice.writedelay.interval=500 ms
nifi.administrative.yield.duration=30 sec
nifi.variable.registry.properties=
nifi.bored.yield.duration=10 millis
# FlowFile Repository
nifi.flowfile.repository.implementation=org.apache.nifi.controller.repository.WriteAheadFlowFileRepository

View File

@ -179,7 +179,6 @@ nifi.minifi.notifier.ingestors.pull.http.headers=Accept:application/json
nifi.flowcontroller.graceful.shutdown.period=10 sec
nifi.flowservice.writedelay.interval=500 ms
nifi.administrative.yield.duration=30 sec
nifi.variable.registry.properties=
nifi.bored.yield.duration=10 millis
# FlowFile Repository
nifi.flowfile.repository.implementation=org.apache.nifi.controller.repository.WriteAheadFlowFileRepository

View File

@ -189,7 +189,6 @@ nifi.minifi.notifier.ingestors.pull.http.truststore.password=badTrustPass
nifi.flowcontroller.graceful.shutdown.period=10 sec
nifi.flowservice.writedelay.interval=500 ms
nifi.administrative.yield.duration=30 sec
nifi.variable.registry.properties=
nifi.bored.yield.duration=10 millis
# FlowFile Repository
nifi.flowfile.repository.implementation=org.apache.nifi.controller.repository.WriteAheadFlowFileRepository

View File

@ -155,7 +155,6 @@ c2.security.keystore.type=JKS
nifi.flowcontroller.graceful.shutdown.period=10 sec
nifi.flowservice.writedelay.interval=500 ms
nifi.administrative.yield.duration=30 sec
nifi.variable.registry.properties=
nifi.bored.yield.duration=10 millis
# FlowFile Repository
nifi.flowfile.repository.implementation=org.apache.nifi.controller.repository.WriteAheadFlowFileRepository

View File

@ -156,7 +156,6 @@ c2.security.keystore.type=JKS
nifi.flowcontroller.graceful.shutdown.period=10 sec
nifi.flowservice.writedelay.interval=500 ms
nifi.administrative.yield.duration=30 sec
nifi.variable.registry.properties=
nifi.bored.yield.duration=10 millis
# FlowFile Repository
nifi.flowfile.repository.implementation=org.apache.nifi.controller.repository.WriteAheadFlowFileRepository

View File

@ -156,7 +156,6 @@ c2.security.keystore.type=JKS
nifi.flowcontroller.graceful.shutdown.period=10 sec
nifi.flowservice.writedelay.interval=500 ms
nifi.administrative.yield.duration=30 sec
nifi.variable.registry.properties=
nifi.bored.yield.duration=10 millis
# FlowFile Repository
nifi.flowfile.repository.implementation=org.apache.nifi.controller.repository.WriteAheadFlowFileRepository

View File

@ -184,7 +184,6 @@ nifi.minifi.sensitive.props.algorithm=
nifi.flowcontroller.graceful.shutdown.period=10 sec
nifi.flowservice.writedelay.interval=500 ms
nifi.administrative.yield.duration=30 sec
nifi.variable.registry.properties=
nifi.bored.yield.duration=10 millis
# FlowFile Repository
nifi.flowfile.repository.implementation=org.apache.nifi.controller.repository.WriteAheadFlowFileRepository

View File

@ -45,7 +45,6 @@ import static org.apache.nifi.util.NiFiProperties.PROVENANCE_MAX_STORAGE_TIME;
import static org.apache.nifi.util.NiFiProperties.PROVENANCE_REPO_IMPLEMENTATION_CLASS;
import static org.apache.nifi.util.NiFiProperties.PROVENANCE_ROLLOVER_TIME;
import static org.apache.nifi.util.NiFiProperties.QUEUE_SWAP_THRESHOLD;
import static org.apache.nifi.util.NiFiProperties.VARIABLE_REGISTRY_PROPERTIES;
import static org.apache.nifi.util.NiFiProperties.WRITE_DELAY_INTERVAL;
import java.util.List;
@ -127,7 +126,6 @@ public class ConfigSchemaToVersionedDataFlowTransformer {
entry(WRITE_DELAY_INTERVAL, coreProperties.getFlowServiceWriteDelayInterval()),
entry(ADMINISTRATIVE_YIELD_DURATION, coreProperties.getAdministrativeYieldDuration()),
entry(BORED_YIELD_DURATION, coreProperties.getBoredYieldDuration()),
entry(VARIABLE_REGISTRY_PROPERTIES, coreProperties.getVariableRegistryProperties()),
entry(FLOWFILE_REPOSITORY_IMPLEMENTATION, flowFileRepositoryProperties.getFlowFileRepository()),
entry(FLOWFILE_REPOSITORY_CHECKPOINT_INTERVAL, flowFileRepositoryProperties.getCheckpointInterval()),
entry(FLOWFILE_REPOSITORY_ALWAYS_SYNC, Boolean.toString(flowFileRepositoryProperties.getAlwaysSync())),

View File

@ -34,21 +34,18 @@ public class CorePropertiesSchema extends BaseSchema implements WritableSchema {
public static final String FLOW_SERVICE_WRITE_DELAY_INTERVAL_KEY = "flow service write delay interval";
public static final String ADMINISTRATIVE_YIELD_DURATION_KEY = "administrative yield duration";
public static final String BORED_YIELD_DURATION_KEY = "bored yield duration";
public static final String VARIABLE_REGISTRY_PROPERTIES_KEY = "variable registry properties";
public static final String DEFAULT_FLOW_CONTROLLER_GRACEFUL_SHUTDOWN_PERIOD = "10 sec";
public static final String DEFAULT_FLOW_SERVICE_WRITE_DELAY_INTERVAL = "500 ms";
public static final String DEFAULT_ADMINISTRATIVE_YIELD_DURATION = "30 sec";
public static final String DEFAULT_BORED_YIELD_DURATION = "10 millis";
public static final int DEFAULT_MAX_CONCURRENT_THREADS = 1;
public static final String DEFAULT_VARIABLE_REGISTRY_PROPERTIES = "";
private String flowControllerGracefulShutdownPeriod = DEFAULT_FLOW_CONTROLLER_GRACEFUL_SHUTDOWN_PERIOD;
private String flowServiceWriteDelayInterval = DEFAULT_FLOW_SERVICE_WRITE_DELAY_INTERVAL;
private String administrativeYieldDuration = DEFAULT_ADMINISTRATIVE_YIELD_DURATION;
private String boredYieldDuration = DEFAULT_BORED_YIELD_DURATION;
private Number maxConcurrentThreads = DEFAULT_MAX_CONCURRENT_THREADS;
private String variableRegistryProperties = DEFAULT_VARIABLE_REGISTRY_PROPERTIES;
public CorePropertiesSchema() {
}
@ -63,8 +60,6 @@ public class CorePropertiesSchema extends BaseSchema implements WritableSchema {
boredYieldDuration = getOptionalKeyAsType(map, BORED_YIELD_DURATION_KEY, String.class, CORE_PROPS_KEY, DEFAULT_BORED_YIELD_DURATION);
maxConcurrentThreads = getOptionalKeyAsType(map, MAX_CONCURRENT_THREADS_KEY, Number.class,
CORE_PROPS_KEY, DEFAULT_MAX_CONCURRENT_THREADS);
variableRegistryProperties = getOptionalKeyAsType(map, VARIABLE_REGISTRY_PROPERTIES_KEY, String.class,
CORE_PROPS_KEY, DEFAULT_VARIABLE_REGISTRY_PROPERTIES);
}
@Override
@ -75,7 +70,6 @@ public class CorePropertiesSchema extends BaseSchema implements WritableSchema {
result.put(ADMINISTRATIVE_YIELD_DURATION_KEY, administrativeYieldDuration);
result.put(BORED_YIELD_DURATION_KEY, boredYieldDuration);
result.put(MAX_CONCURRENT_THREADS_KEY, maxConcurrentThreads);
result.put(VARIABLE_REGISTRY_PROPERTIES_KEY, variableRegistryProperties);
return result;
}
@ -99,8 +93,4 @@ public class CorePropertiesSchema extends BaseSchema implements WritableSchema {
return maxConcurrentThreads;
}
public String getVariableRegistryProperties() {
return variableRegistryProperties;
}
}

View File

@ -84,12 +84,6 @@ public final class PropertyDescriptor implements Comparable<PropertyDescriptor>
* user-defined
*/
private final boolean dynamic;
/**
* indicates whether or not this property supports the Attribute Expression
* Language
*/
@Deprecated
private final boolean expressionLanguageSupported;
/**
* indicates whether or nor this property will evaluate expression language
* against the flow file attributes
@ -134,7 +128,6 @@ public final class PropertyDescriptor implements Comparable<PropertyDescriptor>
this.sensitive = builder.sensitive;
this.dynamic = builder.dynamic;
this.dynamicallyModifiesClasspath = builder.dynamicallyModifiesClasspath;
this.expressionLanguageSupported = builder.expressionLanguageSupported;
this.expressionLanguageScope = builder.expressionLanguageScope;
this.controllerServiceDefinition = builder.controllerServiceDefinition;
this.validators = Collections.unmodifiableList(new ArrayList<>(builder.validators));
@ -220,10 +213,6 @@ public final class PropertyDescriptor implements Comparable<PropertyDescriptor>
private Set<PropertyDependency> dependencies = null;
private boolean required = false;
private boolean sensitive = false;
@Deprecated
private boolean expressionLanguageSupported = false;
private ExpressionLanguageScope expressionLanguageScope = ExpressionLanguageScope.NONE;
private boolean dynamic = false;
private boolean dynamicallyModifiesClasspath = false;
@ -241,7 +230,6 @@ public final class PropertyDescriptor implements Comparable<PropertyDescriptor>
this.sensitive = specDescriptor.sensitive;
this.dynamic = specDescriptor.dynamic;
this.dynamicallyModifiesClasspath = specDescriptor.dynamicallyModifiesClasspath;
this.expressionLanguageSupported = specDescriptor.expressionLanguageSupported;
this.expressionLanguageScope = specDescriptor.expressionLanguageScope;
this.controllerServiceDefinition = specDescriptor.getControllerServiceDefinition();
this.validators = new ArrayList<>(specDescriptor.validators);
@ -282,19 +270,6 @@ public final class PropertyDescriptor implements Comparable<PropertyDescriptor>
return this;
}
/**
* Sets the value indicating whether or not this Property will support
* the Attribute Expression Language.
*
* @param supported true if yes; false otherwise
* @return the builder
*/
@Deprecated
public Builder expressionLanguageSupported(final boolean supported) {
this.expressionLanguageSupported = supported;
return this;
}
/**
* Sets the scope of the expression language evaluation
*
@ -684,7 +659,7 @@ public final class PropertyDescriptor implements Comparable<PropertyDescriptor>
}
public boolean isExpressionLanguageSupported() {
return expressionLanguageSupported || !expressionLanguageScope.equals(ExpressionLanguageScope.NONE);
return !expressionLanguageScope.equals(ExpressionLanguageScope.NONE);
}
public ExpressionLanguageScope getExpressionLanguageScope() {
@ -811,11 +786,11 @@ public final class PropertyDescriptor implements Comparable<PropertyDescriptor>
}
// If Expression Language is supported and is used in the property value, we cannot perform validation against the configured
// input unless the Expression Language is expressly limited to only variable registry. In that case, we can evaluate it and then
// validate the value after evaluating the Expression Language.
// input unless the Expression Language is expressly limited to only env/syst properties variables. In that case, we can evaluate
// it and then validate the value after evaluating the Expression Language.
String input = configuredInput;
if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(configuredInput)) {
if (expressionLanguageScope != null && expressionLanguageScope == ExpressionLanguageScope.VARIABLE_REGISTRY) {
if (expressionLanguageScope != null && expressionLanguageScope == ExpressionLanguageScope.ENVIRONMENT) {
input = context.newPropertyValue(configuredInput).evaluateAttributeExpressions().getValue();
resultBuilder.input(input);
} else {

View File

@ -23,7 +23,7 @@ import org.apache.nifi.expression.AttributeValueDecorator;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.DataUnit;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.registry.EnvironmentVariables;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -139,7 +139,7 @@ public interface PropertyValue {
* Replaces values in the Property Value using the NiFi Expression Language;
* a PropertyValue with the new value is then returned, supporting call
* chaining. Before executing the expression language statement any
* variables names found within any underlying {@link VariableRegistry} will
* variables names found within any underlying {@link EnvironmentVariables} will
* be substituted with their values.
* </p>
*
@ -157,12 +157,12 @@ public interface PropertyValue {
* Replaces values in the Property Value using the NiFi Expression Language;
* a PropertyValue with the new value is then returned, supporting call
* chaining. Before executing the expression language statement any
* variables names found within any underlying {@link VariableRegistry} will
* variables names found within any underlying {@link EnvironmentVariables} will
* be substituted with their values.
* </p>
*
* @param attributes a Map of attributes that the Expression can reference.
* These will take precedence over any underlying variable registry values.
* These will take precedence over any underlying env/syst properties values.
*
* @return a PropertyValue with the new value
*
@ -178,7 +178,7 @@ public interface PropertyValue {
* The supplied decorator is then given a chance to decorate the value, and
* a PropertyValue with the new value is then returned, supporting call
* chaining. Before executing the expression language statement any
* variables names found within any underlying {@link VariableRegistry} will
* variables names found within any underlying {@link EnvironmentVariables} will
* be substituted with their values.
* </p>
*
@ -201,13 +201,13 @@ public interface PropertyValue {
* Replaces values in the Property Value using the NiFi Expression Language;
* a PropertyValue with the new value is then returned, supporting call
* chaining. Before executing the expression language statement any
* variables names found within any underlying {@link VariableRegistry} will
* variables names found within any underlying {@link EnvironmentVariables} will
* be substituted with their values.
* </p>
*
* @param flowFile to evaluate attributes of. It's flow file properties and
* then flow file attributes will take precedence over any underlying
* variable registry.
* env/syst properties.
* @return a PropertyValue with the new value is returned, supporting call
* chaining
*
@ -222,17 +222,17 @@ public interface PropertyValue {
* Replaces values in the Property Value using the NiFi Expression Language;
* a PropertyValue with the new value is then returned, supporting call
* chaining. Before executing the expression language statement any
* variables names found within any underlying {@link VariableRegistry} will
* variables names found within any underlying {@link EnvironmentVariables} will
* be substituted with their values.
* </p>
*
* @param flowFile to evaluate attributes of. It's flow file properties and
* then flow file attributes will take precedence over any underlying
* variable registry.
* env/syst properties.
* @param additionalAttributes a Map of additional attributes that the
* Expression can reference. These attributes will take precedence over any
* conflicting attributes in the provided flowfile or any underlying
* variable registry.
* env/syst properties.
*
* @return a PropertyValue with the new value is returned, supporting call
* chaining
@ -248,17 +248,17 @@ public interface PropertyValue {
* Replaces values in the Property Value using the NiFi Expression Language;
* a PropertyValue with the new value is then returned, supporting call
* chaining. Before executing the expression language statement any
* variables names found within any underlying {@link VariableRegistry} will
* variables names found within any underlying {@link EnvironmentVariables} will
* be substituted with their values.
* </p>
*
* @param flowFile to evaluate attributes of. It's flow file properties and
* then flow file attributes will take precedence over any underlying
* variable registry.
* env/syst properties.
* @param additionalAttributes a Map of additional attributes that the
* Expression can reference. These attributes will take precedence over any
* conflicting attributes in the provided flowfile or any underlying
* variable registry.
* env/syst properties.
* @param decorator the decorator to use in order to update the values
* returned after variable substitution and expression language evaluation.
*
@ -300,7 +300,7 @@ public interface PropertyValue {
* The supplied decorator is then given a chance to decorate the value, and
* a PropertyValue with the new value is then returned, supporting call
* chaining. Before executing the expression language statement any
* variables names found within any underlying {@link VariableRegistry} will
* variables names found within any underlying {@link EnvironmentVariables} will
* be substituted with their values.
* </p>
*
@ -321,7 +321,7 @@ public interface PropertyValue {
* The supplied decorator is then given a chance to decorate the value, and
* a PropertyValue with the new value is then returned, supporting call
* chaining. Before executing the expression language statement any
* variables names found within any underlying {@link VariableRegistry} will
* variables names found within any underlying {@link EnvironmentVariables} will
* be substituted with their values.
* </p>
*

View File

@ -18,13 +18,13 @@ package org.apache.nifi.expression;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.registry.EnvironmentVariables;
/**
* Defines a type of expression language statement that can be applied
* parametrized by various attributes and properties as specified in each of
* the method calls. AttributeExpression evaluations may be also backed by a
* {@link VariableRegistry} used to substitute attributes and variables found in
* {@link EnvironmentVariables} used to substitute attributes and variables found in
* the expression for which the registry has a value.
*/
public interface AttributeExpression {

View File

@ -20,20 +20,15 @@ package org.apache.nifi.expression;
* Indicates the scope of expression language on a property descriptor.
*
* Scope of the expression language is hierarchical.
* NONE -> VARIABLE_REGISTRY -> FLOWFILE_ATTRIBUTES
* NONE -> ENVIRONMENT -> FLOWFILE_ATTRIBUTES
*
* When scope is set to FlowFiles attributes, variables are evaluated
* against attributes of each incoming flow file. If no matching attribute
* is found, variable registry will be checked.
* is found, env/syst properties will be checked.
*
* NONE - expression language is not supported
*
* VARIABLE_REGISTRY is hierarchically constructed as below:
* |---- Variables defined at process group level and then, recursively, up
* | to the higher process group until the root process group.
* |--- Variables defined in custom properties files through the
* | nifi.variable.registry.properties property in nifi.properties file.
* |-- Environment variables defined at JVM level and system properties.
* ENVIRONMENT - Environment variables defined at JVM level and system properties.
*
* FLOWFILE_ATTRIBUTES - will check attributes of each individual flow file
*
@ -48,12 +43,12 @@ public enum ExpressionLanguageScope {
/**
* Expression language is evaluated against variables in registry
*/
VARIABLE_REGISTRY("Variable Registry Only"),
ENVIRONMENT("Environment variables defined at JVM level and system properties"),
/**
* Expression language is evaluated per flow file using attributes
*/
FLOWFILE_ATTRIBUTES("Variable Registry and FlowFile Attributes");
FLOWFILE_ATTRIBUTES("Environment variables and FlowFile Attributes");
private String description;

View File

@ -19,9 +19,7 @@ package org.apache.nifi.flow;
import io.swagger.annotations.ApiModelProperty;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class VersionedProcessGroup extends VersionedComponent {
@ -37,8 +35,6 @@ public class VersionedProcessGroup extends VersionedComponent {
private Set<VersionedControllerService> controllerServices = new HashSet<>();
private VersionedFlowCoordinates versionedFlowCoordinates = null;
private Map<String, String> variables = new HashMap<>();
private String parameterContextName;
private String flowfileConcurrency;
private String flowfileOutboundPolicy;
@ -140,15 +136,6 @@ public class VersionedProcessGroup extends VersionedComponent {
return ComponentType.PROCESS_GROUP;
}
public void setVariables(Map<String, String> variables) {
this.variables = variables;
}
@ApiModelProperty("The Variables in the Variable Registry for this Process Group (not including any ancestor or descendant Process Groups)")
public Map<String, String> getVariables() {
return variables;
}
public void setVersionedFlowCoordinates(VersionedFlowCoordinates flowCoordinates) {
this.versionedFlowCoordinates = flowCoordinates;
}

View File

@ -1,24 +0,0 @@
/*
* 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.nifi.registry;
public interface ComponentVariableRegistry extends VariableRegistry {
VariableRegistry getParent();
void setParent(VariableRegistry parentRegistry);
}

View File

@ -26,19 +26,19 @@ import java.util.Map;
* than explicit values which can make configurations of those components more
* portable.
*/
public interface VariableRegistry {
public interface EnvironmentVariables {
/**
* Returns an empty registry which can be used as a more intentional null
* value.
*/
public static final VariableRegistry EMPTY_REGISTRY = () -> Collections.emptyMap();
public static final EnvironmentVariables EMPTY_ENVIRONMENT_VARIABLES = () -> Collections.emptyMap();
/**
* Provides a registry containing all environment variables and system
* properties. System properties receive precedence.
*/
public static final VariableRegistry ENVIRONMENT_SYSTEM_REGISTRY = new VariableRegistry() {
public static final EnvironmentVariables ENVIRONMENT_VARIABLES = new EnvironmentVariables() {
final Map<VariableDescriptor, String> map = new HashMap<>();
{
@ -59,9 +59,8 @@ public interface VariableRegistry {
}
@Override
public Map<VariableDescriptor, String> getVariableMap() {
public Map<VariableDescriptor, String> getEnvironmentVariablesMap() {
return Collections.unmodifiableMap(map);
}
};
@ -74,7 +73,7 @@ public interface VariableRegistry {
* @return An immutable map of all variables in the registry
*/
Map<VariableDescriptor, String> getVariableMap();
Map<VariableDescriptor, String> getEnvironmentVariablesMap();
/**
* Returns the VariableDescriptor for the given key name if it exists.
@ -83,12 +82,12 @@ public interface VariableRegistry {
* @return the variable descriptor registered for this name if it exists;
* null otherwise
*/
default VariableDescriptor getVariableKey(final String name) {
default VariableDescriptor getEnvironmentVariableKey(final String name) {
if (name == null) {
return null;
}
final VariableDescriptor spec = new VariableDescriptor(name);
for (final Map.Entry<VariableDescriptor, String> entry : getVariableMap().entrySet()) {
for (final Map.Entry<VariableDescriptor, String> entry : getEnvironmentVariablesMap().entrySet()) {
if (entry.getKey().equals(spec)) {
return entry.getKey();
}
@ -105,11 +104,11 @@ public interface VariableRegistry {
* @return the value associated with the given variable name if found; null
* otherwise
*/
default String getVariableValue(final String name) {
default String getEnvironmentVariableValue(final String name) {
if (name == null) {
return null;
}
return getVariableMap().get(new VariableDescriptor(name));
return getEnvironmentVariablesMap().get(new VariableDescriptor(name));
}
/**
@ -119,11 +118,11 @@ public interface VariableRegistry {
* @return the variable value if the given descriptor is equivalent to one
* of the entries in the registry; null otherwise
*/
default String getVariableValue(final VariableDescriptor descriptor) {
default String getEnvironmentVariableValue(final VariableDescriptor descriptor) {
if (descriptor == null) {
return null;
}
return getVariableMap().get(descriptor);
return getEnvironmentVariablesMap().get(descriptor);
}
}

View File

@ -149,7 +149,7 @@ public class TestPropertyDescriptor {
final PropertyDescriptor descriptor = new PropertyDescriptor.Builder()
.name("dir")
.identifiesExternalResource(ResourceCardinality.SINGLE, ResourceType.FILE, ResourceType.DIRECTORY)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.build();
@ -167,7 +167,7 @@ public class TestPropertyDescriptor {
return propertyValue;
});
// Should not be valid because Expression Language scope is VARIABLE_REGISTRY, so the ${TestPropertyDescriptor.Var1} will be replaced with
// Should not be valid because Expression Language scope is ENVIRONMENT, so the ${TestPropertyDescriptor.Var1} will be replaced with
// __my_var__, and __my_var__ does not exist.
assertFalse(descriptor.validate("${TestPropertyDescriptor.Var1}", validationContext).isValid());

View File

@ -21,15 +21,15 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
public class TestVariableRegistry {
public class TestEnvironmentVariables {
@Test
public void testSystemProp() {
assertNull(System.getProperty("ALKJAFLKJDFLSKJSDFLKJSDF"));
final VariableRegistry sysEvnReg = VariableRegistry.ENVIRONMENT_SYSTEM_REGISTRY;
final EnvironmentVariables sysEvnReg = EnvironmentVariables.ENVIRONMENT_VARIABLES;
System.setProperty("ALKJAFLKJDFLSKJSDFLKJSDF", "here now");
//should not be in Variable Registry
assertNull(sysEvnReg.getVariableValue("ALKJAFLKJDFLSKJSDFLKJSDF"));
assertNull(sysEvnReg.getEnvironmentVariableValue("ALKJAFLKJDFLSKJSDFLKJSDF"));
//should be in System properties now though...
assertEquals("here now", System.getProperty("ALKJAFLKJDFLSKJSDFLKJSDF"));
@ -38,13 +38,13 @@ public class TestVariableRegistry {
final String vendorUrl = System.getProperty("java.vendor.url");
if (vendorUrl != null) { // we can run this extra test
//var reg value matches system property
assertEquals(vendorUrl, sysEvnReg.getVariableValue("java.vendor.url"));
assertEquals(vendorUrl, sysEvnReg.getEnvironmentVariableValue("java.vendor.url"));
//change system property
System.setProperty("java.vendor.url", "http://fake.vendor.url/");
//changed in system properties
assertEquals("http://fake.vendor.url/", System.getProperty("java.vendor.url"));
//var reg value matches system property still
assertEquals(vendorUrl, sysEvnReg.getVariableValue("java.vendor.url"));
assertEquals(vendorUrl, sysEvnReg.getEnvironmentVariableValue("java.vendor.url"));
//restore to its old value
System.setProperty("java.vendor.url", vendorUrl);
}

View File

@ -30,7 +30,6 @@ import org.apache.nifi.components.resource.ResourceContext;
import org.apache.nifi.components.resource.StandardResourceContext;
import org.apache.nifi.components.resource.StandardResourceReferenceFactory;
import org.apache.nifi.parameter.ParameterLookup;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -63,15 +62,8 @@ public class NotificationServiceManager {
private final ScheduledExecutorService notificationExecutor;
private int maxAttempts = 5;
private final VariableRegistry variableRegistry;
public NotificationServiceManager() {
this(VariableRegistry.ENVIRONMENT_SYSTEM_REGISTRY);
}
NotificationServiceManager(final VariableRegistry variableRegistry){
this.variableRegistry = variableRegistry;
public NotificationServiceManager(){
notificationExecutor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(final Runnable r) {
@ -144,7 +136,7 @@ public class NotificationServiceManager {
}
// Check if the service is valid; if not, warn now so that users know this before they fail to receive notifications
final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config), variableRegistry);
final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config));
final Collection<ValidationResult> validationResults = service.validate(validationContext);
final List<String> invalidReasons = new ArrayList<>();
@ -182,7 +174,7 @@ public class NotificationServiceManager {
@Override
public void run() {
// Check if the service is valid; if not, warn now so that users know this before they fail to receive notifications
final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config), variableRegistry);
final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config));
final Collection<ValidationResult> validationResults = service.validate(validationContext);
final List<String> invalidReasons = new ArrayList<>();
@ -251,7 +243,7 @@ public class NotificationServiceManager {
}
final ResourceContext resourceContext = new StandardResourceContext(new StandardResourceReferenceFactory(), descriptor);
return new StandardPropertyValue(resourceContext, configuredValue, null, ParameterLookup.EMPTY, variableRegistry);
return new StandardPropertyValue(resourceContext, configuredValue, null, ParameterLookup.EMPTY);
}
@Override
@ -372,7 +364,7 @@ public class NotificationServiceManager {
}
final ResourceContext resourceContext = new StandardResourceContext(new StandardResourceReferenceFactory(), descriptor);
return new StandardPropertyValue(resourceContext, value, null, ParameterLookup.EMPTY, variableRegistry);
return new StandardPropertyValue(resourceContext, value, null, ParameterLookup.EMPTY);
}
@Override

View File

@ -30,7 +30,6 @@ import org.apache.nifi.components.ValidationContext;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.controller.ControllerServiceLookup;
import org.apache.nifi.expression.ExpressionLanguageCompiler;
import org.apache.nifi.registry.VariableRegistry;
import java.util.Collection;
import java.util.Collections;
@ -43,9 +42,8 @@ import java.util.function.Function;
public class NotificationValidationContext implements ValidationContext {
private final NotificationContext context;
private final Map<String, Boolean> expressionLanguageSupported;
private final VariableRegistry variableRegistry;
public NotificationValidationContext(final NotificationContext processContext, VariableRegistry variableRegistry) {
public NotificationValidationContext(final NotificationContext processContext) {
this.context = processContext;
final Map<PropertyDescriptor, String> properties = processContext.getProperties();
@ -53,20 +51,19 @@ public class NotificationValidationContext implements ValidationContext {
for (final PropertyDescriptor descriptor : properties.keySet()) {
expressionLanguageSupported.put(descriptor.getName(), descriptor.isExpressionLanguageSupported());
}
this.variableRegistry = variableRegistry;
}
@Override
public PropertyValue newPropertyValue(final String rawValue) {
final ResourceContext resourceContext = new StandardResourceContext(new StandardResourceReferenceFactory(), null);
return new StandardPropertyValue(resourceContext, rawValue, null, ParameterLookup.EMPTY, variableRegistry);
return new StandardPropertyValue(resourceContext, rawValue, null, ParameterLookup.EMPTY);
}
@Override
public ExpressionLanguageCompiler newExpressionLanguageCompiler() {
return new StandardExpressionLanguageCompiler(null, ParameterLookup.EMPTY);
return new StandardExpressionLanguageCompiler(ParameterLookup.EMPTY);
}
@Override

View File

@ -59,20 +59,20 @@ public class EmailNotificationService extends AbstractNotificationService {
.description("The Port used for SMTP communications")
.required(true)
.defaultValue("25")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.PORT_VALIDATOR)
.build();
public static final PropertyDescriptor SMTP_USERNAME = new PropertyDescriptor.Builder()
.name("SMTP Username")
.description("Username for the SMTP account")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.required(false)
.build();
public static final PropertyDescriptor SMTP_PASSWORD = new PropertyDescriptor.Builder()
.name("SMTP Password")
.description("Password for the SMTP account")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.required(false)
.sensitive(true)
@ -81,7 +81,7 @@ public class EmailNotificationService extends AbstractNotificationService {
.name("SMTP Auth")
.description("Flag indicating whether authentication should be used")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.BOOLEAN_VALIDATOR)
.defaultValue("true")
.build();
@ -89,7 +89,7 @@ public class EmailNotificationService extends AbstractNotificationService {
.name("SMTP TLS")
.description("Flag indicating whether TLS should be enabled")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.BOOLEAN_VALIDATOR)
.defaultValue("false")
.build();
@ -97,7 +97,7 @@ public class EmailNotificationService extends AbstractNotificationService {
.name("SMTP Socket Factory")
.description("Socket Factory to use for SMTP Connection")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.defaultValue("javax.net.ssl.SSLSocketFactory")
.build();
@ -105,7 +105,7 @@ public class EmailNotificationService extends AbstractNotificationService {
.name("SMTP X-Mailer Header")
.description("X-Mailer used in the header of the outgoing email")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.defaultValue("NiFi")
.build();
@ -113,7 +113,7 @@ public class EmailNotificationService extends AbstractNotificationService {
.name("Content Type")
.description("Mime Type used to interpret the contents of the email, such as text/plain or text/html")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.defaultValue("text/plain")
.build();
@ -121,28 +121,28 @@ public class EmailNotificationService extends AbstractNotificationService {
.name("From")
.description("Specifies the Email address to use as the sender")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
public static final PropertyDescriptor TO = new PropertyDescriptor.Builder()
.name("To")
.description("The recipients to include in the To-Line of the email")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
public static final PropertyDescriptor CC = new PropertyDescriptor.Builder()
.name("CC")
.description("The recipients to include in the CC-Line of the email")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
public static final PropertyDescriptor BCC = new PropertyDescriptor.Builder()
.name("BCC")
.description("The recipients to include in the BCC-Line of the email")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();

View File

@ -57,21 +57,21 @@ public class HttpNotificationService extends AbstractNotificationService {
.name("URL")
.description("The URL to send the notification to.")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.URL_VALIDATOR)
.build();
public static final PropertyDescriptor PROP_CONNECTION_TIMEOUT = new PropertyDescriptor.Builder()
.name("Connection timeout")
.description("Max wait time for connection to remote service.")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.TIME_PERIOD_VALIDATOR)
.defaultValue("10s")
.build();
public static final PropertyDescriptor PROP_WRITE_TIMEOUT = new PropertyDescriptor.Builder()
.name("Write timeout")
.description("Max wait time for remote service to read the request sent.")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.TIME_PERIOD_VALIDATOR)
.defaultValue("10s")
.build();
@ -167,7 +167,7 @@ public class HttpNotificationService extends AbstractNotificationService {
.name(propertyDescriptorName)
.addValidator(StandardValidators.createAttributeExpressionLanguageValidator(AttributeExpression.ResultType.STRING, true))
.dynamic(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.build();
}

View File

@ -21,20 +21,17 @@ import org.apache.nifi.expression.AttributeValueDecorator;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.parameter.ParameterLookup;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.registry.VariableRegistry;
import java.util.Collections;
public class StandardAttributeExpression implements AttributeExpression {
private final Query query;
private final VariableRegistry variableRegistry;
private final ParameterLookup parameterLookup;
public StandardAttributeExpression(final Query query, final VariableRegistry variableRegistry, final ParameterLookup parameterLookup) {
public StandardAttributeExpression(final Query query, final ParameterLookup parameterLookup) {
this.query = query;
this.variableRegistry = variableRegistry;
this.parameterLookup = parameterLookup;
}
@ -60,7 +57,7 @@ public class StandardAttributeExpression implements AttributeExpression {
@Override
public String evaluate(final FlowFile flowFile, final AttributeValueDecorator decorator) throws ProcessException {
final ValueLookup lookup = new ValueLookup(variableRegistry, flowFile);
final ValueLookup lookup = new ValueLookup(flowFile);
final EvaluationContext evaluationContext = new StandardEvaluationContext(lookup, Collections.emptyMap(), parameterLookup);
final Object evaluationResult = query.evaluate(evaluationContext).getValue();

View File

@ -19,7 +19,6 @@ package org.apache.nifi.attribute.expression.language;
import org.apache.nifi.attribute.expression.language.evaluation.EvaluatorState;
import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterLookup;
import org.apache.nifi.registry.VariableRegistry;
import java.util.Map;
import java.util.Set;
@ -35,7 +34,7 @@ public class StandardEvaluationContext implements EvaluationContext {
}
public StandardEvaluationContext(final Map<String, String> variables, final Map<String, String> stateMap, final ParameterLookup parameterLookup) {
this(new ValueLookup(VariableRegistry.ENVIRONMENT_SYSTEM_REGISTRY, null, variables), stateMap, parameterLookup);
this(new ValueLookup(null, variables), stateMap, parameterLookup);
}
public StandardEvaluationContext(final ValueLookup valueLookup, final Map<String, String> stateMap, final ParameterLookup parameterLookup) {

View File

@ -21,22 +21,19 @@ import org.apache.nifi.expression.AttributeExpression;
import org.apache.nifi.expression.AttributeExpression.ResultType;
import org.apache.nifi.expression.ExpressionLanguageCompiler;
import org.apache.nifi.parameter.ParameterLookup;
import org.apache.nifi.registry.VariableRegistry;
public class StandardExpressionLanguageCompiler implements ExpressionLanguageCompiler {
private final VariableRegistry variableRegistry;
private final ParameterLookup parameterLookup;
public StandardExpressionLanguageCompiler(final VariableRegistry variableRegistry, final ParameterLookup parameterLookup) {
this.variableRegistry = variableRegistry;
public StandardExpressionLanguageCompiler(final ParameterLookup parameterLookup) {
this.parameterLookup = parameterLookup;
}
@Override
public AttributeExpression compile(final String expression) throws IllegalArgumentException {
try {
return new StandardAttributeExpression(Query.compile(expression), variableRegistry, parameterLookup);
return new StandardAttributeExpression(Query.compile(expression), parameterLookup);
} catch (final AttributeExpressionLanguageParsingException e) {
throw new IllegalArgumentException(e.getMessage());
}

View File

@ -30,7 +30,7 @@ import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.parameter.ParameterLookup;
import org.apache.nifi.processor.DataUnit;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.registry.EnvironmentVariables;
import org.apache.nifi.util.FormatUtils;
import java.util.Map;
@ -41,7 +41,6 @@ public class StandardPropertyValue implements PropertyValue {
private final String rawValue;
private final ControllerServiceLookup serviceLookup;
private final PreparedQuery preparedQuery;
private final VariableRegistry variableRegistry;
private final ParameterLookup parameterLookup;
private final ResourceContext resourceContext;
@ -51,12 +50,7 @@ public class StandardPropertyValue implements PropertyValue {
}
public StandardPropertyValue(final ResourceContext resourceContext, final String rawValue, final ControllerServiceLookup serviceLookup, final ParameterLookup parameterLookup) {
this(resourceContext, rawValue, serviceLookup, parameterLookup, Query.prepare(rawValue), VariableRegistry.EMPTY_REGISTRY);
}
public StandardPropertyValue(final ResourceContext resourceContext, final String rawValue, final ControllerServiceLookup serviceLookup, final ParameterLookup parameterLookup,
final VariableRegistry variableRegistry) {
this(resourceContext, rawValue, serviceLookup, parameterLookup, Query.prepare(rawValue), variableRegistry);
this(resourceContext, rawValue, serviceLookup, parameterLookup, Query.prepare(rawValue));
}
/**
@ -64,7 +58,7 @@ public class StandardPropertyValue implements PropertyValue {
* lookup and indicates whether or not the rawValue contains any NiFi
* Expressions. If it is unknown whether or not the value contains any NiFi
* Expressions, the
* {@link #StandardPropertyValue(ResourceContext, String, ControllerServiceLookup, ParameterLookup, VariableRegistry)}
* {@link #StandardPropertyValue(ResourceContext, String, ControllerServiceLookup, ParameterLookup, EnvironmentVariables)}
* constructor should be used or <code>true</code> should be passed.
* However, if it is known that the value contains no NiFi Expression, that
* information should be provided so that calls to
@ -75,14 +69,12 @@ public class StandardPropertyValue implements PropertyValue {
* @param serviceLookup lookup
* @param parameterLookup the parameter lookup
* @param preparedQuery query
* @param variableRegistry variableRegistry
*/
public StandardPropertyValue(final ResourceContext resourceContext, final String rawValue, final ControllerServiceLookup serviceLookup, final ParameterLookup parameterLookup,
final PreparedQuery preparedQuery, final VariableRegistry variableRegistry) {
final PreparedQuery preparedQuery) {
this.rawValue = rawValue;
this.serviceLookup = serviceLookup;
this.preparedQuery = preparedQuery;
this.variableRegistry = variableRegistry;
this.parameterLookup = parameterLookup == null ? ParameterLookup.EMPTY : parameterLookup;
this.resourceContext = resourceContext;
}
@ -175,11 +167,11 @@ public class StandardPropertyValue implements PropertyValue {
return this;
}
final ValueLookup lookup = new ValueLookup(variableRegistry, flowFile, additionalAttributes);
final ValueLookup lookup = new ValueLookup(flowFile, additionalAttributes);
final EvaluationContext evaluationContext = new StandardEvaluationContext(lookup, stateValues, parameterLookup);
final String evaluated = preparedQuery.evaluateExpressions(evaluationContext, decorator);
return new StandardPropertyValue(resourceContext, evaluated, serviceLookup, parameterLookup, new EmptyPreparedQuery(evaluated), null);
return new StandardPropertyValue(resourceContext, evaluated, serviceLookup, parameterLookup, new EmptyPreparedQuery(evaluated));
}
@Override

View File

@ -18,7 +18,7 @@ package org.apache.nifi.attribute.expression.language;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.registry.VariableDescriptor;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.registry.EnvironmentVariables;
import java.util.ArrayList;
import java.util.Collection;
@ -32,26 +32,26 @@ import java.util.Set;
/**
* A convenience class to encapsulate the logic of variable substitution
* based first on any additional variable maps, then flow file properties,
* then flow file attributes, and finally the provided variable registry.
* then flow file attributes, and finally the provided system and env
* variable registry.
*/
final class ValueLookup implements Map<String, String> {
private final List<Map<String, String>> maps = new ArrayList<>();
private final VariableRegistry registry;
private final EnvironmentVariables environmentVariables = EnvironmentVariables.ENVIRONMENT_VARIABLES;
/**
* Constructs a ValueLookup where values are looked up first based any
* provided additional maps, then flowfile properties, then flowfile
* attributes, then based on the provided variable registry. The lookup is
* immutable and operations which attempt to alter state will throw
* UnsupportedOperationException
* attributes, then based on the provided system and env variable
* registry. The lookup is immutable and operations which attempt to
* alter state will throw UnsupportedOperationException
*
* @param registry the variable registry to lookup from; may be null
* @param flowFile the flowFile to pull attributes from; may be null
* @param additionalMaps the maps to pull values from; may be null or empty
*/
@SuppressWarnings("unchecked")
ValueLookup(final VariableRegistry registry, final FlowFile flowFile, final Map<String, String>... additionalMaps) {
ValueLookup(final FlowFile flowFile, final Map<String, String>... additionalMaps) {
for (final Map<String, String> map : additionalMaps) {
if (map != null && !map.isEmpty()) {
maps.add(map);
@ -62,8 +62,6 @@ final class ValueLookup implements Map<String, String> {
maps.add(ValueLookup.extractFlowFileProperties(flowFile));
maps.add(flowFile.getAttributes());
}
this.registry = registry == null ? VariableRegistry.EMPTY_REGISTRY : registry;
}
static final Map<String, String> extractFlowFileProperties(final FlowFile flowFile) {
@ -89,7 +87,7 @@ final class ValueLookup implements Map<String, String> {
return false;
}
}
return registry.getVariableMap().isEmpty();
return environmentVariables.getEnvironmentVariablesMap().isEmpty();
}
@Override
@ -100,7 +98,7 @@ final class ValueLookup implements Map<String, String> {
if (maps.stream().anyMatch((map) -> (map.containsKey(key)))) {
return true;
}
return registry.getVariableKey(key.toString()) != null;
return environmentVariables.getEnvironmentVariableKey(key.toString()) != null;
}
@Override
@ -125,7 +123,7 @@ final class ValueLookup implements Map<String, String> {
return val;
}
}
return registry.getVariableValue(key.toString());
return environmentVariables.getEnvironmentVariableValue(key.toString());
}
@Override
@ -177,8 +175,8 @@ final class ValueLookup implements Map<String, String> {
@Override
public Set<Entry<String, String>> entrySet() {
final Map<String, String> newMap = new HashMap<>();
//put variable registry entries first
for (final Map.Entry<VariableDescriptor, String> entry : registry.getVariableMap().entrySet()) {
//put syst/env variable registry entries first
for (final Map.Entry<VariableDescriptor, String> entry : environmentVariables.getEnvironmentVariablesMap().entrySet()) {
newMap.put(entry.getKey().getName(), entry.getValue());
}
//put attribute maps in reverse order

View File

@ -28,7 +28,6 @@ import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterDescriptor;
import org.apache.nifi.parameter.ParameterLookup;
import org.apache.nifi.registry.VariableRegistry;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -740,7 +739,7 @@ public class TestQuery {
when(mockFlowFile.getSize()).thenReturn(1L);
when(mockFlowFile.getLineageStartDate()).thenReturn(System.currentTimeMillis());
final ValueLookup lookup = new ValueLookup(VariableRegistry.EMPTY_REGISTRY, mockFlowFile);
final ValueLookup lookup = new ValueLookup(mockFlowFile);
return Query.evaluateExpressions(queryString, lookup, ParameterLookup.EMPTY);
}

View File

@ -17,7 +17,6 @@
package org.apache.nifi.attribute.expression.language;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.registry.VariableRegistry;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
@ -33,8 +32,7 @@ public class TestValueLookup {
@SuppressWarnings("unchecked")
public void testCreateCustomVariableRegistry() {
final VariableRegistry variableRegistry = VariableRegistry.ENVIRONMENT_SYSTEM_REGISTRY;
final ValueLookup initialLookup = new ValueLookup(variableRegistry, null);
final ValueLookup initialLookup = new ValueLookup(null);
assertTrue(initialLookup.containsKey("PATH"));
assertFalse(initialLookup.containsKey("fake.property.3"));
assertFalse(initialLookup.containsKey("fake"));
@ -42,7 +40,7 @@ public class TestValueLookup {
final Map<String, String> otherAttrs = new HashMap<>();
otherAttrs.put("fake", "test");
otherAttrs.put("fake.property.3", "test me out 3, test me out 4");
final ValueLookup newLookup = new ValueLookup(variableRegistry, null, otherAttrs);
final ValueLookup newLookup = new ValueLookup(null, otherAttrs);
assertTrue(newLookup.containsKey("PATH"));
assertTrue(newLookup.containsKey("fake.property.3"));
assertEquals("test me out 3, test me out 4", newLookup.get("fake.property.3"));
@ -50,7 +48,7 @@ public class TestValueLookup {
assertFalse(newLookup.containsKey("filename"));
final FlowFile fakeFile = createFlowFile();
final ValueLookup ffLookup = new ValueLookup(variableRegistry, fakeFile, otherAttrs);
final ValueLookup ffLookup = new ValueLookup(fakeFile, otherAttrs);
assertTrue(ffLookup.containsKey("filename"));
assertEquals("test", ffLookup.get("fake"));
assertEquals("1", ffLookup.get("flowFileId"));
@ -61,7 +59,7 @@ public class TestValueLookup {
final Map<String, String> overrides = new HashMap<>();
overrides.put("fake", "the real deal");
final ValueLookup overriddenLookup = new ValueLookup(variableRegistry, fakeFile, overrides, otherAttrs);
final ValueLookup overriddenLookup = new ValueLookup(fakeFile, overrides, otherAttrs);
assertTrue(overriddenLookup.containsKey("filename"));
assertEquals("the real deal", overriddenLookup.get("fake"));
assertEquals("1", overriddenLookup.get("flowFileId"));
@ -74,7 +72,7 @@ public class TestValueLookup {
final Map<String, String> newOverrides = new HashMap<>();
newOverrides.put("fake", "the real deal");
newOverrides.put("override me", "done you are now overridden");
final ValueLookup newOverriddenLookup = new ValueLookup(variableRegistry, fakeFile, newOverrides, otherAttrs);
final ValueLookup newOverriddenLookup = new ValueLookup(fakeFile, newOverrides, otherAttrs);
assertTrue(newOverriddenLookup.containsKey("filename"));
assertEquals("the real deal", newOverriddenLookup.get("fake"));
assertEquals("1", newOverriddenLookup.get("flowFileId"));

View File

@ -292,9 +292,6 @@ public class NiFiProperties extends ApplicationProperties {
public static final String STATE_MANAGEMENT_START_EMBEDDED_ZOOKEEPER = "nifi.state.management.embedded.zookeeper.start";
public static final String STATE_MANAGEMENT_ZOOKEEPER_PROPERTIES = "nifi.state.management.embedded.zookeeper.properties";
// expression language properties
public static final String VARIABLE_REGISTRY_PROPERTIES = "nifi.variable.registry.properties";
// analytics properties
public static final String ANALYTICS_PREDICTION_ENABLED = "nifi.analytics.predict.enabled";
public static final String ANALYTICS_PREDICTION_INTERVAL = "nifi.analytics.predict.interval";
@ -1626,28 +1623,6 @@ public class NiFiProperties extends ApplicationProperties {
return getIntegerProperty(FLOW_CONFIGURATION_ARCHIVE_MAX_COUNT, null);
}
public String getVariableRegistryProperties() {
return getProperty(VARIABLE_REGISTRY_PROPERTIES);
}
public Path[] getVariableRegistryPropertiesPaths() {
final List<Path> vrPropertiesPaths = new ArrayList<>();
final String vrPropertiesFiles = getVariableRegistryProperties();
if (!StringUtils.isEmpty(vrPropertiesFiles)) {
final String[] vrPropertiesFileList = vrPropertiesFiles.split(",");
for (String propertiesFile : vrPropertiesFileList) {
vrPropertiesPaths.add(Paths.get(propertiesFile));
}
return vrPropertiesPaths.toArray(new Path[vrPropertiesPaths.size()]);
} else {
return new Path[]{};
}
}
/**
* Returns the network interface list to use for HTTP. This method returns a mapping of
* network interface property names to network interface names.

View File

@ -349,7 +349,7 @@ public class StandardValidators {
};
/**
* This validator will evaluate an expression using ONLY environment and variable registry properties,
* This validator will evaluate an expression using ONLY environment properties,
* then validate that the result is a supported character set.
*/
public static final Validator CHARACTER_SET_VALIDATOR_WITH_EVALUATION = new Validator() {

View File

@ -220,8 +220,6 @@ can be published to the host.
| Remote Input Socket Port | nifi.remote.input.socket.port | 10000 |
| JVM Debugger | java.arg.debug | 8000 |
The Variable Registry can be configured for the docker image using the `NIFI_VARIABLE_REGISTRY_PROPERTIES` environment variable.
The JVM Memory initial and maximum heap size can be set using the `NIFI_JVM_HEAP_INIT` and `NIFI_JVM_HEAP_MAX` environment variables. These use values acceptable to the JVM `Xmx` and `Xms` parameters such as `1g` or `512m`.
The JVM Debugger can be enabled by setting the environment variable NIFI_JVM_DEBUGGER to any value.

View File

@ -78,7 +78,6 @@ else
fi
fi
prop_replace 'nifi.variable.registry.properties' "${NIFI_VARIABLE_REGISTRY_PROPERTIES:-}"
prop_replace 'nifi.cluster.is.node' "${NIFI_CLUSTER_IS_NODE:-false}"
prop_replace 'nifi.cluster.node.address' "${NIFI_CLUSTER_ADDRESS:-$HOSTNAME}"
prop_replace 'nifi.cluster.node.protocol.port' "${NIFI_CLUSTER_NODE_PROTOCOL_PORT:-}"

View File

@ -4276,25 +4276,6 @@ As a result, if we set the value of this property higher, up to a value of `100`
In order to view these metrics, we can gather diagnostics by running the command `nifi.sh diagnostics <filename>` and inspecting the generated file. See <<nifi_diagnostics>> for more information.
[[custom_properties]]
=== Custom Properties
To configure custom properties for use with NiFis Expression Language:
* Create the custom property. Ensure that:
** Each custom property contains a distinct property value, so that it is not overridden by existing environment properties, system properties, or FlowFile attributes.
** Each node in a clustered environment is configured with the same custom properties.
* Update `nifi.variable.registry.properties` with the location of the custom property file(s):
|====
|*Property*|*Description*
|`nifi.variable.registry.properties`|This is a comma-separated list of file location paths for one or more custom property files.
|====
* Restart your NiFi instance(s) for the updates to be picked up.
Custom properties can also be configured in the NiFi UI. See the <<user-guide.adoc#Variables_Window,Variables Window>> section in the User Guide for more information.
[[nar_provider_properties]]
=== NAR Provider Properties

View File

@ -138,10 +138,8 @@ will search for the value.
The current hierarchy in NiFi is as follows:
1. Search FlowFile for attribute/key
2. Search Process Group Variables for attribute/key
3. Search File Registry file for attribute/key
4. Search NiFi JVM Properties for attribute/key
5. Search System Environment Variables for attribute/key
2. Search NiFi JVM Properties for attribute/key
3. Search System Environment Variables for attribute/key
NiFi will search for, and return, the first occurrence of a matching property. If no matching property is found, `null` is returned.
@ -161,17 +159,12 @@ image:iconInfo.png["Info"]
provides helpful information about the Property. This information includes a description of the Property,
the default value (if any), historically configured values (if any), and the evaluation scope of this
property for expression language. There are three values and the evaluation scope of the expression
language is hierarchical: NONE -> VARIABLE_REGISTRY -> FLOWFILE_ATTRIBUTES.
language is hierarchical: NONE -> ENVIRONMENT -> FLOWFILE_ATTRIBUTES.
* NONE - expression language is not supported for this property
* VARIABLE_REGISTRY is hierarchically constructed as below:
** Variables defined at process group level and then, recursively, up to the higher process group until
the root process group.
** Variables defined in custom properties files through the nifi.variable.registry.properties property
in nifi.properties file.
** Environment variables defined at JVM level and system properties.
* ENVIRONMENT - will use environment variables defined at JVM level and system properties.
* FLOWFILE_ATTRIBUTES - will use attributes of each individual flow file, as well as those variables defined
by the Variable Registry, as described above.
by the Environment, as described above.
[[escaping]]
=== Escaping Expression Language

View File

@ -588,11 +588,6 @@ cause a tooltip to show, which explains what the function does, the arguments th
== Custom Properties Within Expression Language
In addition to using FlowFile attributes, you can also define custom properties for Expression Language use. Defining custom properties gives you additional flexibility in processing and configuring dataflows. For example, you can refer to custom properties for connection, server, and service properties. Once you have created custom properties, you can identify their location in the `nifi.variable.registry.properties` field in the 'nifi.properties' file. After you have updated the 'nifi.properties' file and restarted NiFi, you are able to use custom properties as needed.
== Monitoring NiFi
As data flows through your dataflow in NiFi, it is important to understand how well your system is performing in order to assess if you

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

View File

@ -362,7 +362,6 @@ image::nifi-process-group-menu.png["Process Group Menu"]
While the options available from the context menu vary, the following options are typically available when you have full privileges to work with the Process Group:
- *Configure*: This option allows the user to establish or change the configuration of the Process Group.
- *Variables*: This option allows the user to create or configure variables within the NiFi UI.
- *Enter group*: This option allows the user to enter the Process Group.
NOTE: It is also possible to double-click on the Process Group to enter it.
@ -882,8 +881,6 @@ The UI indicates whether a Parameter can be used for a property value.
image::el-param-support-help-text.png[Expression Language and Parameters Help Text]
NOTE: Parameters have numerous advantages over <<Variables>>. In addition to sensitive value support, Parameters offer more granular control over access policies. Additionally, properties that reference Parameters are validated against the substituted value, unlike most properties that reference Variables using Expression Language.
[[parameter-contexts]]
==== Parameter Contexts
Parameters are created within Parameter Contexts. Parameter Contexts are globally defined/accessible to the NiFi instance. Access policies can be applied to Parameter Contexts to determine which users can create them. Once created, policies to read and write to a specific Parameter Context can also be applied (see <<accessing-parameters>> for more information).
@ -953,7 +950,7 @@ is `test.txt`. If each of those Properties is set to `#{File}`, then the follow
| Configured Property Value | Expression Language Scope | Effective Property Value | Notes
| #{File} | FlowFile Attributes | test.txt | The filename is resolved by looking at the `filename` attribute.
| #{File} | Variable Registry Only | _Empty String_ | FlowFile attributes are not in scope, and we assume there is no Variable in the Variable Registry named "filename"
| #{File} | Environment | _Empty String_ | FlowFile attributes are not in scope, and we assume there is no system property nor environment variable defined at JVM level named "filename"
| #{File} | None | ${filename} | The literal text "${filename}" will be unevaluated.
|===
@ -1139,127 +1136,7 @@ NiFi properties have resolution precedence of which you should be aware when cre
* Processor-specific attributes
* FlowFile properties
* FlowFile attributes
* From Variable Registry:
** User defined properties (custom properties)
** System properties
** Operating System environment variables
When you are creating custom properties, ensure that each custom property contains a distinct property value, so that it is not overridden by existing environment properties, system properties, or FlowFile attributes.
There are two ways to use and manage custom properties with Expression Language:
- *Variables*: Variables are created and configured within the NiFi UI. They can be used in any field that supports Expression Language. Variables cannot be used for sensitive properties. NiFi automatically picks up new or modified variables. Variables are defined at the Process Group level, as a result, the access policies for viewing and changing variables are derived from the access policies of the Process Group. See <<Variables>> for more information.
- *Custom Properties File*: Key/value pairs are defined in a custom properties file that is referenced via the `nifi.variable.registry.properties` in _nifi.properties_. NiFi must be restarted for updates to be picked up. See <<Custom_Properties>> for more information.
WARNING: Custom properties via Variables and the _nifi.properties_ file are still supported for compatibility purposes but do not have the same power as Parameters such as support for sensitive properties and more granular control over who can create, modify or use them. Variables and the `nifi.variable.registry.properties` property will be removed in a future release. As a result, it is highly recommended to switch to Parameters.
Expression Language support for a property is indicated in the UI.
image::el-support-help-text.png[Expression Language Help Text]
[[Variables]]
==== Variables
WARNING: Custom properties via Variables and the _nifi.properties_ file are still supported for compatibility purposes but do not have the same power as Parameters such as support for sensitive properties and more granular control over who can create, modify or use them. Variables and the `nifi.variable.registry.properties` property will be removed in a future release. As a result, it is highly recommended to switch to Parameters.
Variables are created and configured within the NiFi UI. They can be used in any field that supports Expression Language. Variables cannot be used for sensitive properties. Variables are defined at the Process Group level, as a result, the access policies for viewing and changing variables are derived from the access policies of the Process Group. Variable values cannot reference other variables or make use of Expression Language.
===== Variables Window
To access the Variables window, right-click on the canvas with nothing selected:
image::variables-context_menu-rpg.png["Variables in Context Menu for RPG"]
Select "Variables" from the Context Menu:
image::variables_window_empty.png["Empty Variables Window"]
"Variables" is also available in the right-click Context Menu when a process group is selected:
image::variables-context_menu-pg.png["Variables in Context Menu for PG"]
===== Creating a Variable
In the Variables window, click the `+` button to create a new variable. Add a name:
image::variable-name.png["Variable Name Creation"]
and a value:
image::variable-value.png["Variable Value Creation"]
Select "Apply":
image::new_variable-apply.png["New Variable Applied"]
Steps to update the variable are performed (Identifying components affected, Stopping affected Processors, etc.). For example, the Referencing Processors section now lists the "PutFile-Root" processor. Selecting the name of the processor in the list will navigate to that processor on the canvas. Looking at the properties of the processor, `${putfile_dir}` is referenced by the Directory property:
image::variable-putfile-property.png["Processor Property Using Variable"]
===== Variable Scope
Variables are scoped by the Process Group they are defined in and are available to any Processor defined at that level and below (i.e., any descendant Processors).
Variables in a descendant group override the value in a parent group. More specifically, if a variable `x` is declared at the root group and also declared inside a process group, components inside the process group will use the value of `x` defined in the process group.
For example, in addition to the `putfile_dir` variable that exists at the root process group, assume another `putfile_dir` variable was created within Process Group A. If one of the components within Process Group A references `putfile_dir`, both variables will be listed, but the `putfile_dir` from the root group will have a strikethrough indicating that is is being overridden:
image::variable-overridden.png["Variable Overridden"]
A variable can only be modified for the process group it was created in, which is listed at the top of the Variables window. To modify a variable defined in a different process group, select the "arrow" icon in that variable's row:
image::variable_window-goto.png["Variable Go To"]
which will navigate to the Variables window for that process group:
image::variable_window-rpg.png["Variables Window for RPG"]
===== Variable Permissions
Variable permissions are based solely on the privileges configured on the corresponding Process Group.
For example, if a user does not have access to View a process group, the Variables window can not be viewed for that process group:
image::variable_insufficient-permissions.png["Insufficient Permissions to View Variables"]
If a user has access to View a process group but does not have access to Modify the process group, the variables can be viewed but not modified.
For information on how to manage privileges on components, see the <<administration-guide.adoc#access-policies,Access Policies>> section in the System Administrator's Guide.
===== Referencing Controller Services
In addition to Referencing Processors, the Variables window also displays Referencing Controller Services:
image::variables-window_controller-services.png["Referencing Controller Services"]
Selecting the name of the controller service will navigate to that controller service in the Configuration window:
image::variable_nav-controller_services.png["Controller Service Using Variable"]
===== Unauthorized Referencing Components
When View or Modify privileges are not given to a component that references a variable, the UUID of the component will be displayed in the Variables window:
image::variables-window_unauthorized.png["Unauthorized Referencing Components"]
In the above example, the variable `property1` is referenced by a processor that "user1" is not able to view:
image::variable-unauthorized-ref-processor-canvas.png["Unauthorized Referencing Processor"]
[[Custom_Properties]]
==== Referencing Custom Properties via nifi.properties
WARNING: Custom properties via Variables and the _nifi.properties_ file are still supported for compatibility purposes but do not have the same power as Parameters such as support for sensitive properties and more granular control over who can create, modify or use them. Variables and the `nifi.variable.registry.properties` property will be removed in a future release. As a result, it is highly recommended to switch to Parameters.
Identify one or more sets of key/value pairs, and give them to your system administrator.
Once the new custom properties have been added, ensure that the `nifi.variable.registry.properties`
field in the _nifi.properties_ file is updated with the custom properties location.
NOTE: NiFi must be restarted for these updates to be picked up.
For more information, see the <<administration-guide.adoc#custom_properties,Custom Properties>> section in the System Administrator's Guide.
* Environment (System properties and Operating System environment variables)
[[Controller_Services]]
@ -2778,14 +2655,9 @@ The following actions are not considered local changes:
* modifying remote process group URLs
* updating a processor that was referencing a non-existent controller service to reference an externally available controller service
* assigning, creating, modifying or deleting parameter contexts
* creating, modifying or deleting variables
NOTE: Assigning or creating a parameter context does not trigger a local change because assigning or creating a parameter context on its own has not changed anything about what the flow processes. A component will have to be created or modified that uses a parameter in the parameter context, which will trigger a local change. Modifying a parameter context does not trigger a local change because parameters are intended to be different in each environment. When a versioned flow is imported, it is assumed there is a one-time operation required to set those parameters specific for the given environment. Deleting a parameter context does not trigger a local change because any components that reference parameters in that parameter context will need need to be modified, which will trigger a local change.
NOTE: Creating a variable does not trigger a local change because creating a variable on its own has not changed anything about what the flow processes. A component will have to be created or modified that uses the new variable, which will trigger a local change. Modifying a variable does not trigger a local change because variable values are intended to be different in each environment. When a versioned flow is imported, it is assumed there is a one-time operation required to set those variables specific for the given environment. Deleting a variable does not trigger a local change because the component that references that variable will need need to be modified, which will trigger a local change.
WARNING: Variables do not support sensitive values and will be included when versioning a Process Group. Variables are still supported for compatibility purposes but do not have the same power as Parameters such as support for sensitive properties and more granular control over who can create, modify or use them. Variables will be removed in a future release. As a result, it is highly recommended to switch to Parameters.
==== Show Local Changes
The local changes made to a versioned process group can be viewed in the Show Local Changes dialog by selecting "Version->Show local changes" from the context menu.
@ -2878,40 +2750,6 @@ Version 1 of a flow does not have a Parameter Context associated with it. A new
- An existing Parameter Context is assigned (by name) to the Process Group and the values of the Parameter Contexts are merged
[[Variables_in_Versioned_Flows]]
=== Variables in Versioned Flows
Variables are included when a process group is placed under version control. If a versioned flow is imported that references a variable not defined in the versioned process group, the reference is maintained if the variable exists. If the referenced variable does not exist, a copy of the variable will be defined in the process group. To illustrate, assume the variable “RPG_Var" is defined in the root process group:
image::rpg-variable.png["Root Process Group Defined Variable"]
A process group PG1 is created:
image::PG1_process_group.png["PG1 Process Group"]
The GetFile processor in PG1 references the variable "RPG_Var":
image::PG1_variable_ref_1.png["PG1 References RPG Variable"]
PG1 is saved as a versioned flow:
image::PG1_versioned_flow.png["PG1 Versioned Flow"]
If PG1 versioned flow is imported into this same NiFi instance:
image::PG1_imported_same.png["PG1 Imported to Same NiFi"]
the added GetFile processor will also reference the "RPG_Var" variable that exists in the root process group:
image::PG1_variable_ref_2.png["Both PG1 Reference RPG Variable"]
If PG1 versioned flow is imported into a different NiFi instance where "RPG_Var" does not exist:
image::PG1_imported_diff.png["PG1 Imported to Different NiFi"]
A "RPG_Var" variable is created in the PG1 process group:
image::PG1_variable_ref_PG.png["PG1 References PG Variable Copy"]
[[Restricted_Components_in_Versioned_Flows]]
=== Restricted Components in Versioned Flows
To import a versioned flow or revert local changes in a versioned flow, a user must have access to all the components in the versioned flow. As such, it is recommended that restricted components are created at the root process group level if they are to be utilized in versioned flows. Let's walk through some examples to illustrate the benefits of this configuration. Assume the following:

View File

@ -27,9 +27,9 @@ public enum ExpressionLanguageScope {
NONE,
/**
* Expression language is evaluated against variables in registry
* Expression language is evaluated against system and environment variables
*/
VARIABLE_REGISTRY,
ENVIRONMENT,
/**
* Expression language is evaluated per flow file using attributes

View File

@ -608,8 +608,8 @@ public class StandardRuntimeManifestBuilder implements RuntimeManifestBuilder {
return ExpressionLanguageScope.NONE;
case FLOWFILE_ATTRIBUTES:
return ExpressionLanguageScope.FLOWFILE_ATTRIBUTES;
case VARIABLE_REGISTRY:
return ExpressionLanguageScope.VARIABLE_REGISTRY;
case ENVIRONMENT:
return ExpressionLanguageScope.ENVIRONMENT;
default:
throw new IllegalArgumentException("Unknown Expression Language Scope: " + elScope.name());
}

View File

@ -21,7 +21,6 @@ import org.apache.nifi.components.PropertyValue;
import org.apache.nifi.controller.ConfigurationContext;
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;
@ -33,28 +32,25 @@ public class MockConfigurationContext implements ConfigurationContext {
private final Map<PropertyDescriptor, String> properties;
private final ControllerServiceLookup serviceLookup;
private final ControllerService service;
private final VariableRegistry variableRegistry;
private volatile boolean validateExpressions;
public MockConfigurationContext(final Map<PropertyDescriptor, String> properties,
final ControllerServiceLookup serviceLookup) {
this(null, properties, serviceLookup, VariableRegistry.EMPTY_REGISTRY);
}
// This is only for testing purposes as we don't want to set env/sys variables in the tests
private Map<String, String> environmentVariables;
public MockConfigurationContext(final Map<PropertyDescriptor, String> properties,
final ControllerServiceLookup serviceLookup,
final VariableRegistry variableRegistry) {
this(null, properties, serviceLookup, variableRegistry);
final Map<String, String> environmentVariables) {
this(null, properties, serviceLookup, environmentVariables);
}
public MockConfigurationContext(final ControllerService service,
final Map<PropertyDescriptor, String> properties,
final ControllerServiceLookup serviceLookup,
final VariableRegistry variableRegistry) {
final Map<String, String> environmentVariables) {
this.service = service;
this.properties = properties;
this.serviceLookup = serviceLookup == null ? new EmptyControllerServiceLookup() : serviceLookup;
this.variableRegistry = variableRegistry;
this.environmentVariables = environmentVariables;
}
public void setValidateExpressions(final boolean validate) {
@ -70,7 +66,7 @@ public class MockConfigurationContext implements ConfigurationContext {
}
final boolean alreadyEvaluated = !validateExpressions;
return new MockPropertyValue(value, serviceLookup, canonicalDescriptor, alreadyEvaluated, variableRegistry);
return new MockPropertyValue(value, serviceLookup, canonicalDescriptor, alreadyEvaluated, environmentVariables);
}
@Override

View File

@ -28,10 +28,10 @@ import org.apache.nifi.components.state.StateManager;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.controller.ControllerServiceLookup;
import org.apache.nifi.controller.NodeTypeProvider;
import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.Processor;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.scheduling.ExecutionNode;
import org.apache.nifi.state.MockStateManager;
import org.junit.jupiter.api.Assertions;
@ -55,7 +55,6 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
private final String componentName;
private final Map<PropertyDescriptor, String> properties = new HashMap<>();
private final StateManager stateManager;
private final VariableRegistry variableRegistry;
private String annotationData = null;
private boolean yieldCalled = false;
@ -74,12 +73,15 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
private volatile boolean isPrimaryNode;
private volatile boolean isConnected = true;
// This is only for testing purposes as we don't want to set env/sys variables in the tests
private Map<String, String> environmentVariables;
public MockProcessContext(final ConfigurableComponent component) {
this(component, null);
this(component, null, new MockStateManager(component), null);
}
public MockProcessContext(final ConfigurableComponent component, final String componentName) {
this(component, componentName, new MockStateManager(component), VariableRegistry.EMPTY_REGISTRY);
this(component, componentName, new MockStateManager(component), null);
}
/**
@ -87,25 +89,24 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
*
* @param component being mocked
* @param stateManager state manager
* @param variableRegistry variableRegistry
*/
public MockProcessContext(final ConfigurableComponent component, final StateManager stateManager, final VariableRegistry variableRegistry) {
this(component,null,stateManager,variableRegistry);
public MockProcessContext(final ConfigurableComponent component, final StateManager stateManager) {
this(component, null, stateManager, null);
}
public MockProcessContext(final ControllerService component,
final MockProcessContext context,
final StateManager stateManager,
final VariableRegistry variableRegistry) {
this(component, null, context, stateManager, variableRegistry);
final Map<String, String> environmentVariables) {
this(component, null, context, stateManager, environmentVariables);
}
public MockProcessContext(final ControllerService component,
final String componentName,
final MockProcessContext context,
final StateManager stateManager,
final VariableRegistry variableRegistry) {
this(component, componentName, stateManager, variableRegistry);
final Map<String, String> environmentVariables) {
this(component, componentName, stateManager, environmentVariables);
try {
annotationData = context.getControllerServiceAnnotationData(component);
@ -125,17 +126,16 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
* @param component being mocked
* @param componentName the name to be given the component;
* @param stateManager state manager
* @param variableRegistry variableRegistry
*/
public MockProcessContext(final ConfigurableComponent component,
final String componentName,
final StateManager stateManager,
final VariableRegistry variableRegistry) {
final Map<String, String> environmentVariables) {
this.component = Objects.requireNonNull(component);
this.componentName = componentName == null ? "" : componentName;
this.inputRequirement = component.getClass().getAnnotation(InputRequirement.class);
this.stateManager = stateManager;
this.variableRegistry = variableRegistry;
this.environmentVariables = environmentVariables;
}
@ -154,7 +154,7 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
final String setPropertyValue = properties.get(canonicalDescriptor);
final String propValue = (setPropertyValue == null) ? canonicalDescriptor.getDefaultValue() : setPropertyValue;
final MockPropertyValue propertyValue = new MockPropertyValue(propValue, this, canonicalDescriptor, true, variableRegistry);
final MockPropertyValue propertyValue = new MockPropertyValue(propValue, this, canonicalDescriptor, true, environmentVariables);
return propertyValue;
}
@ -169,13 +169,13 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
final String propValue = (setPropertyValue == null) ? descriptor.getDefaultValue() : setPropertyValue;
final boolean alreadyEvaluated = !this.allowExpressionValidation;
final MockPropertyValue propertyValue = new MockPropertyValue(propValue, this, descriptor, alreadyEvaluated, variableRegistry);
final MockPropertyValue propertyValue = new MockPropertyValue(propValue, this, descriptor, alreadyEvaluated, environmentVariables);
return propertyValue;
}
@Override
public PropertyValue newPropertyValue(final String rawValue) {
return new MockPropertyValue(rawValue, this, variableRegistry);
return new MockPropertyValue(rawValue, this, environmentVariables);
}
public ValidationResult setProperty(final String propertyName, final String propertyValue) {
@ -202,7 +202,7 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
requireNonNull(value, "Cannot set property to null value; if the intent is to remove the property, call removeProperty instead");
final PropertyDescriptor fullyPopulatedDescriptor = component.getPropertyDescriptor(descriptor.getName());
final ValidationResult result = fullyPopulatedDescriptor.validate(value, new MockValidationContext(this, stateManager, variableRegistry));
final ValidationResult result = fullyPopulatedDescriptor.validate(value, new MockValidationContext(this, stateManager));
String oldValue = properties.put(fullyPopulatedDescriptor, value);
if (oldValue == null) {
oldValue = fullyPopulatedDescriptor.getDefaultValue();
@ -313,7 +313,7 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
*/
public Collection<ValidationResult> validate() {
final List<ValidationResult> results = new ArrayList<>();
final ValidationContext validationContext = new MockValidationContext(this, stateManager, variableRegistry);
final ValidationContext validationContext = new MockValidationContext(this, stateManager);
final Collection<ValidationResult> componentResults = component.validate(validationContext);
results.addAll(componentResults);
@ -501,7 +501,7 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
@Override
public boolean isExpressionLanguagePresent(final PropertyDescriptor property) {
if (property == null || !property.isExpressionLanguageSupported()) {
if (property == null || property.getExpressionLanguageScope().equals(ExpressionLanguageScope.NONE)) {
return false;
}
@ -576,4 +576,8 @@ public class MockProcessContext extends MockControllerServiceLookup implements P
public boolean isRelationshipRetried(Relationship relationship) {
return false;
}
public Map<String, String> getEnvironmentVariables() {
return environmentVariables;
}
}

View File

@ -36,7 +36,7 @@ public class MockPropertyContext implements PropertyContext {
if (value == null) {
value = property.getDefaultValue();
}
return new MockPropertyValue(value);
return new MockPropertyValue(value, null);
}
@Override

View File

@ -35,7 +35,6 @@ import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.parameter.ParameterLookup;
import org.apache.nifi.processor.DataUnit;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.registry.VariableRegistry;
import java.util.HashMap;
import java.util.List;
@ -49,38 +48,40 @@ public class MockPropertyValue implements PropertyValue {
private final MockControllerServiceLookup serviceLookup;
private final PropertyDescriptor propertyDescriptor;
private final PropertyValue stdPropValue;
private final VariableRegistry variableRegistry;
// This is only for testing purposes as we don't want to set env/sys variables in the tests
private Map<String, String> environmentVariables;
private boolean expressionsEvaluated;
public MockPropertyValue(final String rawValue) {
this(rawValue, null);
this(rawValue, null, null);
}
public MockPropertyValue(final String rawValue, final ControllerServiceLookup serviceLookup) {
this(rawValue, serviceLookup, VariableRegistry.EMPTY_REGISTRY, null);
public MockPropertyValue(final String rawValue, final Map<String, String> environmentVariables) {
this(rawValue, null, environmentVariables);
}
public MockPropertyValue(final String rawValue, final ControllerServiceLookup serviceLookup, final VariableRegistry variableRegistry) {
this(rawValue, serviceLookup, variableRegistry, null);
public MockPropertyValue(final String rawValue, final ControllerServiceLookup serviceLookup, final Map<String, String> environmentVariables) {
this(rawValue, serviceLookup, null, environmentVariables);
}
public MockPropertyValue(final String rawValue, final ControllerServiceLookup serviceLookup, VariableRegistry variableRegistry, final PropertyDescriptor propertyDescriptor) {
this(rawValue, serviceLookup, propertyDescriptor, false, variableRegistry);
public MockPropertyValue(final String rawValue, final ControllerServiceLookup serviceLookup, final PropertyDescriptor propertyDescriptor,
final Map<String, String> environmentVariables) {
this(rawValue, serviceLookup, propertyDescriptor, false, environmentVariables);
}
protected MockPropertyValue(final String rawValue, final ControllerServiceLookup serviceLookup, final PropertyDescriptor propertyDescriptor, final boolean alreadyEvaluated,
final VariableRegistry variableRegistry) {
protected MockPropertyValue(final String rawValue, final ControllerServiceLookup serviceLookup, final PropertyDescriptor propertyDescriptor,
final boolean alreadyEvaluated, final Map<String, String> environmentVariables) {
final ResourceContext resourceContext = new StandardResourceContext(new StandardResourceReferenceFactory(), propertyDescriptor);
this.stdPropValue = new StandardPropertyValue(resourceContext, rawValue, serviceLookup, ParameterLookup.EMPTY, variableRegistry);
this.stdPropValue = new StandardPropertyValue(resourceContext, rawValue, serviceLookup, ParameterLookup.EMPTY);
this.rawValue = rawValue;
this.serviceLookup = (MockControllerServiceLookup) serviceLookup;
this.expectExpressions = propertyDescriptor == null ? null : propertyDescriptor.isExpressionLanguageSupported();
this.expressionLanguageScope = propertyDescriptor == null ? null : propertyDescriptor.getExpressionLanguageScope();
this.propertyDescriptor = propertyDescriptor;
this.expressionsEvaluated = alreadyEvaluated;
this.variableRegistry = variableRegistry;
this.environmentVariables = environmentVariables;
}
private void ensureExpressionsEvaluated() {
@ -207,15 +208,15 @@ public class MockPropertyValue implements PropertyValue {
public PropertyValue evaluateAttributeExpressions(final FlowFile flowFile) throws ProcessException {
/*
* The reason for this null check is that somewhere in the test API, it automatically assumes that a null FlowFile
* should be treated as though it were evaluated with the VARIABLE_REGISTRY scope instead of the flowfile scope. When NiFi
* should be treated as though it were evaluated with the ENVIRONMENT scope instead of the flowfile scope. When NiFi
* is running, it doesn't care when it's evaluating EL against a null flowfile. However, the testing framework currently
* raises an error which makes it not mimick real world behavior.
*/
if (flowFile == null && expressionLanguageScope == ExpressionLanguageScope.FLOWFILE_ATTRIBUTES) {
return evaluateAttributeExpressions(new HashMap<>());
} else if (flowFile == null && expressionLanguageScope == ExpressionLanguageScope.VARIABLE_REGISTRY) {
} else if (flowFile == null && expressionLanguageScope == ExpressionLanguageScope.ENVIRONMENT) {
return evaluateAttributeExpressions(); //Added this to get around a similar edge case where the a null flowfile is passed
//and the scope is to the registry
//and the scope is to the sys/env variable registry
}
return evaluateAttributeExpressions(flowFile, null, null);
@ -260,8 +261,18 @@ public class MockPropertyValue implements PropertyValue {
validateExpressionScope(flowFile != null || additionalAttributes != null);
}
final PropertyValue newValue = stdPropValue.evaluateAttributeExpressions(flowFile, additionalAttributes, decorator, stateValues);
return new MockPropertyValue(newValue.getValue(), serviceLookup, propertyDescriptor, true, variableRegistry);
if(additionalAttributes == null ) {
additionalAttributes = new HashMap<String,String>();
}
// we need a new map here because additionalAttributes can be an unmodifiable map when it's the FlowFile attributes
final Map<String, String> attAndEnvVarRegistry = new HashMap<>(additionalAttributes);
if(environmentVariables != null) {
attAndEnvVarRegistry.putAll(environmentVariables);
}
final PropertyValue newValue = stdPropValue.evaluateAttributeExpressions(flowFile, attAndEnvVarRegistry, decorator, stateValues);
return new MockPropertyValue(newValue.getValue(), serviceLookup, propertyDescriptor, true, environmentVariables);
}
@Override

View File

@ -27,7 +27,6 @@ import org.apache.nifi.components.PropertyValue;
import org.apache.nifi.components.state.StateManager;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.controller.ControllerServiceLookup;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.reporting.Bulletin;
import org.apache.nifi.reporting.BulletinFactory;
import org.apache.nifi.reporting.BulletinRepository;
@ -40,14 +39,12 @@ public class MockReportingContext extends MockControllerServiceLookup implements
private final MockEventAccess eventAccess = new MockEventAccess();
private final Map<PropertyDescriptor, String> properties = new HashMap<>();
private final StateManager stateManager;
private final VariableRegistry variableRegistry;
private final Map<String, List<Bulletin>> componentBulletinsCreated = new HashMap<>();
public MockReportingContext(final Map<String, ControllerService> controllerServices, final StateManager stateManager, final VariableRegistry variableRegistry) {
public MockReportingContext(final Map<String, ControllerService> controllerServices, final StateManager stateManager) {
this.controllerServices = new HashMap<>();
this.stateManager = stateManager;
this.variableRegistry = variableRegistry;
for (final Map.Entry<String, ControllerService> entry : controllerServices.entrySet()) {
this.controllerServices.put(entry.getKey(), new ControllerServiceConfiguration(entry.getValue()));
}
@ -70,7 +67,7 @@ public class MockReportingContext extends MockControllerServiceLookup implements
@Override
public PropertyValue getProperty(final PropertyDescriptor property) {
final String configuredValue = properties.get(property);
return new MockPropertyValue(configuredValue == null ? property.getDefaultValue() : configuredValue, this, variableRegistry);
return new MockPropertyValue(configuredValue == null ? property.getDefaultValue() : configuredValue, this, null);
}
public void setProperty(final String propertyName, final String value) {

View File

@ -36,7 +36,6 @@ import org.apache.nifi.parameter.ParameterParser;
import org.apache.nifi.parameter.ParameterReference;
import org.apache.nifi.parameter.ParameterTokenList;
import org.apache.nifi.parameter.StandardParameterTokenList;
import org.apache.nifi.registry.VariableRegistry;
import java.util.Collection;
import java.util.Collections;
@ -53,18 +52,16 @@ public class MockValidationContext extends MockControllerServiceLookup implement
private final MockProcessContext context;
private final Map<String, Boolean> expressionLanguageSupported;
private final StateManager stateManager;
private final VariableRegistry variableRegistry;
private final Map<PropertyDescriptor, PropertyConfiguration> properties;
private volatile boolean validateExpressions = true;
public MockValidationContext(final MockProcessContext processContext) {
this(processContext, null, VariableRegistry.EMPTY_REGISTRY);
this(processContext, null);
}
public MockValidationContext(final MockProcessContext processContext, final StateManager stateManager, final VariableRegistry variableRegistry) {
public MockValidationContext(final MockProcessContext processContext, final StateManager stateManager) {
this.context = processContext;
this.stateManager = stateManager;
this.variableRegistry = variableRegistry;
final Map<PropertyDescriptor, String> properties = processContext.getProperties();
expressionLanguageSupported = new HashMap<>(properties.size());
@ -100,18 +97,18 @@ public class MockValidationContext extends MockControllerServiceLookup implement
@Override
public PropertyValue newPropertyValue(final String rawValue) {
return new MockPropertyValue(rawValue, this, null, true, variableRegistry);
return new MockPropertyValue(rawValue, this, null, true, context.getEnvironmentVariables());
}
@Override
public ExpressionLanguageCompiler newExpressionLanguageCompiler() {
return new StandardExpressionLanguageCompiler(variableRegistry, ParameterLookup.EMPTY);
return new StandardExpressionLanguageCompiler(ParameterLookup.EMPTY);
}
@Override
public ValidationContext getControllerServiceValidationContext(final ControllerService controllerService) {
final MockProcessContext serviceProcessContext = new MockProcessContext(controllerService, context, stateManager, variableRegistry);
final MockValidationContext serviceValidationContext = new MockValidationContext(serviceProcessContext, stateManager, variableRegistry);
final MockProcessContext serviceProcessContext = new MockProcessContext(controllerService, context, stateManager, context.getEnvironmentVariables());
final MockValidationContext serviceValidationContext = new MockValidationContext(serviceProcessContext, stateManager);
serviceValidationContext.setValidateExpressions(validateExpressions);
return serviceValidationContext;
}

View File

@ -1,42 +0,0 @@
/*
* 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.nifi.util;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.nifi.registry.VariableDescriptor;
import org.apache.nifi.registry.VariableRegistry;
public class MockVariableRegistry implements VariableRegistry {
private final Map<VariableDescriptor, String> variables = new HashMap<>();
@Override
public Map<VariableDescriptor, String> getVariableMap() {
return Collections.unmodifiableMap(variables);
}
public void setVariable(final VariableDescriptor descriptor, final String value) {
variables.put(descriptor, value);
}
public String removeVariable(final VariableDescriptor descriptor) {
return variables.remove(descriptor);
}
}

View File

@ -41,7 +41,7 @@ import org.apache.nifi.processor.Processor;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.provenance.ProvenanceEventRecord;
import org.apache.nifi.provenance.ProvenanceEventType;
import org.apache.nifi.registry.VariableDescriptor;
import org.apache.nifi.registry.EnvironmentVariables;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.state.MockStateManager;
import org.junit.jupiter.api.Assertions;
@ -87,7 +87,6 @@ public class StandardProcessorTestRunner implements TestRunner {
private final boolean triggerSerially;
private final MockStateManager processorStateManager;
private final Map<String, MockStateManager> controllerServiceStateManagers = new HashMap<>();
private final MockVariableRegistry variableRegistry;
private int numThreads = 1;
private MockSessionFactory sessionFactory;
@ -100,6 +99,9 @@ public class StandardProcessorTestRunner implements TestRunner {
private boolean enforceReadStreamsClosed = true;
private boolean validateExpressionUsage = true;
// This only for testing purposes as we don't want to set env/sys variables in the tests
private final Map<String, String> environmentVariables = new HashMap<>();
StandardProcessorTestRunner(final Processor processor) {
this(processor, null);
}
@ -123,9 +125,8 @@ public class StandardProcessorTestRunner implements TestRunner {
this.flowFileQueue = sharedState.getFlowFileQueue();
this.processorStateManager = new MockStateManager(processor);
this.sessionFactory = new MockSessionFactory(sharedState, processor, enforceReadStreamsClosed, processorStateManager, allowSynchronousSessionCommits);
this.variableRegistry = new MockVariableRegistry();
this.context = new MockProcessContext(processor, processorName, processorStateManager, variableRegistry);
this.context = new MockProcessContext(processor, processorName, processorStateManager, environmentVariables);
this.kerberosContext = kerberosContext;
final MockProcessorInitializationContext mockInitContext = new MockProcessorInitializationContext(processor, context, logger, kerberosContext);
@ -253,6 +254,7 @@ public class StandardProcessorTestRunner implements TestRunner {
}
}
@Override
public void unSchedule() {
try {
ReflectionUtils.invokeMethodsWithAnnotation(OnUnscheduled.class, processor, context);
@ -261,6 +263,7 @@ public class StandardProcessorTestRunner implements TestRunner {
}
}
@Override
public void stop() {
try {
ReflectionUtils.invokeMethodsWithAnnotation(OnStopped.class, processor, context);
@ -681,7 +684,7 @@ public class StandardProcessorTestRunner implements TestRunner {
throw new IllegalStateException("Controller Service has not been added to this TestRunner via the #addControllerService method");
}
final ValidationContext validationContext = new MockValidationContext(context, serviceStateManager, variableRegistry).getControllerServiceValidationContext(service);
final ValidationContext validationContext = new MockValidationContext(context, serviceStateManager).getControllerServiceValidationContext(service);
final Collection<ValidationResult> results = context.getControllerService(service.getIdentifier()).validate(validationContext);
for (final ValidationResult result : results) {
@ -700,7 +703,7 @@ public class StandardProcessorTestRunner implements TestRunner {
throw new IllegalStateException("Controller Service has not been added to this TestRunner via the #addControllerService method");
}
final ValidationContext validationContext = new MockValidationContext(context, serviceStateManager, variableRegistry).getControllerServiceValidationContext(service);
final ValidationContext validationContext = new MockValidationContext(context, serviceStateManager).getControllerServiceValidationContext(service);
final Collection<ValidationResult> results = context.getControllerService(service.getIdentifier()).validate(validationContext);
for (final ValidationResult result : results) {
@ -723,7 +726,7 @@ public class StandardProcessorTestRunner implements TestRunner {
try {
// Create a config context to pass into the controller service's OnDisabled method (it will be ignored if the controller service has no arguments)
final MockConfigurationContext configContext = new MockConfigurationContext(service, configuration.getProperties(), context, variableRegistry);
final MockConfigurationContext configContext = new MockConfigurationContext(service, configuration.getProperties(), context, environmentVariables);
configContext.setValidateExpressions(validateExpressionUsage);
ReflectionUtils.invokeMethodsWithAnnotation(OnDisabled.class, service, configContext);
} catch (final Exception e) {
@ -746,7 +749,7 @@ public class StandardProcessorTestRunner implements TestRunner {
}
// ensure controller service is valid before enabling
final MockValidationContext mockValidationContext = new MockValidationContext(context, null, variableRegistry);
final MockValidationContext mockValidationContext = new MockValidationContext(context, null);
mockValidationContext.setValidateExpressions(validateExpressionUsage);
final ValidationContext serviceValidationContext = mockValidationContext.getControllerServiceValidationContext(service);
@ -759,7 +762,7 @@ public class StandardProcessorTestRunner implements TestRunner {
}
try {
final MockConfigurationContext configContext = new MockConfigurationContext(service, configuration.getProperties(), context, variableRegistry);
final MockConfigurationContext configContext = new MockConfigurationContext(service, configuration.getProperties(), context, environmentVariables);
configContext.setValidateExpressions(validateExpressionUsage);
ReflectionUtils.invokeMethodsWithAnnotation(OnEnabled.class, service, configContext);
} catch (final InvocationTargetException ite) {
@ -834,7 +837,7 @@ public class StandardProcessorTestRunner implements TestRunner {
final Map<PropertyDescriptor, String> curProps = configuration.getProperties();
final Map<PropertyDescriptor, String> updatedProps = new HashMap<>(curProps);
final ValidationContext validationContext = new MockValidationContext(context, serviceStateManager, variableRegistry).getControllerServiceValidationContext(service);
final ValidationContext validationContext = new MockValidationContext(context, serviceStateManager).getControllerServiceValidationContext(service);
final boolean dependencySatisfied = validationContext.isDependencySatisfied(property, processor::getPropertyDescriptor);
final ValidationResult validationResult;
@ -987,26 +990,18 @@ public class StandardProcessorTestRunner implements TestRunner {
}
@Override
public String getVariableValue(final String name) {
public String getEnvironmentVariableValue(final String name) {
Objects.requireNonNull(name);
return variableRegistry.getVariableValue(name);
if(environmentVariables.containsKey(name)) {
return environmentVariables.get(name);
} else {
return EnvironmentVariables.ENVIRONMENT_VARIABLES.getEnvironmentVariableValue(name);
}
}
@Override
public void setVariable(final String name, final String value) {
Objects.requireNonNull(name);
Objects.requireNonNull(value);
final VariableDescriptor descriptor = new VariableDescriptor.Builder(name).build();
variableRegistry.setVariable(descriptor, value);
}
@Override
public String removeVariable(final String name) {
Objects.requireNonNull(name);
return variableRegistry.removeVariable(new VariableDescriptor.Builder(name).build());
public void setEnvironmentVariableValue(String name, String value) {
environmentVariables.put(name, value);
}
/**

View File

@ -994,17 +994,6 @@ public interface TestRunner {
*/
void setConnected(boolean isConnected);
/**
* Sets the value of the variable with the given name to be the given value. This exposes the variable
* for use by the Expression Language.
*
* @param name the name of the variable to set
* @param value the value of the variable
*
* @throws NullPointerException if either the name or the value is null
*/
void setVariable(String name, String value);
/**
* Returns the current value of the variable with the given name
*
@ -1013,17 +1002,21 @@ public interface TestRunner {
*
* @throws NullPointerException if the name is null
*/
String getVariableValue(String name);
String getEnvironmentVariableValue(String name);
/**
* Removes the variable with the given name from this Test Runner, if it is set.
* Sets the value of the variable with the given name to be the given value. This exposes the variable
* for use by the Expression Language.
*
* @param name the name of the variable to remove
* @return the value that was set for the variable, or <code>null</code> if the variable was not set
* NOTE - this method is only for testing purposes as we only support variables coming from environment
* and system variables. This usage is to avoid the need to set env/sys variables in the tests.
*
* @throws NullPointerException if the name is null
* @param name the name of the variable to set
* @param value the value of the variable
*
* @throws NullPointerException if either the name or the value is null
*/
String removeVariable(String name);
void setEnvironmentVariableValue(String name, String value);
/**
* Asserts that all FlowFiles meet all conditions.

View File

@ -43,7 +43,6 @@ import java.util.function.Predicate;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@ -163,19 +162,6 @@ public class TestStandardProcessorTestRunner {
runner.assertAllFlowFilesContainAttribute(AddAttributeProcessor.KEY);
}
@Test
public void testVariables() {
final AddAttributeProcessor proc = new AddAttributeProcessor();
final TestRunner runner = TestRunners.newTestRunner(proc);
assertNull(runner.getVariableValue("hello"));
runner.setVariable("hello", "world");
assertEquals("world", runner.getVariableValue("hello"));
assertEquals("world", runner.removeVariable("hello"));
assertNull(runner.getVariableValue("hello"));
}
@Test
public void testControllerServiceUpdateShouldCallOnSetProperty() {
// Arrange
@ -220,7 +206,6 @@ public class TestStandardProcessorTestRunner {
final AddAttributeProcessor proc = new AddAttributeProcessor();
final TestRunner runner = TestRunners.newTestRunner(proc);
final String serviceIdentifier = "test";
final String pdName = "name";
final String pdValue = "exampleName";
try {
runner.addControllerService(serviceIdentifier, testService);

View File

@ -75,7 +75,7 @@ public class AccumuloService extends AbstractControllerService implements BaseAc
.displayName("ZooKeeper Quorum")
.description("Comma-separated list of ZooKeeper hosts for Accumulo.")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.build();
protected static final PropertyDescriptor INSTANCE_NAME = new PropertyDescriptor.Builder()
@ -83,7 +83,7 @@ public class AccumuloService extends AbstractControllerService implements BaseAc
.displayName("Instance Name")
.description("Instance name of the Accumulo cluster")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.build();
protected static final PropertyDescriptor AUTHENTICATION_TYPE = new PropertyDescriptor.Builder()
@ -100,7 +100,7 @@ public class AccumuloService extends AbstractControllerService implements BaseAc
.displayName("Accumulo User")
.description("Connecting user for Accumulo")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.dependsOn(AUTHENTICATION_TYPE, AuthenticationType.PASSWORD.toString())
.build();
@ -110,7 +110,7 @@ public class AccumuloService extends AbstractControllerService implements BaseAc
.description("Connecting user's password")
.sensitive(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.dependsOn(AUTHENTICATION_TYPE, AuthenticationType.PASSWORD.toString())
.build();
@ -135,7 +135,7 @@ public class AccumuloService extends AbstractControllerService implements BaseAc
.displayName("Kerberos Principal")
.description("Kerberos Principal")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.dependsOn(AUTHENTICATION_TYPE, AuthenticationType.KERBEROS.toString())
.build();
@ -145,7 +145,7 @@ public class AccumuloService extends AbstractControllerService implements BaseAc
.description("Kerberos Password")
.sensitive(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.dependsOn(AUTHENTICATION_TYPE, AuthenticationType.KERBEROS.toString())
.build();

View File

@ -104,7 +104,7 @@ public class QueryAirtableTable extends AbstractProcessor {
.defaultValue(API_V0_BASE_URL)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.addValidator(StandardValidators.URL_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(true)
.build();
@ -123,7 +123,7 @@ public class QueryAirtableTable extends AbstractProcessor {
.displayName("Base ID")
.description("The ID of the Airtable base to be queried.")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
@ -132,7 +132,7 @@ public class QueryAirtableTable extends AbstractProcessor {
.displayName("Table ID")
.description("The name or the ID of the Airtable table to be queried.")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
@ -140,7 +140,7 @@ public class QueryAirtableTable extends AbstractProcessor {
.name("fields")
.displayName("Fields")
.description("Comma-separated list of fields to query from the table. Both the field's name and ID can be used.")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
@ -148,7 +148,7 @@ public class QueryAirtableTable extends AbstractProcessor {
.name("custom-filter")
.displayName("Custom Filter")
.description("Filter records by Airtable's formulas.")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
@ -159,7 +159,7 @@ public class QueryAirtableTable extends AbstractProcessor {
+ " and Airtable servers' clock are not in sync. Must be greater than or equal to 1 second.")
.defaultValue("3 s")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.TIME_PERIOD_VALIDATOR)
.build();
@ -175,7 +175,7 @@ public class QueryAirtableTable extends AbstractProcessor {
.name("query-page-size")
.displayName("Query Page Size")
.description("Number of records to be fetched in a page. Should be between 1 and 100 inclusively.")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.createLongValidator(1, 100, true))
.build();
@ -184,7 +184,7 @@ public class QueryAirtableTable extends AbstractProcessor {
.displayName("Max Records Per FlowFile")
.description("The maximum number of result records that will be included in a single FlowFile. This will allow you to break up very large"
+ " result sets into multiple FlowFiles. If no value specified, then all records are returned in a single FlowFile.")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
.build();

View File

@ -62,7 +62,7 @@ abstract class AbstractAMQPProcessor<T extends AMQPWorker> extends AbstractProce
.description("A comma-separated list of known AMQP Brokers in the format <host>:<port> (e.g., localhost:5672). If this is " +
"set, Host Name and Port are ignored. Only include hosts from the same AMQP cluster.")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.HOSTNAME_PORT_LIST_VALIDATOR)
.build();
public static final PropertyDescriptor HOST = new PropertyDescriptor.Builder()
@ -70,7 +70,7 @@ abstract class AbstractAMQPProcessor<T extends AMQPWorker> extends AbstractProce
.description("Network address of AMQP broker (e.g., localhost). If Brokers is set, then this property is ignored.")
.required(false)
.defaultValue("localhost")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_EL_VALIDATOR)
.build();
public static final PropertyDescriptor PORT = new PropertyDescriptor.Builder()
@ -78,21 +78,21 @@ abstract class AbstractAMQPProcessor<T extends AMQPWorker> extends AbstractProce
.description("Numeric value identifying Port of AMQP broker (e.g., 5671). If Brokers is set, then this property is ignored.")
.required(false)
.defaultValue("5672")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.PORT_VALIDATOR)
.build();
public static final PropertyDescriptor V_HOST = new PropertyDescriptor.Builder()
.name("Virtual Host")
.description("Virtual Host name which segregates AMQP system for enhanced security.")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_EL_VALIDATOR)
.build();
public static final PropertyDescriptor USER = new PropertyDescriptor.Builder()
.name("User Name")
.description("User Name used for authentication and authorization.")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_EL_VALIDATOR)
.build();
public static final PropertyDescriptor PASSWORD = new PropertyDescriptor.Builder()

View File

@ -114,7 +114,7 @@ public class JASN1Reader extends AbstractConfigurableComponent implements Record
.displayName("ASN.1 Files")
.description("Comma-separated list of ASN.1 files.")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
@ -160,7 +160,7 @@ public class JASN1Reader extends AbstractConfigurableComponent implements Record
.name("Schema Preparation Directory")
.description("When the processor is configured to do additional preprocessing, new modified schema files will be created in this directory." +
" For more information about additional preprocessing please see description of the 'Do Additional Preprocessing' property or Additional Details - Additional Preprocessing.")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.createDirectoryExistsValidator(true, false))
.dependsOn(SCHEMA_PREPARATION_STRATEGY, ADDITIONAL_PREPROCESSING)
.required(true)

View File

@ -116,7 +116,7 @@ import static org.apache.nifi.reporting.util.provenance.ProvenanceEventConsumer.
" See 'Additional Details' for further description and limitations.")
@Stateful(scopes = Scope.LOCAL, description = "Stores the Reporting Task's last event Id so that on restart the task knows where it left off.")
@DynamicProperty(name = "hostnamePattern.<namespace>", value = "hostname Regex patterns",
description = RegexNamespaceResolver.PATTERN_PROPERTY_PREFIX_DESC, expressionLanguageScope = ExpressionLanguageScope.VARIABLE_REGISTRY)
description = RegexNamespaceResolver.PATTERN_PROPERTY_PREFIX_DESC, expressionLanguageScope = ExpressionLanguageScope.ENVIRONMENT)
// In order for each reporting task instance to have its own static objects such as KafkaNotification.
@RequiresInstanceClassLoading
public class ReportLineageToAtlas extends AbstractReportingTask {
@ -131,7 +131,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
" (e.g. https://knox-hostname:8443/gateway/{topology-name}/atlas)." +
" If not specified, 'atlas.rest.address' in Atlas Configuration File is used.")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
@ -169,7 +169,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
.displayName("Atlas Username")
.description("User name to communicate with Atlas.")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
@ -179,7 +179,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
.description("Password to communicate with Atlas.")
.required(false)
.sensitive(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
@ -190,7 +190,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
" If not specified and 'Create Atlas Configuration File' is disabled," +
" then, 'atlas-application.properties' file under root classpath is used.")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.identifiesExternalResource(ResourceCardinality.SINGLE, ResourceType.DIRECTORY)
// Atlas generates ssl-client.xml in this directory and then loads it from classpath
.dynamicallyModifiesClasspath(true)
@ -202,7 +202,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
.description("NiFi URL is used in Atlas to represent this NiFi cluster (or standalone instance)." +
" It is recommended to use one that can be accessible remotely instead of using 'localhost'.")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.URL_VALIDATOR)
.build();
@ -214,7 +214,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
" Multiple mappings can be configured by user defined properties." +
" See 'Additional Details...' for more.")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
@ -246,7 +246,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
" NOTE: Once this reporting task has started, restarting NiFi is required to changed this property" +
" as Atlas library holds a unmodifiable static reference to Kafka client.")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
@ -273,7 +273,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
" This principal will be set into 'sasl.jaas.config' Kafka's property.")
.required(false)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.build();
public static final PropertyDescriptor KERBEROS_KEYTAB = new PropertyDescriptor.Builder()
.name("nifi-kerberos-keytab")
@ -283,7 +283,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
" This principal will be set into 'sasl.jaas.config' Kafka's property.")
.required(false)
.identifiesExternalResource(ResourceCardinality.SINGLE, ResourceType.FILE)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.build();
public static final PropertyDescriptor KERBEROS_CREDENTIALS_SERVICE = new PropertyDescriptor.Builder()
.name("kerberos-credentials-service")
@ -303,7 +303,7 @@ public class ReportLineageToAtlas extends AbstractReportingTask {
" It is ignored unless one of the SASL options of the <Security Protocol> are selected.")
.required(false)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.defaultValue("kafka")
.build();

View File

@ -48,7 +48,7 @@ public class RegexNamespaceResolver implements NamespaceResolver {
.Builder().name(propertyDescriptorName)
.description(PATTERN_PROPERTY_PREFIX_DESC)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.dynamic(true)
.sensitive(false)
.build();

View File

@ -390,7 +390,7 @@ public class TestReportLineageToAtlas {
saveAtlasConf(atlasConf);
ConfigurationContext configurationContext = new MockConfigurationContext(properties, controllerServiceLookup);
ConfigurationContext configurationContext = new MockConfigurationContext(properties, controllerServiceLookup, null);
testSubject.initialize(initializationContext);
@ -437,7 +437,7 @@ public class TestReportLineageToAtlas {
when(reportingContext.getProperties()).thenReturn(properties);
when(reportingContext.getProperty(any())).then(invocation -> new MockPropertyValue(properties.get(invocation.getArguments()[0])));
ConfigurationContext configurationContext = new MockConfigurationContext(properties, null);
ConfigurationContext configurationContext = new MockConfigurationContext(properties, null, null);
testSubject.initialize(initializationContext);
testSubject.setup(configurationContext);
@ -486,7 +486,7 @@ public class TestReportLineageToAtlas {
}
private void testNotificationSendingIsSynchronous(Map<PropertyDescriptor, String> properties) throws Exception {
ConfigurationContext configurationContext = new MockConfigurationContext(properties, null);
ConfigurationContext configurationContext = new MockConfigurationContext(properties, null, null);
testSubject.initialize(initializationContext);
testSubject.setup(configurationContext);
@ -504,7 +504,7 @@ public class TestReportLineageToAtlas {
Map<PropertyDescriptor, String> properties = initReportingTaskProperties(atlasConfDir);
properties.put(ATLAS_CONF_CREATE, "false");
ConfigurationContext configurationContext = new MockConfigurationContext(properties, null);
ConfigurationContext configurationContext = new MockConfigurationContext(properties, null, null);
testSubject.initialize(initializationContext);
assertThrows(ProcessException.class, () -> testSubject.setup(configurationContext));

View File

@ -90,7 +90,7 @@ public abstract class AbstractAWSProcessor<ClientType extends AmazonWebServiceCl
public static final PropertyDescriptor PROXY_HOST = new PropertyDescriptor.Builder()
.name("Proxy Host")
.description("Proxy host name or IP")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
@ -98,7 +98,7 @@ public abstract class AbstractAWSProcessor<ClientType extends AmazonWebServiceCl
public static final PropertyDescriptor PROXY_HOST_PORT = new PropertyDescriptor.Builder()
.name("Proxy Host Port")
.description("Proxy host port")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.PORT_VALIDATOR)
.build();
@ -107,7 +107,7 @@ public abstract class AbstractAWSProcessor<ClientType extends AmazonWebServiceCl
.name("proxy-user-name")
.displayName("Proxy Username")
.description("Proxy username")
.expressionLanguageSupported(true)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
@ -116,7 +116,7 @@ public abstract class AbstractAWSProcessor<ClientType extends AmazonWebServiceCl
.name("proxy-user-password")
.displayName("Proxy Password")
.description("Proxy password")
.expressionLanguageSupported(true)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(true)
@ -150,7 +150,7 @@ public abstract class AbstractAWSProcessor<ClientType extends AmazonWebServiceCl
.description("Endpoint URL to use instead of the AWS default including scheme, host, port, and path. " +
"The AWS libraries select an endpoint URL based on the AWS region, but this property overrides " +
"the selected endpoint URL, allowing use with other S3-compatible endpoints.")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.URL_VALIDATOR)
.build();

View File

@ -35,7 +35,7 @@ public final class AwsPropertyDescriptors {
.description(String.format("Fully qualified class name of the custom signer class. The signer must implement %s interface.", Signer.class.getName()))
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.build();
public static final PropertyDescriptor CUSTOM_SIGNER_MODULE_LOCATION = new PropertyDescriptor.Builder()
@ -44,7 +44,7 @@ public final class AwsPropertyDescriptors {
.description("Comma-separated list of paths to files and/or directories which contain the custom signer's JAR file and its dependencies (if any).")
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.identifiesExternalResource(ResourceCardinality.MULTIPLE, ResourceType.FILE, ResourceType.DIRECTORY)
.dynamicallyModifiesClasspath(true)
.build();

View File

@ -74,7 +74,7 @@ public class CredentialPropertyDescriptors {
public static final PropertyDescriptor ACCESS_KEY = new PropertyDescriptor.Builder()
.name("Access Key")
.displayName("Access Key ID")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(true)
@ -83,7 +83,7 @@ public class CredentialPropertyDescriptors {
public static final PropertyDescriptor SECRET_KEY = new PropertyDescriptor.Builder()
.name("Secret Key")
.displayName("Secret Access Key")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(true)
@ -98,7 +98,7 @@ public class CredentialPropertyDescriptors {
public static final PropertyDescriptor PROFILE_NAME = new PropertyDescriptor.Builder()
.name("profile-name")
.displayName("Profile Name")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(false)

View File

@ -83,7 +83,7 @@ public abstract class AbstractDynamoDBProcessor extends AbstractAWSCredentialsPr
public static final PropertyDescriptor TABLE = new PropertyDescriptor.Builder()
.name("Table Name")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.description("The DynamoDB table name")
.build();
@ -124,7 +124,7 @@ public abstract class AbstractDynamoDBProcessor extends AbstractAWSCredentialsPr
public static final PropertyDescriptor HASH_KEY_NAME = new PropertyDescriptor.Builder()
.name("Hash Key Name")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.description("The hash key name of the item")
.build();
@ -132,7 +132,7 @@ public abstract class AbstractDynamoDBProcessor extends AbstractAWSCredentialsPr
public static final PropertyDescriptor RANGE_KEY_NAME = new PropertyDescriptor.Builder()
.name("Range Key Name")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.description("The range key name of the item")
.build();
@ -140,7 +140,7 @@ public abstract class AbstractDynamoDBProcessor extends AbstractAWSCredentialsPr
public static final PropertyDescriptor JSON_DOCUMENT = new PropertyDescriptor.Builder()
.name("Json Document attribute")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.description("The Json document to be retrieved from the dynamodb item")
.build();
@ -148,7 +148,7 @@ public abstract class AbstractDynamoDBProcessor extends AbstractAWSCredentialsPr
public static final PropertyDescriptor BATCH_SIZE = new PropertyDescriptor.Builder()
.name("Batch items for each request (between 1 and 50)")
.required(false)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.createLongValidator(1, 50, true))
.defaultValue("1")
.description("The items to be retrieved in one batch")
@ -159,7 +159,7 @@ public abstract class AbstractDynamoDBProcessor extends AbstractAWSCredentialsPr
.description("Character set of data in the document")
.addValidator(StandardValidators.CHARACTER_SET_VALIDATOR)
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.defaultValue(Charset.defaultCharset().name())
.build();

View File

@ -103,7 +103,7 @@ public abstract class AbstractAwsProcessor<T extends SdkClient, U extends AwsSyn
public static final PropertyDescriptor PROXY_HOST = new PropertyDescriptor.Builder()
.name("Proxy Host")
.description("Proxy host name or IP")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
@ -111,7 +111,7 @@ public abstract class AbstractAwsProcessor<T extends SdkClient, U extends AwsSyn
public static final PropertyDescriptor PROXY_HOST_PORT = new PropertyDescriptor.Builder()
.name("Proxy Host Port")
.description("Proxy host port")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.PORT_VALIDATOR)
.build();
@ -120,7 +120,7 @@ public abstract class AbstractAwsProcessor<T extends SdkClient, U extends AwsSyn
.name("proxy-user-name")
.displayName("Proxy Username")
.description("Proxy username")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
@ -129,7 +129,7 @@ public abstract class AbstractAwsProcessor<T extends SdkClient, U extends AwsSyn
.name("proxy-user-password")
.displayName("Proxy Password")
.description("Proxy password")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(true)
@ -161,7 +161,7 @@ public abstract class AbstractAwsProcessor<T extends SdkClient, U extends AwsSyn
.description("Endpoint URL to use instead of the AWS default including scheme, host, port, and path. " +
"The AWS libraries select an endpoint URL based on the AWS region, but this property overrides " +
"the selected endpoint URL, allowing use with other S3-compatible endpoints.")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.URL_VALIDATOR)
.build();

View File

@ -233,7 +233,9 @@ public abstract class AbstractAWSGatewayApiProcessor extends
.description(
"The Content-Type to specify for when content is being transmitted through a PUT, POST or PATCH. "
+ "In the case of an empty value after evaluating an expression language expression, Content-Type defaults to "
+ DEFAULT_CONTENT_TYPE).required(true).expressionLanguageSupported(true)
+ DEFAULT_CONTENT_TYPE)
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.defaultValue("${" + CoreAttributes.MIME_TYPE.key() + "}")
.addValidator(StandardValidators
.createAttributeExpressionLanguageValidator(AttributeExpression.ResultType.STRING))

View File

@ -163,7 +163,7 @@ public class TestAwsSecretsManagerParameterProvider {
parameterProvider.initialize(initContext);
final Map<PropertyDescriptor, String> properties = new HashMap<>();
final MockConfigurationContext mockConfigurationContext = new MockConfigurationContext(properties, null);
final MockConfigurationContext mockConfigurationContext = new MockConfigurationContext(properties, null, null);
List<ParameterGroup> parameterGroups = new ArrayList<>();
// Verify parameter fetching

View File

@ -134,7 +134,7 @@ public class PutDynamoDBRecord extends AbstractDynamoDBProcessor {
.name("partition-key-field")
.displayName("Partition Key Field")
.required(true)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.description(
"Defines the name of the partition key field in the DynamoDB table. Partition key is also known as hash key. " +
@ -146,7 +146,7 @@ public class PutDynamoDBRecord extends AbstractDynamoDBProcessor {
.displayName("Partition Key Attribute")
.required(true)
.dependsOn(PARTITION_KEY_STRATEGY, PARTITION_BY_ATTRIBUTE)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.description("Specifies the FlowFile attribute that will be used as the value of the partition key when using \"Partition by attribute\" partition key strategy.")
.build();
@ -166,7 +166,7 @@ public class PutDynamoDBRecord extends AbstractDynamoDBProcessor {
.displayName("Sort Key Field")
.required(true)
.dependsOn(SORT_KEY_STRATEGY, SORT_BY_FIELD, SORT_BY_SEQUENCE)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.description("Defines the name of the sort key field in the DynamoDB table. Sort key is also known as range key.")
.build();

View File

@ -185,7 +185,7 @@ public class ConsumeKinesisStream extends AbstractKinesisStreamProcessor {
return new ValidationResult.Builder().valid(true).subject(subject).build();
})
.defaultValue(RecordFieldType.TIMESTAMP.getDefaultFormat())
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(true).build();
public static final PropertyDescriptor FAILOVER_TIMEOUT = new PropertyDescriptor.Builder()
@ -233,7 +233,7 @@ public class ConsumeKinesisStream extends AbstractKinesisStreamProcessor {
.name("amazon-kinesis-stream-dynamodb-override")
.description("DynamoDB override to use non-AWS deployments")
.addValidator(StandardValidators.URL_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false).build();
public static final PropertyDescriptor REPORT_CLOUDWATCH_METRICS = new PropertyDescriptor.Builder()

View File

@ -183,7 +183,7 @@ public class ListS3 extends AbstractS3Processor implements VerifiableProcessor {
public static final PropertyDescriptor PREFIX = new Builder()
.name("prefix")
.displayName("Prefix")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.required(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.description("The prefix used to filter the object list. Do not begin with a forward slash '/'. In most cases, it should end with a forward slash '/'.")

View File

@ -273,7 +273,7 @@ public class PutS3Object extends AbstractS3Processor {
.required(true)
.addValidator(StandardValidators.FILE_EXISTS_VALIDATOR)
.defaultValue("${java.io.tmpdir}")
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.build();
public static final List<PropertyDescriptor> properties = Collections.unmodifiableList(Arrays.asList(

View File

@ -101,7 +101,7 @@ public class StandardS3EncryptionService extends AbstractControllerService imple
.required(false)
.sensitive(true)
.addValidator((subject, input, context) -> new ValidationResult.Builder().valid(true).build()) // will be validated in customValidate()
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.build();
public static final PropertyDescriptor KMS_REGION = new PropertyDescriptor.Builder()

Some files were not shown because too many files have changed in this diff Show More