Skip to content

Commit

Permalink
[thrift_proxy] Add metadata_match to RouteAction and WeightedClusters (
Browse files Browse the repository at this point in the history
…#4402)

This change adds the ability to attach metadata to the clusters and weighted clusters to allow users to filter a down to instances that match metadata criteria provided. This is used only when the subset load balancer is enabled and leverages what exists already for http metadata matching.

Changes include:
- construct MetadataMatchCriteria objects from protobufs
- expose through Thrift::Router::RouteEntry and use in router impl

Risk Level: LOW
Testing: tests, new and old, pass
Docs Changes: added description for new proto fields. docs build successfully.
Release Notes: n/a

Signed-off-by: Brian Ramos <[email protected]>
  • Loading branch information
brirams authored and zuercher committed Sep 14, 2018
1 parent b0ff481 commit c32aed9
Show file tree
Hide file tree
Showing 8 changed files with 332 additions and 3 deletions.
16 changes: 16 additions & 0 deletions api/envoy/config/filter/network/thrift_proxy/v2alpha1/route.proto
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ message RouteAction {
// assigned to each cluster.
WeightedCluster weighted_clusters = 2;
}

// Optional endpoint metadata match criteria used by the subset load balancer. Only endpoints in
// the upstream cluster with metadata matching what is set in this field will be considered.
// Note that this will be merged with what's provided in :ref: `WeightedCluster.MetadataMatch
// <envoy_api_field_config.filter.network.thrift_proxy.v2alpha1.WeightedCluster.ClusterWeight.metadata_match>`,
// with values there taking precedence. Keys and values should be provided under the "envoy.lb"
// metadata key.
envoy.api.v2.core.Metadata metadata_match = 3;
}

// Allows for specification of multiple upstream clusters along with weights that indicate the
Expand All @@ -98,6 +106,14 @@ message WeightedCluster {
// weight. The sum of weights across all entries in the clusters array determines the total
// weight.
google.protobuf.UInt32Value weight = 2 [(validate.rules).uint32.gte = 1];

// Optional endpoint metadata match criteria used by the subset load balancer. Only endpoints in
// the upstream cluster with metadata matching what is set in this field, combined with what's
// provided in :ref: `RouteAction's metadata_match
// <envoy_api_field_config.filter.network.thrift_proxy.v2alpha1.RouteAction.metadata_match>`,
// will be considered. Values here will take precedence. Keys and values should be provided
// under the "envoy.lb" metadata key.
envoy.api.v2.core.Metadata metadata_match = 3;
}

