Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
c4101e1
initial patch
jmarantz Jan 14, 2022
29cf776
get tests working
jmarantz Jan 14, 2022
94c97c0
Add parameters for other admin endpoints. Still need runtime_modify.
jmarantz Jan 14, 2022
aa00670
add coverage for the HTML generator
jmarantz Jan 15, 2022
34c7607
coverage
jmarantz Jan 15, 2022
4e821b4
coverage and doc
jmarantz Jan 15, 2022
8cbcf36
cover html rendering
jmarantz Jan 16, 2022
ff2aaf9
revert pointless name-change and rewrite comment.
jmarantz Jan 16, 2022
1e4d606
remove unused styles
jmarantz Jan 16, 2022
256b6c9
test cleanup
jmarantz Jan 16, 2022
49212f6
Merge branch 'main' into admin-params
jmarantz Jan 17, 2022
ba5a1dc
Remove the intermediate vectors for stats by using forEach for insert…
jmarantz Jan 17, 2022
c78b6a4
Merge branch 'main' into admin-params
jmarantz Jan 19, 2022
33b2f22
Go back to sorting by strings as it's somewhat faster than sorting by…
jmarantz Jan 19, 2022
efe142e
add in ifdef'd version where we do the sort in StaName space.
jmarantz Jan 20, 2022
78091d1
Merge branch 'main' into admin-params
jmarantz Feb 26, 2022
119270c
get build working
jmarantz Feb 26, 2022
68a89d2
fix respones code expectation
jmarantz Feb 26, 2022
70ce924
cleanup
jmarantz Feb 26, 2022
71c1647
Merge branch 'main' into admin-params
jmarantz Mar 2, 2022
d04a05c
get compile working again
jmarantz Mar 2, 2022
85d33f7
Merge branch 'main' into admin-params
jmarantz Apr 6, 2022
d482473
compiles and links tests, but tests fail
jmarantz Apr 7, 2022
d42f01a
All tests working and formatted.
jmarantz Apr 8, 2022
2c4422a
reduce allow-list for std::regex and cleanup commented-out code.
jmarantz Apr 8, 2022
594b618
Merge branch 'main' into admin-params
jmarantz Apr 8, 2022
102d95c
fix signature
jmarantz Apr 8, 2022
a5706e1
fix naming inconsistency
jmarantz Apr 8, 2022
a4de093
add missing function
jmarantz Apr 8, 2022
246af3a
Merge branch 'main' into admin-params
jmarantz Apr 10, 2022
987e764
cleanup
jmarantz Apr 10, 2022
5f5ae3c
use the correct UrlHandler block for /stats.
jmarantz Apr 10, 2022
c9041e6
add histogram buckets into UI params.
jmarantz Apr 11, 2022
afbcf1a
finalize before returning when we are not covering all types.
jmarantz Apr 11, 2022
3fc02f0
format
jmarantz Apr 11, 2022
fc5ac30
Merge branch 'main' into admin-params
jmarantz Apr 11, 2022
7bb3a00
Merge branch 'main' into admin-params
jmarantz Apr 20, 2022
6dcac05
format
jmarantz Apr 20, 2022
81f2763
API change for StatsParams
jmarantz Apr 20, 2022
329281b
Merge branch 'main' into admin-params
jmarantz Apr 22, 2022
c537b80
Merge branch 'main' into admin-params
jmarantz May 11, 2022
25c871e
try to get it to compile
jmarantz May 12, 2022
685e307
get tests working
jmarantz May 12, 2022
182c26d
Merge branch 'main' into admin-params
jmarantz Jun 24, 2022
fecece3
fix tests
jmarantz Jun 24, 2022
f187c65
get tests working in html-disabled mode.
jmarantz Jun 24, 2022
d16f773
cleanup
jmarantz Jun 25, 2022
2ec28de
emit the parameter info in the /help response.
jmarantz Jul 1, 2022
e23c884
format
jmarantz Jul 1, 2022
4f59d62
unbreak
jmarantz Jul 1, 2022
c2350a2
Merge branch 'main' into admin-params
jmarantz Jul 1, 2022
c9a0467
get tests woring with and without html.
jmarantz Jul 2, 2022
e8abc92
format
jmarantz Jul 2, 2022
bfb734a
cover some missing cases
jmarantz Jul 2, 2022
752ae63
add pass-thru overrides for Html rendering to fix gcc builds.
jmarantz Jul 2, 2022
e8d16fd
cover html histogram rendering.
jmarantz Jul 2, 2022
abe2049
add coverage
jmarantz Jul 2, 2022
ab028cf
format
jmarantz Jul 2, 2022
d9d03c8
Merge branch 'main' into admin-params
jmarantz Jul 4, 2022
b28dd55
add comments
jmarantz Jul 11, 2022
1b95d3b
properly sanitize the filter and quote it.
jmarantz Jul 12, 2022
048d239
split out the html rendered into its own files.
jmarantz Jul 12, 2022
93fe3f3
format
jmarantz Jul 12, 2022
5c0fd6c
Merge branch 'main' into admin-params
jmarantz Jul 12, 2022
85cde04
refactor to remove extra html implementation files
jmarantz Jul 12, 2022
b626917
tighten up the logic.
jmarantz Jul 13, 2022
ddda5d7
Merge branch 'main' into admin-params
jmarantz Jul 15, 2022
2a62570
Merge branch 'main' into admin-params
jmarantz Jul 17, 2022
03be332
add accessibility annotations.
jmarantz Jul 17, 2022
ce6e904
fix html validation errors.
jmarantz Jul 17, 2022
26f200d
fix unit tests and prepopulated values.
jmarantz Jul 17, 2022
50dbe5a
Render endpoints using GET that don't have params as simple a tags.
jmarantz Jul 18, 2022
0859243
review comments
jmarantz Jul 22, 2022
603f0f8
Merge branch 'main' into admin-params
jmarantz Jul 22, 2022
1cc67ca
Merge branch 'main' into admin-params
jmarantz Jul 25, 2022
ee21f74
add missing params (round 1)
jmarantz Jul 25, 2022
379b316
add remaining missing admin query params.
jmarantz Jul 26, 2022
a7b3565
back out post support for now
jmarantz Jul 26, 2022
c456954
back out more post params
jmarantz Jul 26, 2022
8c3af8b
format
jmarantz Jul 26, 2022
58c8b81
restore post params hacks.
jmarantz Jul 26, 2022
36888b8
Use AdminFilter::queryParams() to get post-data aware QueryParams.
jmarantz Jul 27, 2022
1738fc7
get POSTs working more generally.
jmarantz Jul 27, 2022
35595ac
format
jmarantz Jul 27, 2022
c820090
correct deliver for /logging help text
jmarantz Jul 28, 2022
da2db71
Merge branch 'main' into admin-post-params
jmarantz Jul 29, 2022
4f2025f
cleanup
jmarantz Jul 29, 2022
bcc798b
set the path when setting the method.
jmarantz Jul 30, 2022
8c9d80c
ensure the request headers path is set properly when running and admi…
jmarantz Jul 30, 2022
b17ad84
explicity specify a string-ref to extract queries out to avoid copyin…
jmarantz Jul 31, 2022
855d881
use range loop per tidy
jmarantz Jul 31, 2022
1c3e458
const decls.
jmarantz Aug 1, 2022
832ea51
Set up y/n enum param for "/cpuprofiler", ignore blank query values.
jmarantz Aug 2, 2022
4d7b7e5
fix tests
jmarantz Aug 2, 2022
f76377b
comments
jmarantz Aug 2, 2022
327ce0f
Keep-it-simple just use by-value passing and returning for vector<str…
jmarantz Aug 2, 2022
e6c81a0
indicate which endpoints require POST in the help text.
jmarantz Aug 2, 2022
8ce26f4
Merge branch 'main' into admin-post-params
jmarantz Aug 4, 2022
32ce495
Merge branch 'main' into admin-post-params
jmarantz Aug 10, 2022
4ec9bad
add promps for /heapprofiler args
jmarantz Aug 10, 2022
e17e9b4
Merge branch 'main' into admin-post-params
jmarantz Aug 10, 2022
09ca850
revert bad bazelversion
jmarantz Aug 10, 2022
c77f7cf
tweak coverage goals -- the profiler impl by its nature has hard-to-r…
jmarantz Aug 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion envoy/server/admin.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ class AdminStream {
* absl::nullopt.
*/
virtual Http::Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() PURE;

/**
* Construct query-param map for the stream, using the URL-specified params,
* or the request data if that is url-form-encoded.
*
* @param The query name/value map.
*/
virtual Http::Utility::QueryParams queryParams() const PURE;
};

