change CSDS to populate new generic_xds_configs field (#27794)

reviewable/pr26812/r10^2
Mark D. Roth 4 years ago committed by GitHub
parent 1c2361e816
commit 06b5061d35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 282
      src/core/ext/xds/xds_api.cc
  2. 6
      src/core/ext/xds/xds_api.h
  3. 17
      src/core/ext/xds/xds_client.cc
  4. 53
      src/proto/grpc/testing/xds/v3/csds.proto
  5. 397
      test/cpp/end2end/xds/xds_end2end_test.cc

@ -3782,6 +3782,7 @@ grpc_error_handle XdsApi::ParseLrsResponse(
}
namespace {
google_protobuf_Timestamp* GrpcMillisToTimestamp(const EncodingContext& context,
grpc_millis value) {
google_protobuf_Timestamp* timestamp =
@ -3792,218 +3793,6 @@ google_protobuf_Timestamp* GrpcMillisToTimestamp(const EncodingContext& context,
return timestamp;
}
envoy_admin_v3_UpdateFailureState* CreateUpdateFailureStateUpb(
const EncodingContext& context,
const XdsApi::ResourceMetadata* resource_metadata) {
auto* update_failure_state =
envoy_admin_v3_UpdateFailureState_new(context.arena);
envoy_admin_v3_UpdateFailureState_set_details(
update_failure_state,
StdStringToUpbString(resource_metadata->failed_details));
envoy_admin_v3_UpdateFailureState_set_version_info(
update_failure_state,
StdStringToUpbString(resource_metadata->failed_version));
envoy_admin_v3_UpdateFailureState_set_last_update_attempt(
update_failure_state,
GrpcMillisToTimestamp(context, resource_metadata->failed_update_time));
return update_failure_state;
}
void DumpLdsConfig(const EncodingContext& context,
const XdsApi::ResourceTypeMetadata& resource_type_metadata,
envoy_service_status_v3_PerXdsConfig* per_xds_config) {
upb_strview kLdsTypeUrlUpb = upb_strview_makez(XdsApi::kLdsTypeUrl);
auto* listener_config_dump =
envoy_service_status_v3_PerXdsConfig_mutable_listener_config(
per_xds_config, context.arena);
envoy_admin_v3_ListenersConfigDump_set_version_info(
listener_config_dump,
StdStringToUpbString(resource_type_metadata.version));
for (auto& p : resource_type_metadata.resource_metadata_map) {
absl::string_view name = p.first;
const XdsApi::ResourceMetadata* meta = p.second;
const upb_strview name_upb = StdStringToUpbString(name);
auto* dynamic_listener =
envoy_admin_v3_ListenersConfigDump_add_dynamic_listeners(
listener_config_dump, context.arena);
envoy_admin_v3_ListenersConfigDump_DynamicListener_set_name(
dynamic_listener, name_upb);
envoy_admin_v3_ListenersConfigDump_DynamicListener_set_client_status(
dynamic_listener, meta->client_status);
if (!meta->serialized_proto.empty()) {
// Set in-effective listeners
auto* dynamic_listener_state =
envoy_admin_v3_ListenersConfigDump_DynamicListener_mutable_active_state(
dynamic_listener, context.arena);
envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_version_info(
dynamic_listener_state, StdStringToUpbString(meta->version));
envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_last_updated(
dynamic_listener_state,
GrpcMillisToTimestamp(context, meta->update_time));
auto* listener_any =
envoy_admin_v3_ListenersConfigDump_DynamicListenerState_mutable_listener(
dynamic_listener_state, context.arena);
google_protobuf_Any_set_type_url(listener_any, kLdsTypeUrlUpb);
google_protobuf_Any_set_value(
listener_any, StdStringToUpbString(meta->serialized_proto));
}
if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
// Set error_state if NACKED
envoy_admin_v3_ListenersConfigDump_DynamicListener_set_error_state(
dynamic_listener, CreateUpdateFailureStateUpb(context, meta));
}
}
}
void DumpRdsConfig(const EncodingContext& context,
const XdsApi::ResourceTypeMetadata& resource_type_metadata,
envoy_service_status_v3_PerXdsConfig* per_xds_config) {
upb_strview kRdsTypeUrlUpb = upb_strview_makez(XdsApi::kRdsTypeUrl);
auto* route_config_dump =
envoy_service_status_v3_PerXdsConfig_mutable_route_config(per_xds_config,
context.arena);
for (auto& p : resource_type_metadata.resource_metadata_map) {
absl::string_view name = p.first;
const XdsApi::ResourceMetadata* meta = p.second;
const upb_strview name_upb = StdStringToUpbString(name);
auto* dynamic_route_config =
envoy_admin_v3_RoutesConfigDump_add_dynamic_route_configs(
route_config_dump, context.arena);
envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_client_status(
dynamic_route_config, meta->client_status);
auto* route_config_any =
envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_mutable_route_config(
dynamic_route_config, context.arena);
if (!meta->serialized_proto.empty()) {
// Set in-effective route configs
envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_version_info(
dynamic_route_config, StdStringToUpbString(meta->version));
envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_last_updated(
dynamic_route_config,
GrpcMillisToTimestamp(context, meta->update_time));
google_protobuf_Any_set_type_url(route_config_any, kRdsTypeUrlUpb);
google_protobuf_Any_set_value(
route_config_any, StdStringToUpbString(meta->serialized_proto));
} else {
// If there isn't a working route config, we still need to print the
// name.
auto* route_config =
envoy_config_route_v3_RouteConfiguration_new(context.arena);
envoy_config_route_v3_RouteConfiguration_set_name(route_config, name_upb);
size_t length;
char* bytes = envoy_config_route_v3_RouteConfiguration_serialize(
route_config, context.arena, &length);
google_protobuf_Any_set_type_url(route_config_any, kRdsTypeUrlUpb);
google_protobuf_Any_set_value(route_config_any,
upb_strview_make(bytes, length));
}
if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
// Set error_state if NACKED
envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_error_state(
dynamic_route_config, CreateUpdateFailureStateUpb(context, meta));
}
}
}
void DumpCdsConfig(const EncodingContext& context,
const XdsApi::ResourceTypeMetadata& resource_type_metadata,
envoy_service_status_v3_PerXdsConfig* per_xds_config) {
upb_strview kCdsTypeUrlUpb = upb_strview_makez(XdsApi::kCdsTypeUrl);
auto* cluster_config_dump =
envoy_service_status_v3_PerXdsConfig_mutable_cluster_config(
per_xds_config, context.arena);
envoy_admin_v3_ClustersConfigDump_set_version_info(
cluster_config_dump,
StdStringToUpbString(resource_type_metadata.version));
for (auto& p : resource_type_metadata.resource_metadata_map) {
absl::string_view name = p.first;
const XdsApi::ResourceMetadata* meta = p.second;
const upb_strview name_upb = StdStringToUpbString(name);
auto* dynamic_cluster =
envoy_admin_v3_ClustersConfigDump_add_dynamic_active_clusters(
cluster_config_dump, context.arena);
envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_client_status(
dynamic_cluster, meta->client_status);
auto* cluster_any =
envoy_admin_v3_ClustersConfigDump_DynamicCluster_mutable_cluster(
dynamic_cluster, context.arena);
if (!meta->serialized_proto.empty()) {
// Set in-effective clusters
envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_version_info(
dynamic_cluster, StdStringToUpbString(meta->version));
envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_last_updated(
dynamic_cluster, GrpcMillisToTimestamp(context, meta->update_time));
google_protobuf_Any_set_type_url(cluster_any, kCdsTypeUrlUpb);
google_protobuf_Any_set_value(
cluster_any, StdStringToUpbString(meta->serialized_proto));
} else {
// If there isn't a working cluster, we still need to print the name.
auto* cluster = envoy_config_cluster_v3_Cluster_new(context.arena);
envoy_config_cluster_v3_Cluster_set_name(cluster, name_upb);
size_t length;
char* bytes = envoy_config_cluster_v3_Cluster_serialize(
cluster, context.arena, &length);
google_protobuf_Any_set_type_url(cluster_any, kCdsTypeUrlUpb);
google_protobuf_Any_set_value(cluster_any,
upb_strview_make(bytes, length));
}
if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
// Set error_state if NACKED
envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_error_state(
dynamic_cluster, CreateUpdateFailureStateUpb(context, meta));
}
}
}
void DumpEdsConfig(const EncodingContext& context,
const XdsApi::ResourceTypeMetadata& resource_type_metadata,
envoy_service_status_v3_PerXdsConfig* per_xds_config) {
upb_strview kEdsTypeUrlUpb = upb_strview_makez(XdsApi::kEdsTypeUrl);
auto* endpoint_config_dump =
envoy_service_status_v3_PerXdsConfig_mutable_endpoint_config(
per_xds_config, context.arena);
for (auto& p : resource_type_metadata.resource_metadata_map) {
absl::string_view name = p.first;
const XdsApi::ResourceMetadata* meta = p.second;
const upb_strview name_upb = StdStringToUpbString(name);
auto* dynamic_endpoint =
envoy_admin_v3_EndpointsConfigDump_add_dynamic_endpoint_configs(
endpoint_config_dump, context.arena);
envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_client_status(
dynamic_endpoint, meta->client_status);
auto* endpoint_any =
envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_mutable_endpoint_config(
dynamic_endpoint, context.arena);
if (!meta->serialized_proto.empty()) {
// Set in-effective endpoints
envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_version_info(
dynamic_endpoint, StdStringToUpbString(meta->version));
envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_last_updated(
dynamic_endpoint, GrpcMillisToTimestamp(context, meta->update_time));
google_protobuf_Any_set_type_url(endpoint_any, kEdsTypeUrlUpb);
google_protobuf_Any_set_value(
endpoint_any, StdStringToUpbString(meta->serialized_proto));
} else {
// If there isn't a working endpoint, we still need to print the name.
auto* cluster_load_assignment =
envoy_config_endpoint_v3_ClusterLoadAssignment_new(context.arena);
envoy_config_endpoint_v3_ClusterLoadAssignment_set_cluster_name(
cluster_load_assignment, name_upb);
size_t length;
char* bytes = envoy_config_endpoint_v3_ClusterLoadAssignment_serialize(
cluster_load_assignment, context.arena, &length);
google_protobuf_Any_set_type_url(endpoint_any, kEdsTypeUrlUpb);
google_protobuf_Any_set_value(endpoint_any,
upb_strview_make(bytes, length));
}
if (meta->client_status == XdsApi::ResourceMetadata::NACKED) {
// Set error_state if NACKED
envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_error_state(
dynamic_endpoint, CreateUpdateFailureStateUpb(context, meta));
}
}
}
} // namespace
std::string XdsApi::AssembleClientConfig(
@ -4019,33 +3808,50 @@ std::string XdsApi::AssembleClientConfig(
arena.ptr(), true, certificate_provider_definition_map_};
PopulateNode(context, node_, build_version_, user_agent_name_,
user_agent_version_, node);
// Dump each xDS-type config into PerXdsConfig
for (auto& p : resource_type_metadata_map) {
// Dump each resource.
for (const auto& p : resource_type_metadata_map) {
absl::string_view type_url = p.first;
const ResourceTypeMetadata& resource_type_metadata = p.second;
if (type_url == kLdsTypeUrl) {
auto* per_xds_config =
envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
context.arena);
DumpLdsConfig(context, resource_type_metadata, per_xds_config);
} else if (type_url == kRdsTypeUrl) {
auto* per_xds_config =
envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
context.arena);
DumpRdsConfig(context, resource_type_metadata, per_xds_config);
} else if (type_url == kCdsTypeUrl) {
auto* per_xds_config =
envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
context.arena);
DumpCdsConfig(context, resource_type_metadata, per_xds_config);
} else if (type_url == kEdsTypeUrl) {
auto* per_xds_config =
envoy_service_status_v3_ClientConfig_add_xds_config(client_config,
context.arena);
DumpEdsConfig(context, resource_type_metadata, per_xds_config);
} else {
gpr_log(GPR_ERROR, "invalid type_url %s", std::string(type_url).c_str());
return "";
const ResourceMetadataMap& resource_metadata_map = p.second;
for (const auto& q : resource_metadata_map) {
absl::string_view resource_name = q.first;
const ResourceMetadata& metadata = *q.second;
auto* entry =
envoy_service_status_v3_ClientConfig_add_generic_xds_configs(
client_config, context.arena);
envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_type_url(
entry, StdStringToUpbString(type_url));
envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_name(
entry, StdStringToUpbString(resource_name));
envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_client_status(
entry, metadata.client_status);
if (!metadata.serialized_proto.empty()) {
envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_version_info(
entry, StdStringToUpbString(metadata.version));
envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_last_updated(
entry, GrpcMillisToTimestamp(context, metadata.update_time));
auto* any_field =
envoy_service_status_v3_ClientConfig_GenericXdsConfig_mutable_xds_config(
entry, context.arena);
google_protobuf_Any_set_type_url(any_field,
StdStringToUpbString(type_url));
google_protobuf_Any_set_value(
any_field, StdStringToUpbString(metadata.serialized_proto));
}
if (metadata.client_status == XdsApi::ResourceMetadata::NACKED) {
auto* update_failure_state =
envoy_admin_v3_UpdateFailureState_new(context.arena);
envoy_admin_v3_UpdateFailureState_set_details(
update_failure_state,
StdStringToUpbString(metadata.failed_details));
envoy_admin_v3_UpdateFailureState_set_version_info(
update_failure_state,
StdStringToUpbString(metadata.failed_version));
envoy_admin_v3_UpdateFailureState_set_last_update_attempt(
update_failure_state,
GrpcMillisToTimestamp(context, metadata.failed_update_time));
envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_error_state(
entry, update_failure_state);
}
}
}
// Serialize the upb message to bytes