// Specifies one or more upstream clusters associated with the route.
Expand Down
2 changes: 2 additions & 0 deletions source/extensions/filters/network/thrift_proxy/router/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ envoy_cc_library(
hdrs = ["router.h"],
external_deps = ["abseil_optional"],
deps = [
"//include/envoy/router:router_interface",
"//source/extensions/filters/network/thrift_proxy:metadata_lib",
],
)
Expand All @@ -43,6 +44,7 @@ envoy_cc_library(
"//include/envoy/upstream:thread_local_cluster_interface",
"//source/common/common:logger_lib",
"//source/common/http:header_utility_lib",
"//source/common/router:metadatamatchcriteria_lib",
"//source/common/upstream:load_balancer_lib",
"//source/extensions/filters/network:well_known_names",
"//source/extensions/filters/network/thrift_proxy:app_exception_lib",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <memory>
#include <string>

#include "envoy/router/router.h"

#include "extensions/filters/network/thrift_proxy/metadata.h"

namespace Envoy {
Expand All @@ -22,6 +24,12 @@ class RouteEntry {
* @return const std::string& the upstream cluster that owns the route.
*/
virtual const std::string& clusterName() const PURE;

/**
* @return MetadataMatchCriteria* the metadata that a subset load balancer should match when
* selecting an upstream host
*/
virtual const Envoy::Router::MetadataMatchCriteria* metadataMatchCriteria() const PURE;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "envoy/upstream/thread_local_cluster.h"

#include "common/common/utility.h"
#include "common/router/metadatamatchcriteria_impl.h"

#include "extensions/filters/network/thrift_proxy/app_exception_impl.h"
#include "extensions/filters/network/well_known_names.h"
Expand All @@ -22,12 +23,21 @@ RouteEntryImplBase::RouteEntryImplBase(
config_headers_.push_back(header_map);
}

if (route.route().has_metadata_match()) {
const auto filter_it = route.route().metadata_match().filter_metadata().find(
Envoy::Config::MetadataFilters::get().ENVOY_LB);
if (filter_it != route.route().metadata_match().filter_metadata().end()) {
metadata_match_criteria_.reset(
new Envoy::Router::MetadataMatchCriteriaImpl(filter_it->second));
}
}

if (route.route().cluster_specifier_case() ==
envoy::config::filter::network::thrift_proxy::v2alpha1::RouteAction::kWeightedClusters) {

total_cluster_weight_ = 0UL;
for (const auto& cluster : route.route().weighted_clusters().clusters()) {
std::unique_ptr<WeightedClusterEntry> cluster_entry(new WeightedClusterEntry(cluster));
std::unique_ptr<WeightedClusterEntry> cluster_entry(new WeightedClusterEntry(*this, cluster));
weighted_clusters_.emplace_back(std::move(cluster_entry));
total_cluster_weight_ += weighted_clusters_.back()->clusterWeight();
}
Expand Down Expand Up @@ -69,10 +79,25 @@ bool RouteEntryImplBase::headersMatch(const Http::HeaderMap& headers) const {
}

RouteEntryImplBase::WeightedClusterEntry::WeightedClusterEntry(
const RouteEntryImplBase& parent,
const envoy::config::filter::network::thrift_proxy::v2alpha1::WeightedCluster_ClusterWeight&
cluster)
: cluster_name_(cluster.name()),
cluster_weight_(PROTOBUF_GET_WRAPPED_REQUIRED(cluster, weight)) {}
: parent_(parent), cluster_name_(cluster.name()),
cluster_weight_(PROTOBUF_GET_WRAPPED_REQUIRED(cluster, weight)) {
if (cluster.has_metadata_match()) {
const auto filter_it = cluster.metadata_match().filter_metadata().find(
Envoy::Config::MetadataFilters::get().ENVOY_LB);
if (filter_it != cluster.metadata_match().filter_metadata().end()) {
if (parent.metadata_match_criteria_) {
metadata_match_criteria_ =
parent.metadata_match_criteria_->mergeMatchCriteria(filter_it->second);
} else {
metadata_match_criteria_.reset(
new Envoy::Router::MetadataMatchCriteriaImpl(filter_it->second));
}
}
}
}

MethodNameRouteEntryImpl::MethodNameRouteEntryImpl(
const envoy::config::filter::network::thrift_proxy::v2alpha1::Route& route)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <vector>

#include "envoy/config/filter/network/thrift_proxy/v2alpha1/thrift_proxy.pb.h"
#include "envoy/router/router.h"
#include "envoy/tcp/conn_pool.h"
#include "envoy/upstream/load_balancer.h"

Expand Down Expand Up @@ -34,6 +35,10 @@ class RouteEntryImplBase : public RouteEntry,
// Router::RouteEntry
const std::string& clusterName() const override;

const Envoy::Router::MetadataMatchCriteria* metadataMatchCriteria() const override {
return metadata_match_criteria_.get();
}

// Router::Route
const RouteEntry* routeEntry() const override;

Expand All @@ -48,27 +53,38 @@ class RouteEntryImplBase : public RouteEntry,
class WeightedClusterEntry : public RouteEntry, public Route {
public:
WeightedClusterEntry(
const RouteEntryImplBase& parent,
const envoy::config::filter::network::thrift_proxy::v2alpha1::WeightedCluster_ClusterWeight&
cluster);

uint64_t clusterWeight() const { return cluster_weight_; }

// Router::RouteEntry
const std::string& clusterName() const override { return cluster_name_; }
const Envoy::Router::MetadataMatchCriteria* metadataMatchCriteria() const override {
if (metadata_match_criteria_) {
return metadata_match_criteria_.get();
}

return parent_.metadataMatchCriteria();
}

// Router::Route
const RouteEntry* routeEntry() const override { return this; }

private:
const RouteEntryImplBase& parent_;
const std::string cluster_name_;
const uint64_t cluster_weight_;
Envoy::Router::MetadataMatchCriteriaConstPtr metadata_match_criteria_;
};
typedef std::shared_ptr<WeightedClusterEntry> WeightedClusterEntrySharedPtr;

const std::string cluster_name_;
std::vector<Http::HeaderUtility::HeaderData> config_headers_;
std::vector<WeightedClusterEntrySharedPtr> weighted_clusters_;
uint64_t total_cluster_weight_;
Envoy::Router::MetadataMatchCriteriaConstPtr metadata_match_criteria_;
};

typedef std::shared_ptr<const RouteEntryImplBase> RouteEntryImplBaseConstSharedPtr;
Expand Down Expand Up @@ -138,6 +154,12 @@ class Router : public Tcp::ConnectionPool::UpstreamCallbacks,

// Upstream::LoadBalancerContext
const Network::Connection* downstreamConnection() const override;
const Envoy::Router::MetadataMatchCriteria* metadataMatchCriteria() override {
if (route_entry_) {
return route_entry_->metadataMatchCriteria();
}
return nullptr;
}

// Tcp::ConnectionPool::UpstreamCallbacks
void onUpstreamData(Buffer::Instance& data, bool end_stream) override;
Expand Down
1 change: 1 addition & 0 deletions test/extensions/filters/network/thrift_proxy/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ envoy_extension_cc_test(
deps = [
":utility_lib",
"//source/extensions/filters/network/thrift_proxy/router:config",
"//source/extensions/filters/network/thrift_proxy/router:router_interface",
"//source/extensions/filters/network/thrift_proxy/router:router_lib",
"//test/test_common:utility_lib",
],
Expand Down
3 changes: 3 additions & 0 deletions test/extensions/filters/network/thrift_proxy/mocks.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "envoy/router/router.h"

#include "extensions/filters/network/thrift_proxy/conn_manager.h"
#include "extensions/filters/network/thrift_proxy/conn_state.h"
#include "extensions/filters/network/thrift_proxy/filters/filter.h"
Expand Down Expand Up @@ -239,6 +241,7 @@ class MockRouteEntry : public RouteEntry {

// ThriftProxy::Router::RouteEntry
MOCK_CONST_METHOD0(clusterName, const std::string&());
MOCK_CONST_METHOD0(metadataMatchCriteria, const Envoy::Router::MetadataMatchCriteria*());
};

class MockRoute : public Route {
Expand Down
Loading

0 comments on commit c32aed9

Please sign in to comment.