GH-883 Add support for filtering out ineligible functions

Resolves #883
This commit is contained in:
Oleg Zhurakousky
2022-06-13 15:46:42 +02:00
parent a1a3f5b343
commit 78dea0aad7
5 changed files with 90 additions and 1 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);