Skip to content

Commit

Permalink
xds route and lb util
Browse files Browse the repository at this point in the history
Signed-off-by: daizhenyu <[email protected]>
  • Loading branch information
daizhenyu committed Aug 30, 2024
1 parent 378b8e7 commit 740c75d
Show file tree
Hide file tree
Showing 8 changed files with 965 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
*
* 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
*
* 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 io.sermant.implement.service.xds.utils;

import io.envoyproxy.envoy.config.cluster.v3.Cluster;
import io.envoyproxy.envoy.config.cluster.v3.Cluster.LbPolicy;
import io.sermant.core.service.xds.entity.XdsCluster;
import io.sermant.core.service.xds.entity.XdsLbPolicy;
import io.sermant.core.service.xds.entity.XdsServiceCluster;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
* Convert cds protocol data to Sermant data model
*
* @author daizhenyu
* @since 2024-05-10
**/
public class CdsProtocolTransformer {
private static final int CLUSTER_SUBSET_INDEX = 2;

private static final String VERTICAL_LINE_SEPARATOR = "\\|";

private CdsProtocolTransformer() {
}

/**
* get the mapping between service name of k8s and cluster of istio
*
* @param clusters clusters
* @return XdsServiceCluster map
*/
public static Map<String, XdsServiceCluster> getServiceClusters(List<Cluster> clusters) {
Map<String, Set<XdsCluster>> xdsClusters = clusters.stream()
.filter(Objects::nonNull)
.map(cluster -> parseCluster(cluster))
.filter(xdsCluster -> xdsCluster.getServiceName() != null)
.collect(Collectors.groupingBy(
XdsCluster::getServiceName,
Collectors.toSet()
));
Map<String, XdsServiceCluster> xdsServiceClusterMap = new HashMap<>();
for (Entry<String, Set<XdsCluster>> clusterEntry : xdsClusters.entrySet()) {
XdsServiceCluster serviceCluster = new XdsServiceCluster();
serviceCluster.setBaseClusterName(getServiceBaseClusterName(clusterEntry.getValue()));
Map<String, XdsCluster> clusterMap = clusterEntry.getValue().stream()
.collect(Collectors.toMap(
XdsCluster::getClusterName,
xdsCluster -> xdsCluster
));
serviceCluster.setClusters(clusterMap);
xdsServiceClusterMap.put(clusterEntry.getKey(), serviceCluster);
}
return xdsServiceClusterMap;
}

private static XdsCluster parseCluster(Cluster cluster) {
XdsCluster xdsCluster = new XdsCluster();
Optional<String> serviceNameFromCluster = XdsCommonUtils.getServiceNameFromCluster(cluster.getName());
if (!serviceNameFromCluster.isPresent()) {
return xdsCluster;
}
xdsCluster.setClusterName(cluster.getName());
xdsCluster.setServiceName(serviceNameFromCluster.get());
xdsCluster.setLocalityLb(cluster.getCommonLbConfig().hasLocalityWeightedLbConfig());
xdsCluster.setLbPolicy(parseClusterLbPolicy(cluster.getLbPolicy()));
return xdsCluster;
}

private static String getServiceBaseClusterName(Set<XdsCluster> xdsClusters) {
for (XdsCluster cluster : xdsClusters) {
String clusterName = cluster.getClusterName();
String[] splitCluster = clusterName.split(VERTICAL_LINE_SEPARATOR);
if (splitCluster[CLUSTER_SUBSET_INDEX].equals("")) {
return clusterName;
}
}
return "";
}

private static XdsLbPolicy parseClusterLbPolicy(LbPolicy lbPolicy) {
if (lbPolicy == LbPolicy.RANDOM) {
return XdsLbPolicy.RANDOM;
}
if (lbPolicy == LbPolicy.ROUND_ROBIN) {
return XdsLbPolicy.ROUND_ROBIN;
}
if (lbPolicy == LbPolicy.LEAST_REQUEST) {
return XdsLbPolicy.LEAST_REQUEST;
}
if (lbPolicy == LbPolicy.RING_HASH) {
return XdsLbPolicy.RING_HASH;
}
if (lbPolicy == LbPolicy.MAGLEV) {
return XdsLbPolicy.MAGLEV;
}
return XdsLbPolicy.UNRECOGNIZED;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
*
* 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
*
* 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 io.sermant.implement.service.xds.utils;

import com.google.protobuf.Any;
import com.google.protobuf.InvalidProtocolBufferException;

import io.envoyproxy.envoy.config.listener.v3.Filter;
import io.envoyproxy.envoy.config.listener.v3.Listener;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
import io.sermant.core.common.LoggerFactory;
import io.sermant.core.service.xds.entity.XdsHttpConnectionManager;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
* Convert lds protocol data to Sermant data model
*
* @author daizhenyu
* @since 2024-05-10
**/
public class LdsProtocolTransformer {
private static final Logger LOGGER = LoggerFactory.getLogger();

private LdsProtocolTransformer() {
}

/**
* get HttpConnectionManager
*
* @param listeners listeners
* @return HttpConnectionManager list
*/
public static List<XdsHttpConnectionManager> getHttpConnectionManager(List<Listener> listeners) {
Set<Any> rawHcm = listeners.stream()
.filter(Objects::nonNull)
.flatMap(listener -> listener.getFilterChainsList().stream())
.flatMap(e -> e.getFiltersList().stream())
.map(Filter::getTypedConfig)
.collect(Collectors.toSet());
List<XdsHttpConnectionManager> xdsHcms = new ArrayList<>();
for (Any any : rawHcm) {
Optional<HttpConnectionManager> httpConnectionManager = unpackHttpConnectionManager(any);
if (httpConnectionManager.isPresent()) {
XdsHttpConnectionManager xdsHcm = new XdsHttpConnectionManager();
xdsHcm.setRouteConfigName(httpConnectionManager.get().getRds().getRouteConfigName());
xdsHcms.add(xdsHcm);
}
}
return xdsHcms;
}

private static Optional<HttpConnectionManager> unpackHttpConnectionManager(Any any) {
try {
if (!any.is(HttpConnectionManager.class)) {
return Optional.empty();
}
return Optional.of(any.unpack(HttpConnectionManager.class));
} catch (InvalidProtocolBufferException e) {
LOGGER.log(Level.SEVERE, "Decode resource to HttpConnectionManager failed.", e);
return Optional.empty();
}
}
}
Loading

0 comments on commit 740c75d

Please sign in to comment.