Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ISSUE #4834] Add protocol exclusive fields filter for /v2/configuration endpoint #4835

Merged
merged 4 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static <T> T mapToObject(Map<String, Object> map, Class<T> beanClass) {
return null;
}
Object obj = OBJECT_MAPPER.convertValue(map, beanClass);
return (T) obj;
return beanClass.cast(obj);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
import com.alibaba.fastjson2.JSONWriter;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Data
public abstract class AbstractHttpHandler implements HttpHandler {

Expand Down Expand Up @@ -83,6 +85,12 @@ protected void writeUnauthorized(ChannelHandlerContext ctx, String message) {
writeJson(ctx, json, HttpResponseStatus.UNAUTHORIZED);
}

protected void writeInternalServerError(ChannelHandlerContext ctx, String message) {
Result<String> result = new Result<>(message);
String json = JSON.toJSONString(result, JSONWriter.Feature.WriteNulls);
writeJson(ctx, json, HttpResponseStatus.INTERNAL_SERVER_ERROR);
}

/**
* Use {@link HttpResponseUtils#buildHttpResponse} to build {@link HttpResponse} param.
*/
Expand All @@ -92,25 +100,36 @@ protected void write(ChannelHandlerContext ctx, HttpResponse response) {

@Override
public void handle(HttpRequest httpRequest, ChannelHandlerContext ctx) throws Exception {
switch (HttpMethod.valueOf(httpRequest.method().name())) {
case OPTIONS:
preflight(ctx);
break;
case GET:
get(httpRequest, ctx);
break;
case POST:
post(httpRequest, ctx);
break;
case PUT:
put(httpRequest, ctx);
break;
case DELETE:
delete(httpRequest, ctx);
break;
default:
// do nothing
break;
try {
switch (HttpMethod.valueOf(httpRequest.method().name())) {
case OPTIONS:
preflight(ctx);
break;
case GET:
get(httpRequest, ctx);
break;
case POST:
post(httpRequest, ctx);
break;
case PUT:
put(httpRequest, ctx);
break;
case DELETE:
delete(httpRequest, ctx);
break;
default: // do nothing
}
} catch (RuntimeException e) {
StackTraceElement element = e.getStackTrace()[0];
String className = element.getClassName();
String handlerName = className.substring(className.lastIndexOf(".") + 1);
if (e instanceof IllegalArgumentException) {
log.warn("Admin endpoint {}:{} - {}", handlerName, element.getLineNumber(), e.getMessage());
writeBadRequest(ctx, e.getMessage());
} else {
log.error("Admin endpoint {}:{} - {}", handlerName, element.getLineNumber(), e.getMessage(), e);
writeInternalServerError(ctx, e.getMessage());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@

public class AdminHandlerManager {

private EventMeshServer eventMeshServer;

private EventMeshTCPServer eventMeshTCPServer;

private EventMeshHTTPServer eventMeshHTTPServer;
Expand All @@ -71,9 +73,10 @@ public class AdminHandlerManager {
private final Map<String, HttpHandler> httpHandlerMap = new ConcurrentHashMap<>();

public AdminHandlerManager(EventMeshServer eventMeshServer) {
this.eventMeshServer = eventMeshServer;
this.eventMeshTCPServer = eventMeshServer.getEventMeshTCPServer();
this.eventMeshGrpcServer = eventMeshServer.getEventMeshGrpcServer();
this.eventMeshHTTPServer = eventMeshServer.getEventMeshHTTPServer();
this.eventMeshTCPServer = eventMeshServer.getEventMeshTCPServer();
this.eventMeshMetaStorage = eventMeshServer.getMetaStorage();
this.adminWebHookConfigOperationManage = eventMeshTCPServer.getAdminWebHookConfigOperationManage();
}
Expand Down Expand Up @@ -112,6 +115,7 @@ public void registerHttpHandler() {

// v2 endpoints
initHandler(new ConfigurationHandler(
eventMeshServer.getConfiguration(),
eventMeshTCPServer.getEventMeshTCPConfiguration(),
eventMeshHTTPServer.getEventMeshHttpConfiguration(),
eventMeshGrpcServer.getEventMeshGrpcConfiguration()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.filter.Filter;
import com.alibaba.fastjson2.filter.NameFilter;
import com.alibaba.fastjson2.filter.PropertyFilter;
import com.alibaba.fastjson2.filter.ValueFilter;

import lombok.extern.slf4j.Slf4j;
Expand All @@ -56,6 +57,7 @@
@EventMeshHttpHandler(path = "/v2/configuration")
public class ConfigurationHandler extends AbstractHttpHandler {

private final CommonConfiguration commonConfiguration;
private final EventMeshTCPConfiguration eventMeshTCPConfiguration;
private final EventMeshHTTPConfiguration eventMeshHTTPConfiguration;
private final EventMeshGrpcConfiguration eventMeshGrpcConfiguration;
Expand All @@ -68,10 +70,12 @@ public class ConfigurationHandler extends AbstractHttpHandler {
* @param eventMeshGrpcConfiguration the gRPC configuration for EventMesh
*/
public ConfigurationHandler(
CommonConfiguration commonConfiguration,
EventMeshTCPConfiguration eventMeshTCPConfiguration,
EventMeshHTTPConfiguration eventMeshHTTPConfiguration,
EventMeshGrpcConfiguration eventMeshGrpcConfiguration) {
super();
this.commonConfiguration = commonConfiguration;
this.eventMeshTCPConfiguration = eventMeshTCPConfiguration;
this.eventMeshHTTPConfiguration = eventMeshHTTPConfiguration;
this.eventMeshGrpcConfiguration = eventMeshGrpcConfiguration;
Expand All @@ -85,34 +89,51 @@ public ConfigurationHandler(
* <p>When {@code properties}, the field names are returned in Properties format;
* <p>When {@code bean}, the field names themselves are used as json keys.
* </li>
* <li>
* {@code configs}: String; Optional, DefaultValue: {@code exclusive}, SelectableValue: {@code all}.
* <p>When {@code exclusive}, protocol-specific configurations will only contain protocol-exclusive fields
* and won't contain any {@link CommonConfiguration} fields;
* <p>When {@code all}, protocol-specific configurations will contain all fields, including those in {@link CommonConfiguration}.
* </li>
* </ul>
*/
@Override
protected void get(HttpRequest httpRequest, ChannelHandlerContext ctx) {
String format = HttpRequestUtil.getQueryParam(httpRequest, "format", "properties");

Filter[] filters;
if (format.equals("properties")) {
filters = new Filter[] {new ConfigFieldFilter(), new IPAddressToStringFilter()};
} else if (format.equals("bean")) {
filters = new Filter[] {new IPAddressToStringFilter()};
} else {
log.warn("Invalid format param: {}", format);
writeBadRequest(ctx, "Invalid format param: " + format);
return;
String configs = HttpRequestUtil.getQueryParam(httpRequest, "configs", "exclusive");

List<Filter> filters = new ArrayList<>();
switch (configs) {
case "exclusive":
filters.add(new SuperClassFieldFilter());
break;
case "all": break;
default:
throw new IllegalArgumentException("Invalid param 'configs': " + configs);
}
switch (format) {
case "properties":
filters.add(new ConfigFieldFilter());
break;
case "bean": break;
default:
throw new IllegalArgumentException("Invalid param 'format': " + format);
}
filters.add(new IPAddressToStringFilter());

GetConfigurationResponse getConfigurationResponse = new GetConfigurationResponse(
commonConfiguration,
eventMeshTCPConfiguration,
eventMeshHTTPConfiguration,
eventMeshGrpcConfiguration
eventMeshGrpcConfiguration,
"v1.10.0-release" // TODO get version number after merging https://github.com/apache/eventmesh/pull/4055
);
String json = JSON.toJSONString(Result.success(getConfigurationResponse), filters);
String json = JSON.toJSONString(Result.success(getConfigurationResponse), filters.toArray(new Filter[0]));
writeJson(ctx, json);
}

/**
* For each member of {@link EventMeshTCPConfiguration}, {@link EventMeshHTTPConfiguration}, and {@link EventMeshGrpcConfiguration},
* For each member of configuration classes,
* the value of the {@link ConfigField} annotation for each field is obtained through reflection,
* and then concatenated with the configuration prefix in the {@link Config} annotation to serve as the JSON key for this field.
* <p>
Expand Down Expand Up @@ -155,6 +176,39 @@ private Field findFieldInClassHierarchy(Class<?> clazz, String fieldName) throws
}
}

/**
* For each member of {@link EventMeshTCPConfiguration}, {@link EventMeshHTTPConfiguration}, and {@link EventMeshGrpcConfiguration},
* if the {@code name} is a member that exists in {@link CommonConfiguration} class, it will be skipped.
*/
static class SuperClassFieldFilter implements PropertyFilter {
@Override
public boolean apply(Object object, String name, Object value) {
try {
Field field = findFieldInClassNonHierarchy(object.getClass(), name);
return field != null;
} catch (NoSuchFieldException e) {
log.error("Failed to get field {} from object {}", name, object, e);
}
return true;
}

/**
* If a field of a subclass exists in the superclass, return null, causing FastJSON to skip this field.
*/
private Field findFieldInClassNonHierarchy(Class<?> clazz, String fieldName) throws NoSuchFieldException {
try {
return clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
Class<?> superclass = clazz.getSuperclass();
if (superclass == null) {
throw e;
} else {
return null;
}
}
}
}

/**
* {@link IPAddress} can't be serialized directly by FastJSON,
* so this filter converts {@link IPAddress} objects to their string representation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package org.apache.eventmesh.runtime.admin.response.v2;

import org.apache.eventmesh.common.config.CommonConfiguration;
import org.apache.eventmesh.runtime.configuration.EventMeshGrpcConfiguration;
import org.apache.eventmesh.runtime.configuration.EventMeshHTTPConfiguration;
import org.apache.eventmesh.runtime.configuration.EventMeshTCPConfiguration;
Expand All @@ -30,7 +31,9 @@
@AllArgsConstructor
public class GetConfigurationResponse {

private CommonConfiguration commonConfiguration;
private EventMeshTCPConfiguration eventMeshTCPConfiguration;
private EventMeshHTTPConfiguration eventMeshHTTPConfiguration;
private EventMeshGrpcConfiguration eventMeshGrpcConfiguration;
private String eventMeshVersion;
}
Loading