Skip to content

Commit

Permalink
[csds] Make grpc_dump_xds_configs return ClientStatusResponse
Browse files Browse the repository at this point in the history
  • Loading branch information
eugeneo committed Jan 24, 2024
1 parent 870a66d commit f89c53c
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 188 deletions.
213 changes: 63 additions & 150 deletions src/core/ext/xds/xds_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,32 +75,29 @@ struct XdsApiContext {
upb_Arena* arena;
};

void PopulateMetadataValue(const XdsApiContext& context,
google_protobuf_Value* value_pb, const Json& value);
void PopulateMetadataValue(google_protobuf_Value* value_pb, const Json& value,
upb_Arena* arena);

void PopulateListValue(const XdsApiContext& context,
google_protobuf_ListValue* list_value,
const Json::Array& values) {
void PopulateListValue(google_protobuf_ListValue* list_value,
const Json::Array& values, upb_Arena* arena) {
for (const auto& value : values) {
auto* value_pb =
google_protobuf_ListValue_add_values(list_value, context.arena);
PopulateMetadataValue(context, value_pb, value);
auto* value_pb = google_protobuf_ListValue_add_values(list_value, arena);
PopulateMetadataValue(value_pb, value, arena);
}
}

void PopulateMetadata(const XdsApiContext& context,
google_protobuf_Struct* metadata_pb,
const Json::Object& metadata) {
void PopulateMetadata(google_protobuf_Struct* metadata_pb,
const Json::Object& metadata, upb_Arena* arena) {
for (const auto& p : metadata) {
google_protobuf_Value* value = google_protobuf_Value_new(context.arena);
PopulateMetadataValue(context, value, p.second);
google_protobuf_Value* value = google_protobuf_Value_new(arena);
PopulateMetadataValue(value, p.second, arena);
google_protobuf_Struct_fields_set(
metadata_pb, StdStringToUpbString(p.first), value, context.arena);
metadata_pb, StdStringToUpbString(p.first), value, arena);
}
}

void PopulateMetadataValue(const XdsApiContext& context,
google_protobuf_Value* value_pb, const Json& value) {
void PopulateMetadataValue(google_protobuf_Value* value_pb, const Json& value,
upb_Arena* arena) {
switch (value.type()) {
case Json::Type::kNull:
google_protobuf_Value_set_null_value(value_pb, 0);
Expand All @@ -118,65 +115,19 @@ void PopulateMetadataValue(const XdsApiContext& context,
break;
case Json::Type::kObject: {
google_protobuf_Struct* struct_value =
google_protobuf_Value_mutable_struct_value(value_pb, context.arena);
PopulateMetadata(context, struct_value, value.object());
google_protobuf_Value_mutable_struct_value(value_pb, arena);
PopulateMetadata(struct_value, value.object(), arena);
break;
}
case Json::Type::kArray: {
google_protobuf_ListValue* list_value =
google_protobuf_Value_mutable_list_value(value_pb, context.arena);
PopulateListValue(context, list_value, value.array());
google_protobuf_Value_mutable_list_value(value_pb, arena);
PopulateListValue(list_value, value.array(), arena);
break;
}
}
}

void PopulateNode(const XdsApiContext& context, const XdsBootstrap::Node* node,
const std::string& user_agent_name,
const std::string& user_agent_version,
envoy_config_core_v3_Node* node_msg) {
if (node != nullptr) {
if (!node->id().empty()) {
envoy_config_core_v3_Node_set_id(node_msg,
StdStringToUpbString(node->id()));
}
if (!node->cluster().empty()) {
envoy_config_core_v3_Node_set_cluster(
node_msg, StdStringToUpbString(node->cluster()));
}
if (!node->metadata().empty()) {
google_protobuf_Struct* metadata =
envoy_config_core_v3_Node_mutable_metadata(node_msg, context.arena);
PopulateMetadata(context, metadata, node->metadata());
}
if (!node->locality_region().empty() || !node->locality_zone().empty() ||
!node->locality_sub_zone().empty()) {
envoy_config_core_v3_Locality* locality =
envoy_config_core_v3_Node_mutable_locality(node_msg, context.arena);
if (!node->locality_region().empty()) {
envoy_config_core_v3_Locality_set_region(
locality, StdStringToUpbString(node->locality_region()));
}
if (!node->locality_zone().empty()) {
envoy_config_core_v3_Locality_set_zone(
locality, StdStringToUpbString(node->locality_zone()));
}
if (!node->locality_sub_zone().empty()) {
envoy_config_core_v3_Locality_set_sub_zone(
locality, StdStringToUpbString(node->locality_sub_zone()));
}
}
}
envoy_config_core_v3_Node_set_user_agent_name(
node_msg, StdStringToUpbString(user_agent_name));
envoy_config_core_v3_Node_set_user_agent_version(
node_msg, StdStringToUpbString(user_agent_version));
envoy_config_core_v3_Node_add_client_features(
node_msg,
upb_StringView_FromString("envoy.lb.does_not_support_overprovisioning"),
context.arena);
}

void MaybeLogDiscoveryRequest(
const XdsApiContext& context,
const envoy_service_discovery_v3_DiscoveryRequest* request) {
Expand All @@ -203,6 +154,50 @@ std::string SerializeDiscoveryRequest(

} // namespace

void XdsApi::PopulateNode(envoy_config_core_v3_Node* node_msg,
upb_Arena* arena) {
if (node_ != nullptr) {
if (!node_->id().empty()) {
envoy_config_core_v3_Node_set_id(node_msg,
StdStringToUpbString(node_->id()));
}
if (!node_->cluster().empty()) {
envoy_config_core_v3_Node_set_cluster(
node_msg, StdStringToUpbString(node_->cluster()));
}
if (!node_->metadata().empty()) {
google_protobuf_Struct* metadata =
envoy_config_core_v3_Node_mutable_metadata(node_msg, arena);
PopulateMetadata(metadata, node_->metadata(), arena);
}
if (!node_->locality_region().empty() || !node_->locality_zone().empty() ||
!node_->locality_sub_zone().empty()) {
envoy_config_core_v3_Locality* locality =
envoy_config_core_v3_Node_mutable_locality(node_msg, arena);
if (!node_->locality_region().empty()) {
envoy_config_core_v3_Locality_set_region(
locality, StdStringToUpbString(node_->locality_region()));
}
if (!node_->locality_zone().empty()) {
envoy_config_core_v3_Locality_set_zone(
locality, StdStringToUpbString(node_->locality_zone()));
}
if (!node_->locality_sub_zone().empty()) {
envoy_config_core_v3_Locality_set_sub_zone(
locality, StdStringToUpbString(node_->locality_sub_zone()));
}
}
}
envoy_config_core_v3_Node_set_user_agent_name(
node_msg, StdStringToUpbString(user_agent_name_));
envoy_config_core_v3_Node_set_user_agent_version(
node_msg, StdStringToUpbString(user_agent_version_));
envoy_config_core_v3_Node_add_client_features(
node_msg,
upb_StringView_FromString("envoy.lb.does_not_support_overprovisioning"),
arena);
}

std::string XdsApi::CreateAdsRequest(
absl::string_view type_url, absl::string_view version,
absl::string_view nonce, const std::vector<std::string>& resource_names,
Expand Down Expand Up @@ -249,8 +244,7 @@ std::string XdsApi::CreateAdsRequest(
envoy_config_core_v3_Node* node_msg =
envoy_service_discovery_v3_DiscoveryRequest_mutable_node(request,
arena.ptr());
PopulateNode(context, node_, user_agent_name_, user_agent_version_,
node_msg);
PopulateNode(node_msg, arena.ptr());
envoy_config_core_v3_Node_add_client_features(
node_msg, upb_StringView_FromString("xds.config.resource-in-sotw"),
context.arena);
Expand Down Expand Up @@ -393,7 +387,7 @@ std::string XdsApi::CreateLrsInitialRequest() {
envoy_config_core_v3_Node* node_msg =
envoy_service_load_stats_v3_LoadStatsRequest_mutable_node(request,
arena.ptr());
PopulateNode(context, node_, user_agent_name_, user_agent_version_, node_msg);
PopulateNode(node_msg, arena.ptr());
envoy_config_core_v3_Node_add_client_features(
node_msg,
upb_StringView_FromString("envoy.lrs.supports_send_all_clusters"),
Expand Down Expand Up @@ -575,85 +569,4 @@ absl::Status XdsApi::ParseLrsResponse(absl::string_view encoded_response,
return absl::OkStatus();
}

namespace {

google_protobuf_Timestamp* EncodeTimestamp(const XdsApiContext& context,
Timestamp value) {
google_protobuf_Timestamp* timestamp =
google_protobuf_Timestamp_new(context.arena);
gpr_timespec timespec = value.as_timespec(GPR_CLOCK_REALTIME);
google_protobuf_Timestamp_set_seconds(timestamp, timespec.tv_sec);
google_protobuf_Timestamp_set_nanos(timestamp, timespec.tv_nsec);
return timestamp;
}

} // namespace

std::string XdsApi::AssembleClientConfig(
const ResourceTypeMetadataMap& resource_type_metadata_map) {
upb::Arena arena;
// Create the ClientConfig for resource metadata from XdsClient
auto* client_config = envoy_service_status_v3_ClientConfig_new(arena.ptr());
// Fill-in the node information
auto* node = envoy_service_status_v3_ClientConfig_mutable_node(client_config,
arena.ptr());
const XdsApiContext context = {client_, tracer_, def_pool_->ptr(),
arena.ptr()};
PopulateNode(context, node_, user_agent_name_, user_agent_version_, node);
// Dump each resource.
std::vector<std::string> type_url_storage;
for (const auto& p : resource_type_metadata_map) {
absl::string_view type_url = p.first;
const ResourceMetadataMap& resource_metadata_map = p.second;
type_url_storage.emplace_back(
absl::StrCat("type.googleapis.com/", type_url));
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_storage.back()));
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, EncodeTimestamp(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_storage.back()));
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,
EncodeTimestamp(context, metadata.failed_update_time));
envoy_service_status_v3_ClientConfig_GenericXdsConfig_set_error_state(
entry, update_failure_state);
}
}
}
// Serialize the upb message to bytes
size_t output_length;
char* output = envoy_service_status_v3_ClientConfig_serialize(
client_config, arena.ptr(), &output_length);
return std::string(output, output_length);
}

} // namespace grpc_core
9 changes: 2 additions & 7 deletions src/core/ext/xds/xds_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "envoy/admin/v3/config_dump_shared.upb.h"
#include "envoy/service/status/v3/csds.upb.h"
#include "upb/mem/arena.h"
#include "upb/reflection/def.hpp"

Expand Down Expand Up @@ -126,10 +127,6 @@ class XdsApi {
// Timestamp of the last failed update attempt.
Timestamp failed_update_time;
};
using ResourceMetadataMap =
std::map<std::string /*resource_name*/, const ResourceMetadata*>;
using ResourceTypeMetadataMap =
std::map<absl::string_view /*type_url*/, ResourceMetadataMap>;
static_assert(static_cast<ResourceMetadata::ClientResourceStatus>(
envoy_admin_v3_REQUESTED) ==
ResourceMetadata::ClientResourceStatus::REQUESTED,
Expand Down Expand Up @@ -176,9 +173,7 @@ class XdsApi {
std::set<std::string>* cluster_names,
Duration* load_reporting_interval);

// Assemble the client config proto message and return the serialized result.
std::string AssembleClientConfig(
const ResourceTypeMetadataMap& resource_type_metadata_map);
void PopulateNode(envoy_config_core_v3_Node* node_msg, upb_Arena* arena);

private:
XdsClient* client_;
Expand Down
Loading

0 comments on commit f89c53c

Please sign in to comment.