/**
Expand Down Expand Up @@ -102,7 +110,7 @@ class Admin {
enum class Type { Boolean, String, Enum };
const Type type_;
const std::string id_; // HTML form ID and query-param name (JS var name rules).
const std::string help_; // Help text rendered into UI.
const std::string help_; // Rendered into home-page HTML and /help text.
std::vector<absl::string_view> enum_choices_{};
};
using ParamDescriptorVec = std::vector<ParamDescriptor>;
Expand Down
54 changes: 44 additions & 10 deletions source/server/admin/admin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ void AdminImpl::startHttpListener(const std::list<AccessLog::InstanceSharedPtr>&
}
}

namespace {
// Prepends an element to an array, modifying it as passed in.
std::vector<absl::string_view> prepend(const absl::string_view first,
std::vector<absl::string_view> strings) {
strings.insert(strings.begin(), first);
return strings;
}
} // namespace

AdminImpl::AdminImpl(const std::string& profile_path, Server::Instance& server,
bool ignore_global_conn_limit)
: server_(server),
Expand Down Expand Up @@ -122,9 +131,17 @@ AdminImpl::AdminImpl(const std::string& profile_path, Server::Instance& server,
makeHandler("/contention", "dump current Envoy mutex contention stats (if enabled)",
MAKE_ADMIN_HANDLER(stats_handler_.handlerContention), false, false),
makeHandler("/cpuprofiler", "enable/disable the CPU profiler",
MAKE_ADMIN_HANDLER(profiling_handler_.handlerCpuProfiler), false, true),
MAKE_ADMIN_HANDLER(profiling_handler_.handlerCpuProfiler), false, true,
{{Admin::ParamDescriptor::Type::Enum,
"enable",
"enables the CPU profiler",
{"y", "n"}}}),
makeHandler("/heapprofiler", "enable/disable the heap profiler",
MAKE_ADMIN_HANDLER(profiling_handler_.handlerHeapProfiler), false, true),
MAKE_ADMIN_HANDLER(profiling_handler_.handlerHeapProfiler), false, true,
{{Admin::ParamDescriptor::Type::Enum,
"enable",
"enable/disable the heap profiler",
{"y", "n"}}}),
makeHandler("/heap_dump", "dump current Envoy heap (if supported)",
MAKE_ADMIN_HANDLER(tcmalloc_profiling_handler_.handlerHeapDump), false,
false),
Expand All @@ -138,20 +155,34 @@ AdminImpl::AdminImpl(const std::string& profile_path, Server::Instance& server,
MAKE_ADMIN_HANDLER(server_info_handler_.handlerHotRestartVersion), false,
false),

// TODO(jmarantz): add support for param-passing through a POST. Browsers send
// those params as the post-body rather than query-params and that requires some
// re-plumbing through the admin callback API. See also drain_listeners.
// The logging "level" parameter, if specified as a non-blank entry,
// changes all the logging-paths to that level. So the enum parameter
// needs to include a an empty string as the default (first) option.
// Thus we prepend an empty string to the logging-levels list.
makeHandler("/logging", "query/change logging levels",
MAKE_ADMIN_HANDLER(logs_handler_.handlerLogging), false, true),

MAKE_ADMIN_HANDLER(logs_handler_.handlerLogging), false, true,
{{Admin::ParamDescriptor::Type::String, "paths",
"Change multiple logging levels by setting to "
"<logger_name1>:<desired_level1>,<logger_name2>:<desired_level2>."},
{Admin::ParamDescriptor::Type::Enum, "level", "desired logging level",
prepend("", LogsHandler::levelStrings())}}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does empty level do? I could not find this info here https://www.envoyproxy.io/docs/envoy/latest/operations/admin#post--logging

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this particular command, if you specify one of the logging levels, it will change all the logging paths to use that level. If you leave the level blank then it will perform some other operation -- either just listing out the current levels for each path, or setting particular path/level combos.

I'll add a comment.

makeHandler("/memory", "print current allocation/heap usage",
MAKE_ADMIN_HANDLER(server_info_handler_.handlerMemory), false, false),
makeHandler("/quitquitquit", "exit the server",
MAKE_ADMIN_HANDLER(server_cmd_handler_.handlerQuitQuitQuit), false, true),
makeHandler("/reset_counters", "reset all counters to zero",
MAKE_ADMIN_HANDLER(stats_handler_.handlerResetCounters), false, true),
makeHandler("/drain_listeners", "drain listeners",
MAKE_ADMIN_HANDLER(listeners_handler_.handlerDrainListeners), false, true),
makeHandler(
"/drain_listeners", "drain listeners",
MAKE_ADMIN_HANDLER(listeners_handler_.handlerDrainListeners), false, true,
{{ParamDescriptor::Type::Boolean, "graceful",
"When draining listeners, enter a graceful drain period prior to closing "
"listeners. This behaviour and duration is configurable via server options "
"or CLI"},
{ParamDescriptor::Type::Boolean, "inboundonly",
"Drains all inbound listeners. traffic_direction field in "
"envoy_v3_api_msg_config.listener.v3.Listener is used to determine whether a "
"listener is inbound or outbound."}}),
makeHandler("/server_info", "print server version/status information",
MAKE_ADMIN_HANDLER(server_info_handler_.handlerServerInfo), false, false),
makeHandler("/ready", "print server state, return 200 if LIVE, otherwise return 503",
Expand Down Expand Up @@ -335,6 +366,7 @@ Admin::RequestPtr AdminImpl::makeRequest(absl::string_view path_and_query,
}
}

ASSERT(admin_stream.getRequestHeaders().getPathValue() == path_and_query);
return handler.handler_(path_and_query, admin_stream);
}
}
Expand Down Expand Up @@ -369,7 +401,8 @@ void AdminImpl::getHelp(Buffer::Instance& response) const {

// Prefix order is used during searching, but for printing do them in alpha order.
for (const UrlHandler* handler : sortedHandlers()) {
response.add(fmt::format(" {}: {}\n", handler->prefix_, handler->help_text_));
const absl::string_view method = handler->mutates_server_state_ ? " (POST)" : "";
response.add(fmt::format(" {}{}: {}\n", handler->prefix_, method, handler->help_text_));
for (const ParamDescriptor& param : handler->params_) {
response.add(fmt::format(" {}: {}", param.id_, param.help_));
if (param.type_ == ParamDescriptor::Type::Enum) {
Expand Down Expand Up @@ -440,6 +473,7 @@ Http::Code AdminImpl::request(absl::string_view path_and_query, absl::string_vie

auto request_headers = Http::RequestHeaderMapImpl::create();
request_headers->setMethod(method);
request_headers->setPath(path_and_query);
filter.decodeHeaders(*request_headers, false);
Buffer::OwnedImpl response;

Expand Down
21 changes: 20 additions & 1 deletion source/server/admin/admin_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,27 @@ const Http::RequestHeaderMap& AdminFilter::getRequestHeaders() const {
return *request_headers_;
}

Http::Utility::QueryParams AdminFilter::queryParams() const {
absl::string_view path = request_headers_->getPathValue();
Http::Utility::QueryParams query = Http::Utility::parseAndDecodeQueryString(path);
if (!query.empty()) {
return query;
}

// Check if the params are in the request's body.
if (request_headers_->getContentTypeValue() ==
Http::Headers::get().ContentTypeValues.FormUrlEncoded) {
const Buffer::Instance* body = getRequestBody();
if (body != nullptr) {
query = Http::Utility::parseFromBody(body->toString());
}
}

return query;
}

void AdminFilter::onComplete() {
const absl::string_view path = request_headers_->getPathValue();
absl::string_view path = request_headers_->getPathValue();
ENVOY_STREAM_LOG(debug, "request complete: path: {}", *decoder_callbacks_, path);

auto header_map = Http::ResponseHeaderMapImpl::create();
Expand Down
1 change: 1 addition & 0 deletions source/server/admin/admin_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class AdminFilter : public Http::PassThroughFilter,
Http::Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override {
return encoder_callbacks_->http1StreamEncoderOptions();
}
Http::Utility::QueryParams queryParams() const override;

private:
/**
Expand Down
7 changes: 3 additions & 4 deletions source/server/admin/clusters_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,10 @@ void addCircuitBreakerSettingsAsJson(const envoy::config::core::v3::RoutingPrior

ClustersHandler::ClustersHandler(Server::Instance& server) : HandlerContextBase(server) {}

Http::Code ClustersHandler::handlerClusters(absl::string_view url,
Http::Code ClustersHandler::handlerClusters(absl::string_view,
Http::ResponseHeaderMap& response_headers,
Buffer::Instance& response, AdminStream&) {
Http::Utility::QueryParams query_params = Http::Utility::parseAndDecodeQueryString(url);
const auto format_value = Utility::formatParam(query_params);
Buffer::Instance& response, AdminStream& admin_stream) {
const auto format_value = Utility::formatParam(admin_stream.queryParams());

if (format_value.has_value() && format_value.value() == "json") {
writeClustersAsJson(response);
Expand Down
11 changes: 6 additions & 5 deletions source/server/admin/config_dump_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,13 @@ absl::optional<std::string> maskParam(const Http::Utility::QueryParams& params)

// Helper method to get the eds parameter.
bool shouldIncludeEdsInDump(const Http::Utility::QueryParams& params) {
return Utility::queryParam(params, "include_eds") != absl::nullopt;
return params.find("include_eds") != params.end();
}

absl::StatusOr<Matchers::StringMatcherPtr>
buildNameMatcher(const Http::Utility::QueryParams& params) {
const auto name_regex = Utility::queryParam(params, "name_regex");
if (!name_regex.has_value()) {
if (!name_regex.has_value() || name_regex->empty()) {
return std::make_unique<Matchers::UniversalStringMatcher>();
}
envoy::type::matcher::v3::RegexMatcher matcher;
Expand All @@ -157,10 +157,11 @@ buildNameMatcher(const Http::Utility::QueryParams& params) {
ConfigDumpHandler::ConfigDumpHandler(ConfigTracker& config_tracker, Server::Instance& server)
: HandlerContextBase(server), config_tracker_(config_tracker) {}

Http::Code ConfigDumpHandler::handlerConfigDump(absl::string_view url,
Http::Code ConfigDumpHandler::handlerConfigDump(absl::string_view,
Http::ResponseHeaderMap& response_headers,
Buffer::Instance& response, AdminStream&) const {
Http::Utility::QueryParams query_params = Http::Utility::parseAndDecodeQueryString(url);
Buffer::Instance& response,
AdminStream& admin_stream) const {
Http::Utility::QueryParams query_params = admin_stream.queryParams();
const auto resource = resourceParam(query_params);
const auto mask = maskParam(query_params);
const bool include_eds = shouldIncludeEdsInDump(query_params);
Expand Down
8 changes: 4 additions & 4 deletions source/server/admin/init_dump_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ absl::optional<std::string> maskParam(const Http::Utility::QueryParams& params)

InitDumpHandler::InitDumpHandler(Server::Instance& server) : HandlerContextBase(server) {}

Http::Code InitDumpHandler::handlerInitDump(absl::string_view url,
Http::Code InitDumpHandler::handlerInitDump(absl::string_view,
Http::ResponseHeaderMap& response_headers,
Buffer::Instance& response, AdminStream&) const {
Http::Utility::QueryParams query_params = Http::Utility::parseAndDecodeQueryString(url);
const auto mask = maskParam(query_params);
Buffer::Instance& response,
AdminStream& admin_stream) const {
const auto mask = maskParam(admin_stream.queryParams());

envoy::admin::v3::UnreadyTargetsDumps dump = *dumpUnreadyTargets(mask);
MessageUtil::redact(dump);
Expand Down
14 changes: 8 additions & 6 deletions source/server/admin/listeners_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ namespace Server {

ListenersHandler::ListenersHandler(Server::Instance& server) : HandlerContextBase(server) {}

Http::Code ListenersHandler::handlerDrainListeners(absl::string_view url, Http::ResponseHeaderMap&,
Buffer::Instance& response, AdminStream&) {
const Http::Utility::QueryParams params = Http::Utility::parseQueryString(url);
Http::Code ListenersHandler::handlerDrainListeners(absl::string_view, Http::ResponseHeaderMap&,
Buffer::Instance& response,
AdminStream& admin_query) {
const Http::Utility::QueryParams params = admin_query.queryParams();

ListenerManager::StopListenersType stop_listeners_type =
params.find("inboundonly") != params.end() ? ListenerManager::StopListenersType::InboundOnly
Expand All @@ -37,10 +38,11 @@ Http::Code ListenersHandler::handlerDrainListeners(absl::string_view url, Http::
return Http::Code::OK;
}

Http::Code ListenersHandler::handlerListenerInfo(absl::string_view url,
Http::Code ListenersHandler::handlerListenerInfo(absl::string_view,
Http::ResponseHeaderMap& response_headers,
Buffer::Instance& response, AdminStream&) {
const Http::Utility::QueryParams query_params = Http::Utility::parseQueryString(url);
Buffer::Instance& response,
AdminStream& admin_query) {
const Http::Utility::QueryParams query_params = admin_query.queryParams();
const auto format_value = Utility::formatParam(query_params);

if (format_value.has_value() && format_value.value() == "json") {
Expand Down
Loading