-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Support api config source without cluster names #2999
Support api config source without cluster names #2999
Conversation
Signed-off-by: James Buckland <jbuckland@google.com>
8f7fc1b
to
6cafac9
Compare
@@ -5,6 +5,7 @@ | |||
#include "common/config/resources.h" | |||
#include "common/protobuf/protobuf.h" | |||
|
|||
#include "test/integration/fake_upstream.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I'll remove this. I was at one point attempting to mock an upstream target_uri.
@@ -190,18 +188,26 @@ INSTANTIATE_TEST_CASE_P(SubscriptionFactoryTestApiConfigSource, | |||
envoy::api::v2::core::ApiConfigSource::REST, | |||
envoy::api::v2::core::ApiConfigSource::GRPC)); | |||
|
|||
// TODO(jbuckland) add test case for ApiConfigSource::GRPC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I'll remove this. I had at one point removed envoy::api::v2::core::ApiConfigSource::GRPC
from the values block above.
source/common/config/utility.cc
Outdated
"envoy::api::v2::core::ConfigSource must have a singleton cluster name specified"); | ||
} | ||
if (api_config_source.api_type() == envoy::api::v2::core::ApiConfigSource::GRPC) { | ||
if (api_config_source.cluster_names().size() != 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also throw an exception if grpc_services().size() != 1
.
source/common/config/utility.cc
Outdated
"envoy::api::v2::core::ConfigSource must have a statically " | ||
"defined non-EDS cluster: '{}' does not exist, was added via api, or is an EDS cluster", | ||
cluster_name)); | ||
const auto& cluster_name = api_config_source.cluster_names()[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you meant here. You should have a condition here; if it's api_type() == GRPC && api_config_soures.grpc_service()[0].has_envoy_grpc()
then you can verify api_Config.grpc_Services()[0].envou_grpc().cluster_name()
.
"non-EDS cluster: 'eds_cluster' " | ||
"does not exist, was added via api, or is an EDS cluster"); | ||
if (api_config_source->api_type() == envoy::api::v2::core::ApiConfigSource::GRPC) { | ||
EXPECT_THROW_WITH_MESSAGE( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for subscription_factory_test
, we should go in and add additional tests to cover all the branches possible now in checkApiConfigSourceSubscriptionBackingCluster
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in d149e7f.
Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
…urceSubscriptionBackingCluster Signed-off-by: James Buckland <jbuckland@google.com>
…ps://github.com/ambuc/envoy into support-api_config_source-without-cluster_names Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
…g_source-without-cluster_names Signed-off-by: James Buckland <jbuckland@google.com>
…ster_names Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
source/common/config/utility.cc
Outdated
// TODO(htuch): Add support for multiple clusters, #1170. | ||
throw EnvoyException( | ||
"envoy::api::v2::core::ConfigSource must have a singleton cluster name specified"); | ||
bool is_grpc = (api_config_source.api_type() == envoy::api::v2::core::ApiConfigSource::GRPC); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: const bool
source/common/config/utility.cc
Outdated
} | ||
if (api_config_source.grpc_services().size() != 1) { | ||
throw EnvoyException( | ||
"envoy::api::v2::core::ConfigSource::GRPC must have a singleton grpc service specified"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: either "singleton grpc_services" or "single gRPC service".
source/common/config/utility.cc
Outdated
} else { | ||
if (api_config_source.grpc_services().size() != 0) { | ||
throw EnvoyException( | ||
"envoy::api::v2::core::ConfigSource must not have a grpc service specified"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
source/common/config/utility.cc
Outdated
} | ||
|
||
const auto& cluster_name = api_config_source.cluster_names()[0]; | ||
const std::string& cluster_name = | ||
is_grpc ? api_config_source.grpc_services()[0].envoy_grpc().cluster_name() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There needs to be another condition here on has_envoy_grpc()
. Some gRPC services will be configured with google_grpc
and won't have a cluster name.
source/common/config/utility.cc
Outdated
} | ||
grpc_service.MergeFrom(api_config_source.grpc_services(0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can skip this line now and pass grpc_service(0) directly into the below call to the factory method.
source/common/config/utility.cc
Outdated
|
||
if (api_config_source.grpc_services().empty()) { | ||
throw EnvoyException( | ||
fmt::format("Missing gRPC services in envoy::api::v2::core::ApiConfigSource: {}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems we have the same log messages as in checkApiConfigSourceSubscriptionBackingCluster. Can we refactor? Alternatively, can we expect checkApiConfigSourceSubscriptionBackingCluster to always be called before we get here and just put in some ASSERTs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. in source/common/upstream/cluster_manager_impl.cc
, we run factoryFor...
to reset load_stats_reporter_
, but we don't have a list of clusters to validate against. I could split up checkApiConfig...
into two bits, the first of which checks cluster_names() vs. grpc_services() (no list of clusters necessary), and the second of which does the actual validation. Does that sound like the right solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
"bar"); | ||
cluster_map.emplace("bar", cluster); | ||
envoy::api::v2::core::GrpcService expected_grpc_service_bar; | ||
expected_grpc_service_bar.mutable_envoy_grpc()->set_cluster_name("bar"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, this is a stub from when I was using EXPECT_CALL(cm_.async_client_manager_, factoryForGrpcService(ProtoEq(expected_grpc_service)...))
in all the test cases. I'll get rid of it here...
"foo"); | ||
cluster_map.emplace("foo", cluster); | ||
envoy::api::v2::core::GrpcService expected_grpc_service_foo; | ||
expected_grpc_service_foo.mutable_envoy_grpc()->set_cluster_name("foo"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... and here.
Upstream::ClusterManager::ClusterInfoMap cluster_map; | ||
Upstream::MockCluster cluster; | ||
cluster_map.emplace("eds_cluster", cluster); | ||
cluster_map.emplace("foo", cluster); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this lends clarity, seems a gratuitous rename.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't actually an eds cluster by default -- because it's a mock object, it defaults to the first enum in envoy::api::v2::Cluster::
, which is STATIC
. https://github.com/envoyproxy/data-plane-api/blob/master/envoy/api/v2/cds.proto#L67
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd make it static_cluster
then for clarity.
if (api_config_source->api_type() == envoy::api::v2::core::ApiConfigSource::GRPC) { | ||
EXPECT_THROW_WITH_MESSAGE( | ||
subscriptionFromConfigSource(config)->start({"foo"}, callbacks_), EnvoyException, | ||
"envoy::api::v2::core::ConfigSource::GRPC must not have a cluster name specified"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to setup this test to actually get the below behavior, by using grpc_services.envoy_grpc.cluster_name to specify cluster name in the gRPC case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll refactor all the SubscriptionFactoryTestApiConfigSource/*
tests to better fit this.
Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
…n-statically defined error instead Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
…iptionBackingCluster into checkApiConfigSourceNames and use it to validate inside factoryForGrpcApiConfigSource And various assorted testing changes to make this possible Signed-off-by: James Buckland <jbuckland@google.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM modulo nits and the missing coverage case. This is looking like a really nice cleanup.
source/common/config/utility.cc
Outdated
const bool is_grpc = | ||
(api_config_source.api_type() == envoy::api::v2::core::ApiConfigSource::GRPC); | ||
|
||
// we ought to validate the cluster name if and only if there is a cluster name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super tiny nit: Prefer having comment sentences begin with capital letters (here and below).
@@ -121,6 +121,13 @@ class Utility { | |||
*/ | |||
static void checkFilesystemSubscriptionBackingPath(const std::string& path); | |||
|
|||
/** | |||
* Check the grpc_services and cluster_names for API config sanity. Throws on error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use Doxygeen @throw
syntax here, grep around for examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 421a420.
EXPECT_CALL(cm_, clusters()).WillOnce(Return(cluster_map)); | ||
EXPECT_THROW_WITH_MESSAGE( | ||
subscriptionFromConfigSource(config), EnvoyException, | ||
"envoy::api::v2::core::ConfigSource::GRPC must have a single gRPC service specified"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need to change anything now that we have these tests, but I would probably approach testing by doing full branch coverage in a dedicated unit test for Utility::checkApiConfigSourceNames()
and then just do specific point tests in SubscriptionFactoryTest
for where behavior is more complex. I think what you have is fine though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good catch. The coverage report actually shows a hole in utility.cc
for a REST API with defined gRPC services. I won't refactor this entirely but I am going to add coverage for that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in bb137e7.
…rpc services Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rad, this is a really great cleanup.
)" This reverts commit 01e75f9. Discuession on #envoy-users revealed that this is going to break operationally for folks who are trying to roll forward binaries with the same config, there's no config that can work both before/after. Signed-off-by: Harvey Tuch <htuch@google.com>
This reverts commit 01e75f9. Discuession on #envoy-users revealed that this is going to break operationally for folks who are trying to roll forward binaries with the same config, there's no config that can work both before/after. Signed-off-by: Harvey Tuch <htuch@google.com>
…yproxy#2999)" (envoyproxy#3018)" This reverts commit fdcbe10. Signed-off-by: James Buckland <jbuckland@google.com>
This reverts #3018, which reverted #2999. Therefore this PR is similar to #2999, except that 77b292c allows REST/gRPC config mismatch errors to warn instead of throwing an error. Hopefully this solves the issue for users who were unable to roll forward their binaries while keeping the same config. Changelist for #2999: To support the deprecation of cluster_names in the api_config_source (#2860), I added a more verbose error in utility.cc for GRPC api_config_sources with any named clusters hunted down places in tests where api_config_source.cluster_names()[0] was implicitly used (assuming that API would be GRPC and would have cluster names). renamed factoryForApiConfigSource to factoryForGrpcApiConfigSource, as it already implicitly returns a Grpc::AsyncClientFactoryPtr, and gave a more verbose error for when the user passes a config with cluster_names set. separated out checkApiConfigSourceSubscriptionBackingCluster into checkApiConfigSourceNames, which does the gRPC services v. cluster names validation, and - checkApiConfigSourceSubscriptionBackingCluster, which actually validates the cluster name against the clusters map. more completely covered the tests for the branching cases for non-gRPC API configs which happened to have grpc services defined. Risk Level: Low Testing: bazel test test/... all passed. Fixed #2680 Fixed #2902 Signed-off-by: James Buckland <jbuckland@google.com>
To support the deprecation of cluster_names in the api_config_source (#2860), I
utility.cc
for GRPCapi_config_sources
with any named clustersapi_config_source.cluster_names()[0]
was implicitly used (assuming that API would be GRPC and would have cluster names).factoryForApiConfigSource
tofactoryForGrpcApiConfigSource
, as it already implicitly returns aGrpc::AsyncClientFactoryPtr
, and gave a more verbose error for when the user passes a config withcluster_names
set.checkApiConfigSourceSubscriptionBackingCluster
intocheckApiConfigSourceNames
, which does the gRPC services v. cluster names validation, andcheckApiConfigSourceSubscriptionBackingCluster
, which actually validates the cluster name against the clusters map.Risk Level: Low
Testing:
bazel test test/...
all passed.Fixed #2680
Fixed #2902
Signed-off-by: James Buckland jbuckland@google.com