@ -617,12 +617,8 @@ class XdsApi {
};
using ResourceMetadataMap =
std::map<absl::string_view /*resource_name*/, const ResourceMetadata*>;
struct ResourceTypeMetadata {
absl::string_view version;
ResourceMetadataMap resource_metadata_map;
};
using ResourceTypeMetadataMap =
std::map<absl::string_view /*type_url*/, ResourceTypeMetadata>;
std::map<absl::string_view /*type_url*/, ResourceMetadataMap>;
static_assert(static_cast<ResourceMetadata::ClientResourceStatus>(
envoy_admin_v3_REQUESTED) ==
ResourceMetadata::ClientResourceStatus::REQUESTED,

@ -2332,32 +2332,23 @@ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshotLocked(
std::string XdsClient::DumpClientConfigBinary() {
MutexLock lock(&mu_);
XdsApi::ResourceTypeMetadataMap resource_type_metadata_map;
// Update per-xds-type version if available, this version corresponding to the
// last successful ADS update version.
for (auto& p : resource_version_map_) {
resource_type_metadata_map[p.first].version = p.second;
}
// Collect resource metadata from listeners
auto& lds_map =
resource_type_metadata_map[XdsApi::kLdsTypeUrl].resource_metadata_map;
auto& lds_map = resource_type_metadata_map[XdsApi::kLdsTypeUrl];
for (auto& p : listener_map_) {
lds_map[p.first] = &p.second.meta;
}
// Collect resource metadata from route configs
auto& rds_map =
resource_type_metadata_map[XdsApi::kRdsTypeUrl].resource_metadata_map;
auto& rds_map = resource_type_metadata_map[XdsApi::kRdsTypeUrl];
for (auto& p : route_config_map_) {
rds_map[p.first] = &p.second.meta;
}
// Collect resource metadata from clusters
auto& cds_map =
resource_type_metadata_map[XdsApi::kCdsTypeUrl].resource_metadata_map;
auto& cds_map = resource_type_metadata_map[XdsApi::kCdsTypeUrl];
for (auto& p : cluster_map_) {
cds_map[p.first] = &p.second.meta;
}
// Collect resource metadata from endpoints
auto& eds_map =
resource_type_metadata_map[XdsApi::kEdsTypeUrl].resource_metadata_map;
auto& eds_map = resource_type_metadata_map[XdsApi::kEdsTypeUrl];
for (auto& p : endpoint_map_) {
eds_map[p.first] = &p.second.meta;
}

@ -21,6 +21,9 @@ package envoy.service.status.v3;
import "src/proto/grpc/testing/xds/v3/config_dump.proto";
import "src/proto/grpc/testing/xds/v3/base.proto";
import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";
// CSDS is Client Status Discovery Service. It can be used to get the status of
// an xDS-compliant client from the management server's point of view. It can
@ -77,10 +80,58 @@ message PerXdsConfig {
// All xds configs for a particular client.
message ClientConfig {
// GenericXdsConfig is used to specify the config status and the dump
// of any xDS resource identified by their type URL. It is the generalized
// version of the now deprecated ListenersConfigDump, ClustersConfigDump etc
// [#next-free-field: 10]
message GenericXdsConfig {
// Type_url represents the fully qualified name of xDS resource type
// like envoy.v3.Cluster, envoy.v3.ClusterLoadAssignment etc.
string type_url = 1;
// Name of the xDS resource
string name = 2;
// This is the :ref:`version_info <envoy_v3_api_field_service.discovery.v3.DiscoveryResponse.version_info>`
// in the last processed xDS discovery response. If there are only
// static bootstrap listeners, this field will be ""
string version_info = 3;
// The xDS resource config. Actual content depends on the type
google.protobuf.Any xds_config = 4;
// Timestamp when the xDS resource was last updated
google.protobuf.Timestamp last_updated = 5;
// Per xDS resource config status. It is generated by management servers.
// It will not be present if the CSDS server is an xDS client.
ConfigStatus config_status = 6;
// Per xDS resource status from the view of a xDS client
admin.v3.ClientResourceStatus client_status = 7;
// Set if the last update failed, cleared after the next successful
// update. The *error_state* field contains the rejected version of
// this particular resource along with the reason and timestamp. For
// successfully updated or acknowledged resource, this field should
// be empty.
admin.v3.UpdateFailureState error_state = 8;
// Is static resource is true if it is specified in the config supplied
// through the file at the startup.
bool is_static_resource = 9;
}
// Node for a particular client.
config.core.v3.Node node = 1;
repeated PerXdsConfig xds_config = 2;
// This field is deprecated in favor of generic_xds_configs which is
// much simpler and uniform in structure.
repeated PerXdsConfig xds_config = 2 [deprecated = true];
// Represents generic xDS config and the exact config structure depends on
// the type URL (like Cluster if it is CDS)
repeated GenericXdsConfig generic_xds_configs = 3;
}
message ClientStatusResponse {

@ -11713,25 +11713,20 @@ MATCHER_P4(EqNode, id, user_agent_name, user_agent_version, client_features,
return ok;
}
MATCHER_P2(EqListenersConfigDump, version_info, dynamic_listeners,
"equals ListenerConfigDump") {
MATCHER_P6(EqGenericXdsConfig, type_url, name, version_info, xds_config,
client_status, error_state, "equals GenericXdsConfig") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(::testing::ElementsAre(),
arg.static_listeners(), result_listener);
ok &=
::testing::ExplainMatchResult(type_url, arg.type_url(), result_listener);
ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
result_listener);
ok &= ::testing::ExplainMatchResult(dynamic_listeners,
arg.dynamic_listeners(), result_listener);
return ok;
}
MATCHER_P2(EqDynamicListenerState, version_info, listener,
"equals DynamicListenerState") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
ok &= ::testing::ExplainMatchResult(xds_config, arg.xds_config(),
result_listener);
ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
result_listener);
ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
result_listener);
ok &=
::testing::ExplainMatchResult(listener, arg.listener(), result_listener);
return ok;
}
@ -11773,46 +11768,12 @@ MATCHER_P2(EqRouteConfiguration, name, cluster_name,
return ok;
}
MATCHER_P(EqRoutesConfigDump, dynamic_route_configs,
"equals RoutesConfigDump") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(
::testing::ElementsAre(), arg.static_route_configs(), result_listener);
ok &= ::testing::ExplainMatchResult(
dynamic_route_configs, arg.dynamic_route_configs(), result_listener);
return ok;
}
MATCHER_P2(EqClustersConfigDump, version_info, dynamic_active_clusters,
"equals ClustersConfigDump") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(::testing::ElementsAre(),
arg.static_clusters(), result_listener);
ok &= ::testing::ExplainMatchResult(::testing::ElementsAre(),
arg.dynamic_warming_clusters(),
result_listener);
ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
result_listener);
ok &= ::testing::ExplainMatchResult(
dynamic_active_clusters, arg.dynamic_active_clusters(), result_listener);
return ok;
}
MATCHER_P(EqCluster, name, "equals Cluster") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
return ok;
}
MATCHER_P(EqEndpointsConfigDump, dynamic_endpoint_configs,
"equals EndpointsConfigDump") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(dynamic_endpoint_configs,
arg.dynamic_endpoint_configs(),
result_listener);
return ok;
}
MATCHER_P(EqEndpoint, port, "equals Endpoint") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(
@ -11905,87 +11866,6 @@ MATCHER_P(UnpackClusterLoadAssignment, matcher, "is a ClusterLoadAssignment") {
return ::testing::ExplainMatchResult(matcher, config, result_listener);
}
MATCHER_P5(EqDynamicListener, name, version_info, client_status,
api_listener_matcher, error_state, "equals DynamicListener") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(false, arg.has_warming_state(),
result_listener);
ok &= ::testing::ExplainMatchResult(false, arg.has_draining_state(),
result_listener);
ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener);
ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
result_listener);
if (client_status == ClientResourceStatus::ACKED ||
client_status == ClientResourceStatus::NACKED) {
ok &= ::testing::ExplainMatchResult(
EqDynamicListenerState(version_info, UnpackListener(EqListener(
name, api_listener_matcher))),
arg.active_state(), result_listener);
}
ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
result_listener);
return ok;
}
MATCHER_P5(EqDynamicRouteConfig, name, version_info, client_status,
cluster_name, error_state, "equals DynamicRouteConfig") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
result_listener);
if (client_status == ClientResourceStatus::REQUESTED ||
client_status == ClientResourceStatus::DOES_NOT_EXIST) {
ok &= ::testing::ExplainMatchResult(
UnpackRouteConfiguration(EqRouteConfigurationName(name)),
arg.route_config(), result_listener);
} else {
ok &= ::testing::ExplainMatchResult(
UnpackRouteConfiguration(EqRouteConfiguration(name, cluster_name)),
arg.route_config(), result_listener);
}
ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
result_listener);
ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
result_listener);
return ok;
}
MATCHER_P4(EqDynamicCluster, name, version_info, client_status, error_state,
"equals DynamicCluster") {
bool ok = true;
ok &= ::testing::ExplainMatchResult(UnpackCluster(EqCluster(name)),
arg.cluster(), result_listener);
ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
result_listener);
ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
result_listener);
ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
result_listener);
return ok;
}
MATCHER_P6(EqDynamicEndpointConfig, name, version_info, client_status, port,
weight, error_state, "equals DynamicEndpointConfig") {
bool ok = true;
if (client_status == ClientResourceStatus::REQUESTED ||
client_status == ClientResourceStatus::DOES_NOT_EXIST) {
ok &= ::testing::ExplainMatchResult(
UnpackClusterLoadAssignment(EqClusterLoadAssignmentName(name)),
arg.endpoint_config(), result_listener);
} else {
ok &= ::testing::ExplainMatchResult(
UnpackClusterLoadAssignment(
EqClusterLoadAssignment(name, port, weight)),
arg.endpoint_config(), result_listener);
}
ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(),
result_listener);
ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(),
result_listener);
ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(),
result_listener);
return ok;
}
MATCHER(IsRdsEnabledHCM, "is a RDS enabled HttpConnectionManager") {
return ::testing::ExplainMatchResult(
UnpackHttpConnectionManager(
@ -12021,47 +11901,48 @@ TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpVanilla) {
::testing::HasSubstr(grpc_version_string()),
::testing::ElementsAre(
"envoy.lb.does_not_support_overprovisioning")));
// Prepare matches for RDS on or off
// Listener matcher depends on whether RDS is enabled.
::testing::Matcher<google::protobuf::Any> api_listener_matcher;
::testing::Matcher<envoy::admin::v3::RoutesConfigDump>
route_config_dump_matcher;
if (GetParam().enable_rds_testing()) {
api_listener_matcher = IsRdsEnabledHCM();
route_config_dump_matcher =
EqRoutesConfigDump(::testing::ElementsAre(EqDynamicRouteConfig(
kDefaultRouteConfigurationName, "1", ClientResourceStatus::ACKED,
kDefaultClusterName, ::testing::_)));
} else {
api_listener_matcher =
EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName);
route_config_dump_matcher = EqRoutesConfigDump(::testing::ElementsAre());
}
// Construct list of all matchers.
std::vector<::testing::Matcher<
envoy::service::status::v3::ClientConfig_GenericXdsConfig>>
matchers = {
// Listener
EqGenericXdsConfig(
kLdsTypeUrl, kServerName, /*version_info=*/"1",
UnpackListener(EqListener(kServerName, api_listener_matcher)),
ClientResourceStatus::ACKED, /*error_state=*/::testing::_),
// Cluster
EqGenericXdsConfig(
kCdsTypeUrl, kDefaultClusterName, /*version_info=*/"1",
UnpackCluster(EqCluster(kDefaultClusterName)),
ClientResourceStatus::ACKED, /*error_state=*/::testing::_),
// ClusterLoadAssignment
EqGenericXdsConfig(
kEdsTypeUrl, kDefaultEdsServiceName, /*version_info=*/"1",
UnpackClusterLoadAssignment(EqClusterLoadAssignment(
kDefaultEdsServiceName, backends_[0]->port(),
kDefaultLocalityWeight)),
ClientResourceStatus::ACKED, /*error_state=*/::testing::_),
};
// If RDS is enabled, add matcher for RDS resource.
if (GetParam().enable_rds_testing()) {
matchers.push_back(EqGenericXdsConfig(
kRdsTypeUrl, kDefaultRouteConfigurationName, /*version_info=*/"1",
UnpackRouteConfiguration(EqRouteConfiguration(
kDefaultRouteConfigurationName, kDefaultClusterName)),
ClientResourceStatus::ACKED, /*error_state=*/::testing::_));
}
// Validate the dumped xDS configs
EXPECT_THAT(
client_config.xds_config(),
::testing::UnorderedElementsAre(
::testing::Property(
&envoy::service::status::v3::PerXdsConfig::listener_config,
EqListenersConfigDump(
"1", ::testing::ElementsAre(EqDynamicListener(
kServerName, "1", ClientResourceStatus::ACKED,
api_listener_matcher, ::testing::_)))),
::testing::Property(
&envoy::service::status::v3::PerXdsConfig::route_config,
route_config_dump_matcher),
::testing::Property(
&envoy::service::status::v3::PerXdsConfig::cluster_config,
EqClustersConfigDump(
"1", ::testing::ElementsAre(EqDynamicCluster(
kDefaultClusterName, "1",
ClientResourceStatus::ACKED, ::testing::_)))),
::testing::Property(
&envoy::service::status::v3::PerXdsConfig::endpoint_config,
EqEndpointsConfigDump(
::testing::ElementsAre(EqDynamicEndpointConfig(
kDefaultEdsServiceName, "1", ClientResourceStatus::ACKED,
backends_[0]->port(), kDefaultLocalityWeight,
::testing::_))))));
EXPECT_THAT(client_config.generic_xds_configs(),
::testing::UnorderedElementsAreArray(matchers))
<< "Actual: " << client_config.DebugString();
}
TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEmpty) {
@ -12093,22 +11974,19 @@ TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerError) {
api_listener_matcher =
EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName);
}
for (int o = 0; o < kFetchConfigRetries; o++) {
for (int i = 0; i < kFetchConfigRetries; ++i) {
auto csds_response = FetchCsdsResponse();
// Check if error state is propagated
bool ok = ::testing::Value(
csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::listener_config,
EqListenersConfigDump(
"1",
::testing::ElementsAre(EqDynamicListener(
kServerName, "1", ClientResourceStatus::NACKED,
api_listener_matcher,
EqUpdateFailureState(
::testing::HasSubstr(
"Listener has neither address nor ApiListener"),
"2")))))));
csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kLdsTypeUrl, kServerName, /*version_info=*/"1",
UnpackListener(EqListener(kServerName, api_listener_matcher)),
ClientResourceStatus::NACKED,
EqUpdateFailureState(
::testing::HasSubstr(
"Listener has neither address nor ApiListener"),
"2"))));
if (ok) return; // TEST PASSED!
gpr_sleep_until(
grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
@ -12135,34 +12013,30 @@ TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpRouteError) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendOk();
for (int o = 0; o < kFetchConfigRetries; o++) {
for (int i = 0; i < kFetchConfigRetries; ++i) {
auto csds_response = FetchCsdsResponse();
bool ok = false;
if (GetParam().enable_rds_testing()) {
ok = ::testing::Value(
csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::route_config,
EqRoutesConfigDump(::testing::ElementsAre(EqDynamicRouteConfig(
kDefaultRouteConfigurationName, "1",
ClientResourceStatus::NACKED, kDefaultClusterName,
EqUpdateFailureState(
::testing::HasSubstr("VirtualHost has no domains"),
"2")))))));
csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kRdsTypeUrl, kDefaultRouteConfigurationName, /*version_info=*/"1",
UnpackRouteConfiguration(EqRouteConfiguration(
kDefaultRouteConfigurationName, kDefaultClusterName)),
ClientResourceStatus::NACKED,
EqUpdateFailureState(
::testing::HasSubstr("VirtualHost has no domains"), "2"))));
} else {
ok = ::testing::Value(
csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::listener_config,
EqListenersConfigDump(
"1",
::testing::ElementsAre(EqDynamicListener(
kServerName, "1", ClientResourceStatus::NACKED,
EqNoRdsHCM(kDefaultRouteConfigurationName,
kDefaultClusterName),
EqUpdateFailureState(
::testing::HasSubstr("VirtualHost has no domains"),
"2")))))));
csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kLdsTypeUrl, kServerName, /*version_info=*/"1",
UnpackListener(EqListener(
kServerName, EqNoRdsHCM(kDefaultRouteConfigurationName,
kDefaultClusterName))),
ClientResourceStatus::NACKED,
EqUpdateFailureState(
::testing::HasSubstr("VirtualHost has no domains"), "2"))));
}
if (ok) return; // TEST PASSED!
gpr_sleep_until(
@ -12189,19 +12063,17 @@ TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterError) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendOk();
for (int o = 0; o < kFetchConfigRetries; o++) {
for (int i = 0; i < kFetchConfigRetries; ++i) {
auto csds_response = FetchCsdsResponse();
// Check if error state is propagated
bool ok = ::testing::Value(
csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::cluster_config,
EqClustersConfigDump(
"1", ::testing::ElementsAre(EqDynamicCluster(
kDefaultClusterName, "1", ClientResourceStatus::NACKED,
EqUpdateFailureState(
::testing::HasSubstr("DiscoveryType not found"),
"2")))))));
csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kCdsTypeUrl, kDefaultClusterName, /*version_info=*/"1",
UnpackCluster(EqCluster(kDefaultClusterName)),
ClientResourceStatus::NACKED,
EqUpdateFailureState(
::testing::HasSubstr("DiscoveryType not found"), "2"))));
if (ok) return; // TEST PASSED!
gpr_sleep_until(
grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
@ -12231,19 +12103,19 @@ TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEndpointError) {
SetNextResolution({});
SetNextResolutionForLbChannelAllBalancers();
CheckRpcSendOk();
for (int o = 0; o < kFetchConfigRetries; o++) {
for (int i = 0; i < kFetchConfigRetries; ++i) {
auto csds_response = FetchCsdsResponse();
// Check if error state is propagated
bool ok = ::testing::Value(
csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::endpoint_config,
EqEndpointsConfigDump(
::testing::ElementsAre(EqDynamicEndpointConfig(
kDefaultEdsServiceName, "1", ClientResourceStatus::NACKED,
backends_[0]->port(), kDefaultLocalityWeight,
EqUpdateFailureState(::testing::HasSubstr("Empty locality"),
"2")))))));
csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kEdsTypeUrl, kDefaultEdsServiceName, /*version_info=*/"1",
UnpackClusterLoadAssignment(EqClusterLoadAssignment(
kDefaultEdsServiceName, backends_[0]->port(),
kDefaultLocalityWeight)),
ClientResourceStatus::NACKED,
EqUpdateFailureState(::testing::HasSubstr("Empty locality"),
"2"))));
if (ok) return; // TEST PASSED!
gpr_sleep_until(
grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds));
@ -12259,14 +12131,11 @@ TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerRequested) {
.set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
.set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
auto csds_response = FetchCsdsResponse();
EXPECT_THAT(csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::listener_config,
EqListenersConfigDump(
::testing::_, ::testing::ElementsAre(EqDynamicListener(
kServerName, ::testing::_,
ClientResourceStatus::REQUESTED,
::testing::_, ::testing::_))))));
EXPECT_THAT(
csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kLdsTypeUrl, kServerName, /*version_info=*/::testing::_, ::testing::_,
ClientResourceStatus::REQUESTED, /*error_state=*/::testing::_)));
}
TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterRequested) {
@ -12295,18 +12164,16 @@ TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterRequested) {
.set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
.set_expected_error_code(StatusCode::DEADLINE_EXCEEDED));
auto csds_response = FetchCsdsResponse();
EXPECT_THAT(csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::cluster_config,
EqClustersConfigDump(
::testing::_,
::testing::UnorderedElementsAre(
EqDynamicCluster(kClusterName1, ::testing::_,
ClientResourceStatus::REQUESTED,
::testing::_),
EqDynamicCluster(kClusterName2, ::testing::_,
ClientResourceStatus::REQUESTED,
::testing::_))))));
EXPECT_THAT(csds_response.config(0).generic_xds_configs(),
::testing::AllOf(
::testing::Contains(EqGenericXdsConfig(
kCdsTypeUrl, kClusterName1, /*version_info=*/::testing::_,
::testing::_, ClientResourceStatus::REQUESTED,
/*error_state=*/::testing::_)),
::testing::Contains(EqGenericXdsConfig(
kCdsTypeUrl, kClusterName2, /*version_info=*/::testing::_,
::testing::_, ClientResourceStatus::REQUESTED,
/*error_state=*/::testing::_))));
}
class CsdsShortAdsTimeoutTest : public ClientStatusDiscoveryServiceTest {
@ -12325,14 +12192,11 @@ TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpListenerDoesNotExist) {
.set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
.set_expected_error_code(grpc::UNAVAILABLE));
auto csds_response = FetchCsdsResponse();
EXPECT_THAT(csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::listener_config,
EqListenersConfigDump(
::testing::_, ::testing::ElementsAre(EqDynamicListener(
kServerName, ::testing::_,
ClientResourceStatus::DOES_NOT_EXIST,
::testing::_, ::testing::_))))));
EXPECT_THAT(
csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kLdsTypeUrl, kServerName, /*version_info=*/::testing::_, ::testing::_,
ClientResourceStatus::DOES_NOT_EXIST, /*error_state=*/::testing::_)));
}
TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpRouteConfigDoesNotExist) {
@ -12348,13 +12212,11 @@ TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpRouteConfigDoesNotExist) {
.set_expected_error_code(grpc::UNAVAILABLE));
auto csds_response = FetchCsdsResponse();
EXPECT_THAT(
csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::route_config,
EqRoutesConfigDump(::testing::ElementsAre(
EqDynamicRouteConfig(kDefaultRouteConfigurationName, ::testing::_,
ClientResourceStatus::DOES_NOT_EXIST,
::testing::_, ::testing::_))))));
csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kRdsTypeUrl, kDefaultRouteConfigurationName,
/*version_info=*/::testing::_, ::testing::_,
ClientResourceStatus::DOES_NOT_EXIST, /*error_state=*/::testing::_)));
}
TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpClusterDoesNotExist) {
@ -12367,14 +12229,12 @@ TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpClusterDoesNotExist) {
.set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
.set_expected_error_code(grpc::UNAVAILABLE));
auto csds_response = FetchCsdsResponse();
EXPECT_THAT(csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::cluster_config,
EqClustersConfigDump(::testing::_,
::testing::ElementsAre(EqDynamicCluster(
kDefaultClusterName, ::testing::_,
ClientResourceStatus::DOES_NOT_EXIST,
::testing::_))))));
EXPECT_THAT(
csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kCdsTypeUrl, kDefaultClusterName, /*version_info=*/::testing::_,
::testing::_, ClientResourceStatus::DOES_NOT_EXIST,
/*error_state=*/::testing::_)));
}
TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpEndpointDoesNotExist) {
@ -12388,15 +12248,14 @@ TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpEndpointDoesNotExist) {
.set_rpc_options(RpcOptions().set_timeout_ms(kTimeoutMillisecond))
.set_expected_error_code(grpc::UNAVAILABLE));
auto csds_response = FetchCsdsResponse();
EXPECT_THAT(
csds_response.config(0).xds_config(),
::testing::Contains(::testing::Property(
&envoy::service::status::v3::PerXdsConfig::endpoint_config,
EqEndpointsConfigDump(::testing::ElementsAre(EqDynamicEndpointConfig(
kDefaultEdsServiceName, ::testing::_,
ClientResourceStatus::DOES_NOT_EXIST, ::testing::_, ::testing::_,
::testing::_))))));
EXPECT_THAT(csds_response.config(0).generic_xds_configs(),
::testing::Contains(EqGenericXdsConfig(
kEdsTypeUrl, kDefaultEdsServiceName,
/*version_info=*/::testing::_, ::testing::_,
ClientResourceStatus::DOES_NOT_EXIST,
/*error_state=*/::testing::_)));
}
#endif // DISABLED_XDS_PROTO_IN_CC
std::string TestTypeName(const ::testing::TestParamInfo<TestType>& info) {

Loading…
Cancel
Save