Skip to content

Commit

Permalink
Merge pull request #1608 from daizhenyu/develop-xds-route-930
Browse files Browse the repository at this point in the history
xds framework util
  • Loading branch information
Sherlockhan authored Sep 3, 2024
2 parents a61202c + 88f8654 commit a3abf86
Show file tree
Hide file tree
Showing 8 changed files with 966 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* 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 io.sermant.core.utils.StringUtils;

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-08-22
**/
public class CdsProtocolTransformer {
private static final int CLUSTER_SUBSET_INDEX = 2;

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

private static final Map<LbPolicy, XdsLbPolicy> LB_POLICY_MAPPING = new HashMap<>();

static {
LB_POLICY_MAPPING.put(LbPolicy.RANDOM, XdsLbPolicy.RANDOM);
LB_POLICY_MAPPING.put(LbPolicy.ROUND_ROBIN, XdsLbPolicy.ROUND_ROBIN);
LB_POLICY_MAPPING.put(LbPolicy.LEAST_REQUEST, XdsLbPolicy.LEAST_REQUEST);
LB_POLICY_MAPPING.put(LbPolicy.RING_HASH, XdsLbPolicy.RING_HASH);
LB_POLICY_MAPPING.put(LbPolicy.MAGLEV, XdsLbPolicy.MAGLEV);
}

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 -> !StringUtils.isEmpty(xdsCluster.getServiceName()))
.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(StringUtils.EMPTY)) {
return clusterName;
}
}
return StringUtils.EMPTY;
}

private static XdsLbPolicy parseClusterLbPolicy(LbPolicy lbPolicy) {
return LB_POLICY_MAPPING.getOrDefault(lbPolicy, XdsLbPolicy.UNRECOGNIZED);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* 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.List;
import java.util.Objects;
import java.util.Optional;
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-08-22
**/
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) {
return listeners.stream()
.filter(Objects::nonNull)
.flatMap(listener -> listener.getFilterChainsList().stream())
.flatMap(e -> e.getFiltersList().stream())
.map(Filter::getTypedConfig)
.map(LdsProtocolTransformer::unpackHttpConnectionManager)
.filter(Optional::isPresent)
.map(Optional::get)
.map(httpConnectionManager -> {
XdsHttpConnectionManager xdsHcm = new XdsHttpConnectionManager();
xdsHcm.setRouteConfigName(httpConnectionManager.getRds().getRouteConfigName());
return xdsHcm;
})
.collect(Collectors.toList());
}

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 a3abf86

Please sign in to comment.