/proc/self/cwd/source/server/admin/runtime_handler.cc
Line | Count | Source (jump to first uncovered line) |
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 | 5.34k | 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::QueryParams 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::QueryParams params = admin_stream.queryParams(); |
83 | 0 | if (params.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 | overrides.insert(params.begin(), params.end()); |
91 | 0 | TRY_ASSERT_MAIN_THREAD { server_.runtime().mergeValues(overrides); } |
92 | 0 | END_TRY |
93 | 0 | catch (const EnvoyException& e) { |
94 | 0 | ENVOY_LOG_MISC(error, "{}", e.what()); |
95 | 0 | response.add(e.what()); |
96 | 0 | return Http::Code::ServiceUnavailable; |
97 | 0 | } |
98 | 0 | response.add("OK\n"); |
99 | 0 | return Http::Code::OK; |
100 | 0 | } |
101 | | |
102 | | } // namespace Server |
103 | | } // namespace Envoy |