|
|
|
@ -784,12 +784,9 @@ grpc_slice XdsApi::CreateAdsRequest( |
|
|
|
|
// generate them in the parsing code, and then use that here.
|
|
|
|
|
google_rpc_Status_set_code(error_detail, GRPC_STATUS_INVALID_ARGUMENT); |
|
|
|
|
// Error description comes from the error that was passed in.
|
|
|
|
|
grpc_slice error_description_slice; |
|
|
|
|
GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, |
|
|
|
|
&error_description_slice)); |
|
|
|
|
upb_strview error_description_strview = |
|
|
|
|
StdStringToUpbString(StringViewFromSlice(error_description_slice)); |
|
|
|
|
google_rpc_Status_set_message(error_detail, error_description_strview); |
|
|
|
|
upb_strview error_description = |
|
|
|
|
StdStringToUpbString(absl::string_view(grpc_error_string(error))); |
|
|
|
|
google_rpc_Status_set_message(error_detail, error_description); |
|
|
|
|
GRPC_ERROR_UNREF(error); |
|
|
|
|
} |
|
|
|
|
// Populate node.
|
|
|
|
@ -1289,7 +1286,6 @@ grpc_error* CommonTlsContextParse( |
|
|
|
|
} |
|
|
|
|
bool ignore_case = envoy_type_matcher_v3_StringMatcher_ignore_case( |
|
|
|
|
subject_alt_names_matchers[i]); |
|
|
|
|
|
|
|
|
|
absl::StatusOr<StringMatcher> string_matcher = |
|
|
|
|
StringMatcher::Create(type, matcher, |
|
|
|
|
/*case_sensitive=*/!ignore_case); |
|
|
|
@ -1471,7 +1467,9 @@ grpc_error* LdsResponseParse( |
|
|
|
|
XdsClient* client, TraceFlag* tracer, upb_symtab* symtab, |
|
|
|
|
const envoy_service_discovery_v3_DiscoveryResponse* response, |
|
|
|
|
const std::set<absl::string_view>& expected_listener_names, |
|
|
|
|
XdsApi::LdsUpdateMap* lds_update_map, upb_arena* arena) { |
|
|
|
|
XdsApi::LdsUpdateMap* lds_update_map, |
|
|
|
|
std::set<std::string>* resource_names_failed, upb_arena* arena) { |
|
|
|
|
std::vector<grpc_error*> errors; |
|
|
|
|
// Get the resources from the response.
|
|
|
|
|
size_t size; |
|
|
|
|
const google_protobuf_Any* const* resources = |
|
|
|
@ -1481,7 +1479,10 @@ grpc_error* LdsResponseParse( |
|
|
|
|
absl::string_view type_url = |
|
|
|
|
UpbStringToAbsl(google_protobuf_Any_type_url(resources[i])); |
|
|
|
|
if (!IsLds(type_url)) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not LDS."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("resource index ", i, ": Resource is not LDS.") |
|
|
|
|
.c_str())); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// Decode the listener.
|
|
|
|
|
const upb_strview encoded_listener = |
|
|
|
@ -1490,7 +1491,10 @@ grpc_error* LdsResponseParse( |
|
|
|
|
envoy_config_listener_v3_Listener_parse(encoded_listener.data, |
|
|
|
|
encoded_listener.size, arena); |
|
|
|
|
if (listener == nullptr) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode listener."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("resource index ", i, ": Can't decode listener.") |
|
|
|
|
.c_str())); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// Check listener name. Ignore unexpected listeners.
|
|
|
|
|
std::string listener_name = |
|
|
|
@ -1501,9 +1505,11 @@ grpc_error* LdsResponseParse( |
|
|
|
|
} |
|
|
|
|
// Fail if listener name is duplicated.
|
|
|
|
|
if (lds_update_map->find(listener_name) != lds_update_map->end()) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("duplicate listener name \"", listener_name, "\"") |
|
|
|
|
.c_str()); |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(listener_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
XdsApi::LdsUpdate& lds_update = (*lds_update_map)[listener_name]; |
|
|
|
|
// Check whether it's a client or server listener.
|
|
|
|
@ -1512,12 +1518,20 @@ grpc_error* LdsResponseParse( |
|
|
|
|
const envoy_config_core_v3_Address* address = |
|
|
|
|
envoy_config_listener_v3_Listener_address(listener); |
|
|
|
|
if (api_listener != nullptr && address != nullptr) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"Listener has both address and ApiListener"); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(listener_name, |
|
|
|
|
": Listener has both address and ApiListener") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(listener_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (api_listener == nullptr && address == nullptr) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"Listener has neither address nor ApiListener"); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(listener_name, |
|
|
|
|
": Listener has neither address nor ApiListener") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(listener_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
grpc_error* error = GRPC_ERROR_NONE; |
|
|
|
|
if (api_listener != nullptr) { |
|
|
|
@ -1527,16 +1541,24 @@ grpc_error* LdsResponseParse( |
|
|
|
|
error = LdsResponseParseServer(arena, listener, listener_name, address, |
|
|
|
|
&lds_update); |
|
|
|
|
} |
|
|
|
|
if (error != GRPC_ERROR_NONE) return error; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
errors.push_back(grpc_error_add_child( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(listener_name, ": validation error").c_str()), |
|
|
|
|
error)); |
|
|
|
|
resource_names_failed->insert(listener_name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing LDS response", &errors); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_error* RdsResponseParse( |
|
|
|
|
XdsClient* client, TraceFlag* tracer, upb_symtab* symtab, |
|
|
|
|
const envoy_service_discovery_v3_DiscoveryResponse* response, |
|
|
|
|
const std::set<absl::string_view>& expected_route_configuration_names, |
|
|
|
|
XdsApi::RdsUpdateMap* rds_update_map, upb_arena* arena) { |
|
|
|
|
XdsApi::RdsUpdateMap* rds_update_map, |
|
|
|
|
std::set<std::string>* resource_names_failed, upb_arena* arena) { |
|
|
|
|
std::vector<grpc_error*> errors; |
|
|
|
|
// Get the resources from the response.
|
|
|
|
|
size_t size; |
|
|
|
|
const google_protobuf_Any* const* resources = |
|
|
|
@ -1546,7 +1568,10 @@ grpc_error* RdsResponseParse( |
|
|
|
|
absl::string_view type_url = |
|
|
|
|
UpbStringToAbsl(google_protobuf_Any_type_url(resources[i])); |
|
|
|
|
if (!IsRds(type_url)) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not RDS."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("resource index ", i, ": Resource is not RDS.") |
|
|
|
|
.c_str())); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// Decode the route_config.
|
|
|
|
|
const upb_strview encoded_route_config = |
|
|
|
@ -1555,7 +1580,10 @@ grpc_error* RdsResponseParse( |
|
|
|
|
envoy_config_route_v3_RouteConfiguration_parse( |
|
|
|
|
encoded_route_config.data, encoded_route_config.size, arena); |
|
|
|
|
if (route_config == nullptr) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode route_config."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("resource index ", i, ": Can't decode route_config.") |
|
|
|
|
.c_str())); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// Check route_config_name. Ignore unexpected route_config.
|
|
|
|
|
std::string route_config_name = UpbStringToStdString( |
|
|
|
@ -1566,26 +1594,35 @@ grpc_error* RdsResponseParse( |
|
|
|
|
} |
|
|
|
|
// Fail if route config name is duplicated.
|
|
|
|
|
if (rds_update_map->find(route_config_name) != rds_update_map->end()) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("duplicate route config name \"", route_config_name, |
|
|
|
|
"\"") |
|
|
|
|
.c_str()); |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(route_config_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// Parse the route_config.
|
|
|
|
|
XdsApi::RdsUpdate& rds_update = |
|
|
|
|
(*rds_update_map)[std::move(route_config_name)]; |
|
|
|
|
XdsApi::RdsUpdate& rds_update = (*rds_update_map)[route_config_name]; |
|
|
|
|
grpc_error* error = |
|
|
|
|
RouteConfigParse(client, tracer, symtab, route_config, &rds_update); |
|
|
|
|
if (error != GRPC_ERROR_NONE) return error; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
errors.push_back(grpc_error_add_child( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(route_config_name, ": validation error").c_str()), |
|
|
|
|
error)); |
|
|
|
|
resource_names_failed->insert(route_config_name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing RDS response", &errors); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_error* CdsResponseParse( |
|
|
|
|
XdsClient* client, TraceFlag* tracer, upb_symtab* symtab, |
|
|
|
|
const envoy_service_discovery_v3_DiscoveryResponse* response, |
|
|
|
|
const std::set<absl::string_view>& expected_cluster_names, |
|
|
|
|
XdsApi::CdsUpdateMap* cds_update_map, upb_arena* arena) { |
|
|
|
|
XdsApi::CdsUpdateMap* cds_update_map, |
|
|
|
|
std::set<std::string>* resource_names_failed, upb_arena* arena) { |
|
|
|
|
std::vector<grpc_error*> errors; |
|
|
|
|
// Get the resources from the response.
|
|
|
|
|
size_t size; |
|
|
|
|
const google_protobuf_Any* const* resources = |
|
|
|
@ -1596,7 +1633,10 @@ grpc_error* CdsResponseParse( |
|
|
|
|
absl::string_view type_url = |
|
|
|
|
UpbStringToAbsl(google_protobuf_Any_type_url(resources[i])); |
|
|
|
|
if (!IsCds(type_url)) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not CDS."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("resource index ", i, ": Resource is not CDS.") |
|
|
|
|
.c_str())); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// Decode the cluster.
|
|
|
|
|
const upb_strview encoded_cluster = google_protobuf_Any_value(resources[i]); |
|
|
|
@ -1604,7 +1644,10 @@ grpc_error* CdsResponseParse( |
|
|
|
|
envoy_config_cluster_v3_Cluster_parse(encoded_cluster.data, |
|
|
|
|
encoded_cluster.size, arena); |
|
|
|
|
if (cluster == nullptr) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode cluster."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("resource index ", i, ": Can't decode cluster.") |
|
|
|
|
.c_str())); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
MaybeLogCluster(client, tracer, symtab, cluster); |
|
|
|
|
// Ignore unexpected cluster names.
|
|
|
|
@ -1616,15 +1659,20 @@ grpc_error* CdsResponseParse( |
|
|
|
|
} |
|
|
|
|
// Fail on duplicate resources.
|
|
|
|
|
if (cds_update_map->find(cluster_name) != cds_update_map->end()) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("duplicate resource name \"", cluster_name, "\"") |
|
|
|
|
.c_str()); |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
XdsApi::CdsUpdate& cds_update = (*cds_update_map)[std::move(cluster_name)]; |
|
|
|
|
XdsApi::CdsUpdate& cds_update = (*cds_update_map)[cluster_name]; |
|
|
|
|
// Check the cluster_discovery_type.
|
|
|
|
|
if (!envoy_config_cluster_v3_Cluster_has_type(cluster) && |
|
|
|
|
!envoy_config_cluster_v3_Cluster_has_cluster_type(cluster)) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType not found."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, ": DiscoveryType not found.").c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (envoy_config_cluster_v3_Cluster_type(cluster) == |
|
|
|
|
envoy_config_cluster_v3_Cluster_EDS) { |
|
|
|
@ -1637,8 +1685,11 @@ grpc_error* CdsResponseParse( |
|
|
|
|
envoy_config_cluster_v3_Cluster_EdsClusterConfig_eds_config( |
|
|
|
|
eds_cluster_config); |
|
|
|
|
if (!envoy_config_core_v3_ConfigSource_has_ads(eds_config)) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"EDS ConfigSource is not ADS."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, ": EDS ConfigSource is not ADS.") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// Record EDS service_name (if any).
|
|
|
|
|
upb_strview service_name = |
|
|
|
@ -1648,8 +1699,10 @@ grpc_error* CdsResponseParse( |
|
|
|
|
cds_update.eds_service_name = UpbStringToStdString(service_name); |
|
|
|
|
} |
|
|
|
|
} else if (!XdsAggregateAndLogicalDnsClusterEnabled()) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"DiscoveryType is not valid."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, ": DiscoveryType is not valid.").c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} else if (envoy_config_cluster_v3_Cluster_type(cluster) == |
|
|
|
|
envoy_config_cluster_v3_Cluster_LOGICAL_DNS) { |
|
|
|
|
cds_update.cluster_type = XdsApi::CdsUpdate::ClusterType::LOGICAL_DNS; |
|
|
|
@ -1675,8 +1728,11 @@ grpc_error* CdsResponseParse( |
|
|
|
|
aggregate_cluster_config_upb_strview.data, |
|
|
|
|
aggregate_cluster_config_upb_strview.size, arena); |
|
|
|
|
if (aggregate_cluster_config == nullptr) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"Can't parse aggregate cluster."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, ": Can't parse aggregate cluster.") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
size_t size; |
|
|
|
|
const upb_strview* clusters = |
|
|
|
@ -1688,19 +1744,28 @@ grpc_error* CdsResponseParse( |
|
|
|
|
UpbStringToStdString(cluster)); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"DiscoveryType is not valid."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, ": DiscoveryType is not valid.") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"DiscoveryType is not valid."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, ": DiscoveryType is not valid.") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Check the LB policy.
|
|
|
|
|
if (envoy_config_cluster_v3_Cluster_lb_policy(cluster) != |
|
|
|
|
envoy_config_cluster_v3_Cluster_ROUND_ROBIN) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"LB policy is not ROUND_ROBIN."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, ": LB policy is not ROUND_ROBIN.") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (XdsSecurityEnabled()) { |
|
|
|
|
// Record Upstream tls context
|
|
|
|
@ -1721,8 +1786,12 @@ grpc_error* CdsResponseParse( |
|
|
|
|
encoded_upstream_tls_context.data, |
|
|
|
|
encoded_upstream_tls_context.size, arena); |
|
|
|
|
if (upstream_tls_context == nullptr) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"Can't decode upstream tls context."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, |
|
|
|
|
": Can't decode upstream tls context.") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
auto* common_tls_context = |
|
|
|
|
envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_common_tls_context( |
|
|
|
@ -1730,15 +1799,28 @@ grpc_error* CdsResponseParse( |
|
|
|
|
if (common_tls_context != nullptr) { |
|
|
|
|
grpc_error* error = CommonTlsContextParse( |
|
|
|
|
common_tls_context, &cds_update.common_tls_context); |
|
|
|
|
if (error != GRPC_ERROR_NONE) return error; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
errors.push_back(grpc_error_add_child( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, ": error in TLS context") |
|
|
|
|
.c_str()), |
|
|
|
|
error)); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (cds_update.common_tls_context.combined_validation_context |
|
|
|
|
.validation_context_certificate_provider_instance |
|
|
|
|
.instance_name.empty()) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"TLS configuration provided but no " |
|
|
|
|
"validation_context_certificate_provider_instance found."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, |
|
|
|
|
"TLS configuration provided but no " |
|
|
|
|
"validation_context_certificate_provider_instance " |
|
|
|
|
"found.") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1748,8 +1830,11 @@ grpc_error* CdsResponseParse( |
|
|
|
|
envoy_config_cluster_v3_Cluster_lrs_server(cluster); |
|
|
|
|
if (lrs_server != nullptr) { |
|
|
|
|
if (!envoy_config_core_v3_ConfigSource_has_self(lrs_server)) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"LRS ConfigSource is not self."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(cluster_name, ": LRS ConfigSource is not self.") |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(cluster_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
cds_update.lrs_load_reporting_server_name.emplace(""); |
|
|
|
|
} |
|
|
|
@ -1780,7 +1865,7 @@ grpc_error* CdsResponseParse( |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing CDS response", &errors); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_error* ServerAddressParseAndAppend( |
|
|
|
@ -1898,7 +1983,9 @@ grpc_error* EdsResponseParse( |
|
|
|
|
XdsClient* client, TraceFlag* tracer, upb_symtab* symtab, |
|
|
|
|
const envoy_service_discovery_v3_DiscoveryResponse* response, |
|
|
|
|
const std::set<absl::string_view>& expected_eds_service_names, |
|
|
|
|
XdsApi::EdsUpdateMap* eds_update_map, upb_arena* arena) { |
|
|
|
|
XdsApi::EdsUpdateMap* eds_update_map, |
|
|
|
|
std::set<std::string>* resource_names_failed, upb_arena* arena) { |
|
|
|
|
std::vector<grpc_error*> errors; |
|
|
|
|
// Get the resources from the response.
|
|
|
|
|
size_t size; |
|
|
|
|
const google_protobuf_Any* const* resources = |
|
|
|
@ -1908,7 +1995,10 @@ grpc_error* EdsResponseParse( |
|
|
|
|
absl::string_view type_url = |
|
|
|
|
UpbStringToAbsl(google_protobuf_Any_type_url(resources[i])); |
|
|
|
|
if (!IsEds(type_url)) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not EDS."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("resource index ", i, ": Resource is not EDS.") |
|
|
|
|
.c_str())); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// Get the cluster_load_assignment.
|
|
|
|
|
upb_strview encoded_cluster_load_assignment = |
|
|
|
@ -1918,8 +2008,11 @@ grpc_error* EdsResponseParse( |
|
|
|
|
encoded_cluster_load_assignment.data, |
|
|
|
|
encoded_cluster_load_assignment.size, arena); |
|
|
|
|
if (cluster_load_assignment == nullptr) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"Can't parse cluster_load_assignment."); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("resource index ", i, |
|
|
|
|
": Can't parse cluster_load_assignment.") |
|
|
|
|
.c_str())); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
MaybeLogClusterLoadAssignment(client, tracer, symtab, |
|
|
|
|
cluster_load_assignment); |
|
|
|
@ -1933,22 +2026,24 @@ grpc_error* EdsResponseParse( |
|
|
|
|
} |
|
|
|
|
// Fail on duplicate resources.
|
|
|
|
|
if (eds_update_map->find(eds_service_name) != eds_update_map->end()) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat("duplicate resource name \"", eds_service_name, "\"") |
|
|
|
|
.c_str()); |
|
|
|
|
.c_str())); |
|
|
|
|
resource_names_failed->insert(eds_service_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
XdsApi::EdsUpdate& eds_update = |
|
|
|
|
(*eds_update_map)[std::move(eds_service_name)]; |
|
|
|
|
XdsApi::EdsUpdate& eds_update = (*eds_update_map)[eds_service_name]; |
|
|
|
|
// Get the endpoints.
|
|
|
|
|
size_t locality_size; |
|
|
|
|
const envoy_config_endpoint_v3_LocalityLbEndpoints* const* endpoints = |
|
|
|
|
envoy_config_endpoint_v3_ClusterLoadAssignment_endpoints( |
|
|
|
|
cluster_load_assignment, &locality_size); |
|
|
|
|
grpc_error* error = GRPC_ERROR_NONE; |
|
|
|
|
for (size_t j = 0; j < locality_size; ++j) { |
|
|
|
|
size_t priority; |
|
|
|
|
XdsApi::EdsUpdate::Priority::Locality locality; |
|
|
|
|
grpc_error* error = LocalityParse(endpoints[j], &locality, &priority); |
|
|
|
|
if (error != GRPC_ERROR_NONE) return error; |
|
|
|
|
error = LocalityParse(endpoints[j], &locality, &priority); |
|
|
|
|
if (error != GRPC_ERROR_NONE) break; |
|
|
|
|
// Filter out locality with weight 0.
|
|
|
|
|
if (locality.lb_weight == 0) continue; |
|
|
|
|
// Make sure prorities is big enough. Note that they might not
|
|
|
|
@ -1959,10 +2054,21 @@ grpc_error* EdsResponseParse( |
|
|
|
|
eds_update.priorities[priority].localities.emplace(locality.name.get(), |
|
|
|
|
std::move(locality)); |
|
|
|
|
} |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
errors.push_back(grpc_error_add_child( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(eds_service_name, ": locality validation error") |
|
|
|
|
.c_str()), |
|
|
|
|
error)); |
|
|
|
|
resource_names_failed->insert(eds_service_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
for (const auto& priority : eds_update.priorities) { |
|
|
|
|
if (priority.localities.empty()) { |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"EDS update includes sparse priority list"); |
|
|
|
|
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(eds_service_name, ": sparse priority list").c_str())); |
|
|
|
|
resource_names_failed->insert(eds_service_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Get the drop config.
|
|
|
|
@ -1977,13 +2083,22 @@ grpc_error* EdsResponseParse( |
|
|
|
|
envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_drop_overloads( |
|
|
|
|
policy, &drop_size); |
|
|
|
|
for (size_t j = 0; j < drop_size; ++j) { |
|
|
|
|
grpc_error* error = |
|
|
|
|
error = |
|
|
|
|
DropParseAndAppend(drop_overload[j], eds_update.drop_config.get()); |
|
|
|
|
if (error != GRPC_ERROR_NONE) return error; |
|
|
|
|
if (error != GRPC_ERROR_NONE) break; |
|
|
|
|
} |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
errors.push_back(grpc_error_add_child( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_COPIED_STRING( |
|
|
|
|
absl::StrCat(eds_service_name, ": drop config validation error") |
|
|
|
|
.c_str()), |
|
|
|
|
error)); |
|
|
|
|
resource_names_failed->insert(eds_service_name); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing EDS response", &errors); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string TypeUrlInternalToExternal(absl::string_view type_url) { |
|
|
|
@ -1999,6 +2114,15 @@ std::string TypeUrlInternalToExternal(absl::string_view type_url) { |
|
|
|
|
return std::string(type_url); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename UpdateMap> |
|
|
|
|
void MoveUpdatesToFailedSet(UpdateMap* update_map, |
|
|
|
|
std::set<std::string>* resource_names_failed) { |
|
|
|
|
for (const auto& p : *update_map) { |
|
|
|
|
resource_names_failed->insert(p.first); |
|
|
|
|
} |
|
|
|
|
update_map->clear(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
XdsApi::AdsParseResult XdsApi::ParseAdsResponse( |
|
|
|
@ -2030,22 +2154,38 @@ XdsApi::AdsParseResult XdsApi::ParseAdsResponse( |
|
|
|
|
envoy_service_discovery_v3_DiscoveryResponse_nonce(response)); |
|
|
|
|
// Parse the response according to the resource type.
|
|
|
|
|
if (IsLds(result.type_url)) { |
|
|
|
|
result.parse_error = LdsResponseParse(client_, tracer_, symtab_.ptr(), |
|
|
|
|
response, expected_listener_names, |
|
|
|
|
&result.lds_update_map, arena.ptr()); |
|
|
|
|
result.parse_error = LdsResponseParse( |
|
|
|
|
client_, tracer_, symtab_.ptr(), response, expected_listener_names, |
|
|
|
|
&result.lds_update_map, &result.resource_names_failed, arena.ptr()); |
|
|
|
|
if (result.parse_error != GRPC_ERROR_NONE) { |
|
|
|
|
MoveUpdatesToFailedSet(&result.lds_update_map, |
|
|
|
|
&result.resource_names_failed); |
|
|
|
|
} |
|
|
|
|
} else if (IsRds(result.type_url)) { |
|
|
|
|
result.parse_error = |
|
|
|
|
RdsResponseParse(client_, tracer_, symtab_.ptr(), response, |
|
|
|
|
expected_route_configuration_names, |
|
|
|
|
&result.rds_update_map, arena.ptr()); |
|
|
|
|
result.parse_error = RdsResponseParse( |
|
|
|
|
client_, tracer_, symtab_.ptr(), response, |
|
|
|
|
expected_route_configuration_names, &result.rds_update_map, |
|
|
|
|
&result.resource_names_failed, arena.ptr()); |
|
|
|
|
if (result.parse_error != GRPC_ERROR_NONE) { |
|
|
|
|
MoveUpdatesToFailedSet(&result.rds_update_map, |
|
|
|
|
&result.resource_names_failed); |
|
|
|
|
} |
|
|
|
|
} else if (IsCds(result.type_url)) { |
|
|
|
|
result.parse_error = CdsResponseParse(client_, tracer_, symtab_.ptr(), |
|
|
|
|
response, expected_cluster_names, |
|
|
|
|
&result.cds_update_map, arena.ptr()); |
|
|
|
|
result.parse_error = CdsResponseParse( |
|
|
|
|
client_, tracer_, symtab_.ptr(), response, expected_cluster_names, |
|
|
|
|
&result.cds_update_map, &result.resource_names_failed, arena.ptr()); |
|
|
|
|
if (result.parse_error != GRPC_ERROR_NONE) { |
|
|
|
|
MoveUpdatesToFailedSet(&result.cds_update_map, |
|
|
|
|
&result.resource_names_failed); |
|
|
|
|
} |
|
|
|
|
} else if (IsEds(result.type_url)) { |
|
|
|
|
result.parse_error = EdsResponseParse(client_, tracer_, symtab_.ptr(), |
|
|
|
|
response, expected_eds_service_names, |
|
|
|
|
&result.eds_update_map, arena.ptr()); |
|
|
|
|
result.parse_error = EdsResponseParse( |
|
|
|
|
client_, tracer_, symtab_.ptr(), response, expected_eds_service_names, |
|
|
|
|
&result.eds_update_map, &result.resource_names_failed, arena.ptr()); |
|
|
|
|
if (result.parse_error != GRPC_ERROR_NONE) { |
|
|
|
|
MoveUpdatesToFailedSet(&result.eds_update_map, |
|
|
|
|
&result.resource_names_failed); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|