// // Copyright 2022 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include #include "src/core/ext/xds/xds_cluster_specifier_plugin.h" #include #include #include #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "absl/types/variant.h" #include "upb/json_encode.h" #include "upb/status.h" #include "upb/upb.hpp" #include #include "src/core/lib/json/json.h" #include "src/proto/grpc/lookup/v1/rls_config.upb.h" #include "src/proto/grpc/lookup/v1/rls_config.upbdefs.h" namespace grpc_core { // // XdsRouteLookupClusterSpecifierPlugin // absl::string_view XdsRouteLookupClusterSpecifierPlugin::ConfigProtoName() const { return "grpc.lookup.v1.RouteLookupClusterSpecifier"; } void XdsRouteLookupClusterSpecifierPlugin::PopulateSymtab( upb_DefPool* symtab) const { grpc_lookup_v1_RouteLookupConfig_getmsgdef(symtab); } Json XdsRouteLookupClusterSpecifierPlugin::GenerateLoadBalancingPolicyConfig( XdsExtension extension, upb_Arena* arena, upb_DefPool* symtab, ValidationErrors* errors) const { absl::string_view* serialized_plugin_config = absl::get_if(&extension.value); if (serialized_plugin_config == nullptr) { errors->AddError("could not parse plugin config"); return {}; } const auto* specifier = grpc_lookup_v1_RouteLookupClusterSpecifier_parse( serialized_plugin_config->data(), serialized_plugin_config->size(), arena); if (specifier == nullptr) { errors->AddError("could not parse plugin config"); return {}; } const auto* plugin_config = grpc_lookup_v1_RouteLookupClusterSpecifier_route_lookup_config(specifier); if (plugin_config == nullptr) { ValidationErrors::ScopedField field(errors, ".route_lookup_config"); errors->AddError("field not present"); return {}; } upb::Status status; const upb_MessageDef* msg_type = grpc_lookup_v1_RouteLookupConfig_getmsgdef(symtab); size_t json_size = upb_JsonEncode(plugin_config, msg_type, symtab, 0, nullptr, 0, status.ptr()); if (json_size == static_cast(-1)) { errors->AddError(absl::StrCat("failed to dump proto to JSON: ", upb_Status_ErrorMessage(status.ptr()))); return {}; } void* buf = upb_Arena_Malloc(arena, json_size + 1); upb_JsonEncode(plugin_config, msg_type, symtab, 0, reinterpret_cast(buf), json_size + 1, status.ptr()); auto json = Json::Parse(reinterpret_cast(buf)); GPR_ASSERT(json.ok()); return Json::Array{Json::Object{ {"rls_experimental", Json::Object{ {"routeLookupConfig", std::move(*json)}, {"childPolicy", Json::Array{Json::Object{{"cds_experimental", Json::Object()}}}}, {"childPolicyConfigTargetFieldName", "cluster"}, }}}}; } // // XdsClusterSpecifierPluginRegistry // XdsClusterSpecifierPluginRegistry::XdsClusterSpecifierPluginRegistry() { RegisterPlugin(std::make_unique()); } void XdsClusterSpecifierPluginRegistry::RegisterPlugin( std::unique_ptr plugin) { absl::string_view name = plugin->ConfigProtoName(); registry_[name] = std::move(plugin); } const XdsClusterSpecifierPluginImpl* XdsClusterSpecifierPluginRegistry::GetPluginForType( absl::string_view config_proto_type_name) const { auto it = registry_.find(config_proto_type_name); if (it == registry_.end()) return nullptr; return it->second.get(); } void XdsClusterSpecifierPluginRegistry::PopulateSymtab( upb_DefPool* symtab) const { for (const auto& p : registry_) { p.second->PopulateSymtab(symtab); } } } // namespace grpc_core