com.alibaba.cloud.governance.opensergo.OpenSergoTrafficRouterParser Maven / Gradle / Ivy
/*
* Copyright 2022-2023 the original author or authors.
*
* Licensed 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
*
* https://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 com.alibaba.cloud.governance.opensergo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.cloud.commons.governance.routing.MatchService;
import com.alibaba.cloud.commons.governance.routing.RoutingRule;
import com.alibaba.cloud.commons.governance.routing.UnifiedRoutingDataStructure;
import com.alibaba.cloud.commons.governance.routing.rule.HeaderRoutingRule;
import com.alibaba.cloud.commons.governance.routing.rule.Rule;
import com.alibaba.cloud.commons.governance.routing.rule.UrlRoutingRule;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.cloud.commons.matcher.StringMatcher;
import com.alibaba.cloud.commons.matcher.StringMatcherType;
import com.alibaba.cloud.governance.opensergo.util.ConvUtils;
import com.google.protobuf.InvalidProtocolBufferException;
import io.envoyproxy.envoy.config.route.v3.ClusterSpecifierPlugin;
import io.envoyproxy.envoy.config.route.v3.HeaderMatcher;
import io.envoyproxy.envoy.config.route.v3.QueryParameterMatcher;
import io.envoyproxy.envoy.config.route.v3.Route;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
import io.envoyproxy.envoy.config.route.v3.RouteMatch;
import io.envoyproxy.envoy.config.route.v3.VirtualHost;
import io.envoyproxy.envoy.config.route.v3.WeightedCluster;
import io.opensergo.proto.router.v1.ClusterFallbackConfig_ClusterConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author panxiaojun233
* @author
* @since 2.2.10-RC1
*/
public class OpenSergoTrafficRouterParser {
protected static final Logger log = LoggerFactory
.getLogger(OpenSergoTrafficRouterParser.class);
public OpenSergoTrafficRouterParser() {
}
/**
* transform rds RouterConfig list to spring cloud alibaba router data list.
* @param routeConfigurations the routerConfig list from OpenSergo control plane.
* @return spring cloud alibaba router rules.
* @throws InvalidProtocolBufferException transform exception.
*/
public Collection resolveLabelRouting(
List routeConfigurations)
throws InvalidProtocolBufferException {
if (routeConfigurations == null) {
return new ArrayList<>();
}
Map unifiedRouteDataStructures = new HashMap<>();
for (RouteConfiguration routeConfiguration : routeConfigurations) {
List virtualHosts = routeConfiguration.getVirtualHostsList();
for (VirtualHost virtualHost : virtualHosts) {
UnifiedRoutingDataStructure unifiedRouteDataStructure = new UnifiedRoutingDataStructure();
String targetService = "";
String[] serviceAndPort = virtualHost.getName().split(":");
if (serviceAndPort.length > 0) {
targetService = serviceAndPort[0].split("\\.")[0];
}
unifiedRouteDataStructure.setTargetService(targetService);
List routes = virtualHost.getRoutesList();
RoutingRule labelRouteRule = getLabelRouteData(routes);
unifiedRouteDataStructure.setLabelRouteRule(labelRouteRule);
unifiedRouteDataStructures.put(
unifiedRouteDataStructure.getTargetService(),
unifiedRouteDataStructure);
}
}
return unifiedRouteDataStructures.values();
}
private RoutingRule getLabelRouteData(List routes)
throws InvalidProtocolBufferException {
List matchServices = new ArrayList<>();
RoutingRule labelRouteRule = new RoutingRule();
for (Route route : routes) {
ClusterSpecifierPlugin clusterSpecifierPlugin = route.getRoute()
.getInlineClusterSpecifierPlugin();
String cluster = "";
String fallbackCluster = "";
if (clusterSpecifierPlugin != null) {
ClusterFallbackConfig_ClusterConfig fallbackConfig = ConvUtils
.convFallbackClusterConfig(clusterSpecifierPlugin);
fallbackCluster = fallbackConfig.getFallbackCluster();
cluster = fallbackConfig.getRoutingCluster();
}
if (StringUtils.isEmpty(cluster)) {
cluster = route.getRoute().getCluster();
}
if (StringUtils.isNotEmpty(cluster)) {
MatchService matchService = null;
if (StringUtils.isNotEmpty(fallbackCluster)) {
matchService = getMatchService(route, cluster, 100,
getVersion(route, fallbackCluster));
}
else {
matchService = getMatchService(route, cluster, 100);
}
matchServices.add(matchService);
}
WeightedCluster weightedCluster = route.getRoute().getWeightedClusters();
for (WeightedCluster.ClusterWeight clusterWeight : weightedCluster
.getClustersList()) {
MatchService matchService = getMatchService(route,
clusterWeight.getName(), clusterWeight.getWeight().getValue());
matchServices.add(matchService);
}
}
labelRouteRule.setMatchRouteList(matchServices);
if (!matchServices.isEmpty()) {
labelRouteRule.setDefaultRouteVersion(
matchServices.get(matchServices.size() - 1).getVersion());
}
return labelRouteRule;
}
private MatchService getMatchService(Route route, String cluster, int weight) {
return getMatchService(route, cluster, weight, null);
}
private MatchService getMatchService(Route route, String cluster, int weight,
String fallback) {
String version = getVersion(route, cluster);
MatchService matchService = new MatchService();
matchService.setVersion(version);
matchService.setRuleList(match2RouteRules(route.getMatch()));
matchService.setWeight(weight);
if (StringUtils.isNotEmpty(fallback)) {
matchService.setFallback(fallback);
}
return matchService;
}
private String getVersion(Route route, String cluster) {
String version = "";
try {
String[] info = cluster.split("\\|");
version = info[2];
}
catch (Exception e) {
log.error("invalid cluster info for route {}", route.getName());
}
return version;
}
private List match2RouteRules(RouteMatch routeMatch) {
List routeRules = new ArrayList<>();
for (HeaderMatcher headerMatcher : routeMatch.getHeadersList()) {
HeaderRoutingRule headerRule = headerMatcher2HeaderRule(headerMatcher);
if (headerRule != null) {
routeRules.add(headerRule);
}
}
for (QueryParameterMatcher parameterMatcher : routeMatch
.getQueryParametersList()) {
UrlRoutingRule.ParameterRoutingRule parameterRoutingRule = parameterMatcher2ParameterRule(
parameterMatcher);
if (parameterRoutingRule != null) {
routeRules.add(parameterRoutingRule);
}
}
UrlRoutingRule.PathRoutingRule path = new UrlRoutingRule.PathRoutingRule();
switch (routeMatch.getPathSpecifierCase()) {
case PREFIX:
path.setCondition(StringMatcherType.PREFIX.toString());
path.setValue(routeMatch.getPrefix());
break;
case PATH:
path.setCondition(StringMatcherType.EXACT.toString());
path.setValue(routeMatch.getPath());
break;
case SAFE_REGEX:
path.setCondition(StringMatcherType.REGEX.toString());
path.setValue(routeMatch.getSafeRegex().getRegex());
break;
default:
// unknown type
path = null;
}
if (path != null) {
routeRules.add(path);
}
return routeRules;
}
private UrlRoutingRule.ParameterRoutingRule parameterMatcher2ParameterRule(
QueryParameterMatcher queryParameterMatcher) {
UrlRoutingRule.ParameterRoutingRule parameterRoutingRule = new UrlRoutingRule.ParameterRoutingRule();
StringMatcher stringMatcher = ConvUtils
.convStringMatcher(queryParameterMatcher.getStringMatch());
if (stringMatcher != null) {
parameterRoutingRule.setCondition(stringMatcher.getType().toString());
parameterRoutingRule.setKey(queryParameterMatcher.getName());
parameterRoutingRule.setValue(stringMatcher.getMatcher());
return parameterRoutingRule;
}
return null;
}
private HeaderRoutingRule headerMatcher2HeaderRule(HeaderMatcher headerMatcher) {
StringMatcher stringMatcher = ConvUtils
.convStringMatcher(ConvUtils.headerMatch2StringMatch(headerMatcher));
if (stringMatcher != null) {
HeaderRoutingRule headerRule = new HeaderRoutingRule();
headerRule.setCondition(stringMatcher.getType().toString());
headerRule.setKey(headerMatcher.getName());
headerRule.setValue(stringMatcher.getMatcher());
return headerRule;
}
return null;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy