GH-883 Add support for filtering out ineligible functions
Resolves #883
This commit is contained in:
@@ -16,7 +16,10 @@
|
||||
|
||||
package org.springframework.cloud.function.context;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@@ -65,6 +68,11 @@ public class FunctionProperties implements EnvironmentAware, ApplicationContextA
|
||||
*/
|
||||
private String definition;
|
||||
|
||||
/**
|
||||
* List of functions that are not eligible to be registered in Function Catalog.
|
||||
*/
|
||||
private final List<String> ineligibleDefinitions;
|
||||
|
||||
private Map<String, FunctionConfigurationProperties> configuration;
|
||||
|
||||
private String expectedContentType;
|
||||
@@ -73,6 +81,23 @@ public class FunctionProperties implements EnvironmentAware, ApplicationContextA
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
public FunctionProperties() {
|
||||
ineligibleDefinitions = new ArrayList<>();
|
||||
String[] definitions = new String[] {
|
||||
"org.springframework.boot",
|
||||
"org.springframework.cloud.function.cloudevent.CloudEventsFunctionExtensionConfiguration",
|
||||
"org.springframework.cloud.function.context.config.FunctionsEndpointAutoConfiguration",
|
||||
"classLoaderMetrics",
|
||||
"jvmMemoryMetrics",
|
||||
"jvmInfoMetrics",
|
||||
"jvmCompilationMetrics",
|
||||
"uptimeMetrics",
|
||||
"kotlinToFunctionTransformer",
|
||||
"CloudEventsMessageConverterConfiguration"
|
||||
};
|
||||
ineligibleDefinitions.addAll(Arrays.asList(definitions));
|
||||
}
|
||||
|
||||
public Map<String, FunctionConfigurationProperties> getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
@@ -164,6 +189,14 @@ public class FunctionProperties implements EnvironmentAware, ApplicationContextA
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public List<String> getIneligibleDefinitions() {
|
||||
return new ArrayList<>(this.ineligibleDefinitions);
|
||||
}
|
||||
|
||||
public void setIneligibleDefinitions(List<String> definitions) {
|
||||
this.ineligibleDefinitions.addAll(definitions);
|
||||
}
|
||||
|
||||
public static class FunctionConfigurationProperties {
|
||||
|
||||
private Map<String, Object> inputHeaderMappingExpression;
|
||||
|
||||
@@ -163,6 +163,9 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect
|
||||
|
||||
@Override
|
||||
public <T> void register(FunctionRegistration<T> registration) {
|
||||
if (!isRegistrationEligible(registration)) {
|
||||
return;
|
||||
}
|
||||
Assert.notNull(registration, "'registration' must not be null");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Registering function " + registration.getNames());
|
||||
@@ -170,6 +173,21 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect
|
||||
this.functionRegistrations.add(registration);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private boolean isRegistrationEligible(FunctionRegistration registration) {
|
||||
if (this.functionProperties != null) {
|
||||
for (String definition : this.functionProperties.getIneligibleDefinitions()) {
|
||||
if (registration.getTarget().getClass().getName().equals(definition)) {
|
||||
return false;
|
||||
}
|
||||
else if (registration.getNames().contains(definition) || registration.getTarget().getClass().getName().contains(definition)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----
|
||||
|
||||
@Override
|
||||
|
||||
@@ -140,7 +140,7 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean(RoutingFunction.FUNCTION_NAME)
|
||||
RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionProperties functionProperties,
|
||||
public RoutingFunction functionRouter(FunctionCatalog functionCatalog, FunctionProperties functionProperties,
|
||||
BeanFactory beanFactory, @Nullable MessageRoutingCallback routingCallback) {
|
||||
return new RoutingFunction(functionCatalog, functionProperties, new BeanFactoryResolver(beanFactory), routingCallback);
|
||||
}
|
||||
|
||||
@@ -105,6 +105,27 @@ public class BeanFactoryAwareFunctionRegistryTests {
|
||||
System.clearProperty("spring.cloud.function.definition");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionEligibilityFiltering() {
|
||||
System.setProperty("spring.cloud.function.ineligible-definitions", "asJsonNode");
|
||||
Collection<FunctionInvocationWrapper> registeredFunction = new ArrayList<FunctionInvocationWrapper>();
|
||||
FunctionCatalog catalog = this.configureCatalog(JsonNodeConfiguration.class);
|
||||
for (String beanName : context.getBeanDefinitionNames()) {
|
||||
try {
|
||||
FunctionInvocationWrapper function = catalog.lookup(beanName);
|
||||
if (function != null) {
|
||||
registeredFunction.add(function);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
System.out.println(registeredFunction);
|
||||
assertThat(registeredFunction.size()).isEqualTo(2);
|
||||
assertThat((FunctionInvocationWrapper) catalog.lookup("asJsonNode")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsonNodeAsInput() throws Exception {
|
||||
FunctionCatalog catalog = this.configureCatalog(JsonNodeConfiguration.class);
|
||||
|
||||
Reference in New Issue
Block a user