LCOV - code coverage report
Current view: top level - source/server/admin - runtime_handler.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 1 72 1.4 %
Date: 2024-01-05 06:35:25 Functions: 1 3 33.3 %

          Line data    Source code
       1             : #include "source/server/admin/runtime_handler.h"
       2             : 
       3             : #include <string>
       4             : #include <vector>
       5             : 
       6             : #include "source/common/common/empty_string.h"
       7             : #include "source/common/http/headers.h"
       8             : #include "source/common/http/utility.h"
       9             : #include "source/server/admin/utils.h"
      10             : 
      11             : #include "absl/container/node_hash_map.h"
      12             : 
      13             : namespace Envoy {
      14             : namespace Server {
      15             : 
      16         134 : RuntimeHandler::RuntimeHandler(Server::Instance& server) : HandlerContextBase(server) {}
      17             : 
      18             : Http::Code RuntimeHandler::handlerRuntime(Http::ResponseHeaderMap& response_headers,
      19           0 :                                           Buffer::Instance& response, AdminStream& admin_stream) {
      20           0 :   const Http::Utility::QueryParamsMulti params = admin_stream.queryParams();
      21           0 :   response_headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Json);
      22             : 
      23             :   // TODO(jsedgwick): Use proto to structure this output instead of arbitrary JSON.
      24           0 :   const auto& layers = server_.runtime().snapshot().getLayers();
      25             : 
      26           0 :   std::vector<ProtobufWkt::Value> layer_names;
      27           0 :   layer_names.reserve(layers.size());
      28           0 :   std::map<std::string, std::vector<std::string>> entries;
      29           0 :   for (const auto& layer : layers) {
      30           0 :     layer_names.push_back(ValueUtil::stringValue(layer->name()));
      31           0 :     for (const auto& value : layer->values()) {
      32           0 :       const auto found = entries.find(value.first);
      33           0 :       if (found == entries.end()) {
      34           0 :         entries.emplace(value.first, std::vector<std::string>{});
      35           0 :       }
      36           0 :     }
      37           0 :   }
      38             : 
      39           0 :   for (const auto& layer : layers) {
      40           0 :     for (auto& entry : entries) {
      41           0 :       const auto found = layer->values().find(entry.first);
      42           0 :       const auto& entry_value =
      43           0 :           found == layer->values().end() ? EMPTY_STRING : found->second.raw_string_value_;
      44           0 :       entry.second.push_back(entry_value);
      45           0 :     }
      46           0 :   }
      47             : 
      48           0 :   ProtobufWkt::Struct layer_entries;
      49           0 :   auto* layer_entry_fields = layer_entries.mutable_fields();
      50           0 :   for (const auto& entry : entries) {
      51           0 :     std::vector<ProtobufWkt::Value> layer_entry_values;
      52           0 :     layer_entry_values.reserve(entry.second.size());
      53           0 :     std::string final_value;
      54           0 :     for (const auto& value : entry.second) {
      55           0 :       if (!value.empty()) {
      56           0 :         final_value = value;
      57           0 :       }
      58           0 :       layer_entry_values.push_back(ValueUtil::stringValue(value));
      59           0 :     }
      60             : 
      61           0 :     ProtobufWkt::Struct layer_entry_value;
      62           0 :     auto* layer_entry_value_fields = layer_entry_value.mutable_fields();
      63             : 
      64           0 :     (*layer_entry_value_fields)["final_value"] = ValueUtil::stringValue(final_value);
      65           0 :     (*layer_entry_value_fields)["layer_values"] = ValueUtil::listValue(layer_entry_values);
      66           0 :     (*layer_entry_fields)[entry.first] = ValueUtil::structValue(layer_entry_value);
      67           0 :   }
      68             : 
      69           0 :   ProtobufWkt::Struct runtime;
      70           0 :   auto* fields = runtime.mutable_fields();
      71             : 
      72           0 :   (*fields)["layers"] = ValueUtil::listValue(layer_names);
      73           0 :   (*fields)["entries"] = ValueUtil::structValue(layer_entries);
      74             : 
      75           0 :   response.add(MessageUtil::getJsonStringFromMessageOrError(runtime, true, true));
      76           0 :   return Http::Code::OK;
      77           0 : }
      78             : 
      79             : Http::Code RuntimeHandler::handlerRuntimeModify(Http::ResponseHeaderMap&,
      80             :                                                 Buffer::Instance& response,
      81           0 :                                                 AdminStream& admin_stream) {
      82           0 :   Http::Utility::QueryParamsMulti params = admin_stream.queryParams();
      83           0 :   if (params.data().empty()) {
      84           0 :     response.add("usage: /runtime_modify?key1=value1&key2=value2&keyN=valueN\n");
      85           0 :     response.add("       or send the parameters as form values\n");
      86           0 :     response.add("use an empty value to remove a previously added override");
      87           0 :     return Http::Code::BadRequest;
      88           0 :   }
      89           0 :   absl::node_hash_map<std::string, std::string> overrides;
      90           0 :   for (const auto& it : params.data()) {
      91           0 :     overrides.insert({it.first, it.second[0]});
      92           0 :   }
      93           0 :   TRY_ASSERT_MAIN_THREAD { server_.runtime().mergeValues(overrides); }
      94           0 :   END_TRY
      95           0 :   catch (const EnvoyException& e) {
      96           0 :     ENVOY_LOG_MISC(error, "{}", e.what());
      97           0 :     response.add(e.what());
      98           0 :     return Http::Code::ServiceUnavailable;
      99           0 :   }
     100           0 :   response.add("OK\n");
     101           0 :   return Http::Code::OK;
     102           0 : }
     103             : 
     104             : } // namespace Server
     105             : } // namespace Envoy

Generated by: LCOV version 1.15