Coverage Report

Created: 2023-11-12 09:30

/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