build: making admin optional#23903
Conversation
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
RyanTheOptimist
left a comment
There was a problem hiding this comment.
88 files? My goodness :)
Looks great other than a few nits.
bazel/README.md
Outdated
| * http3/quic with --//bazel:http3=False | ||
| * autolinking libraries with --define=library_autolink=disabled | ||
| * admin HTML home page with `--define=admin_html=disabled` | ||
| * admin functionlity with `--define=admin_functionaity=disabled` |
There was a problem hiding this comment.
nit: "admin_functionaity" => "admin_functionality", I think?
ci/do_ci.sh
Outdated
|
|
||
| echo "Building and testing with wasm=wasmtime: ${TEST_TARGETS[*]}" | ||
| bazel_with_collection test "${BAZEL_BUILD_OPTIONS[@]}" --define wasm=wasmtime "${COMPILE_TIME_OPTIONS[@]}" -c dbg "${TEST_TARGETS[@]}" --test_tag_filters=-nofips --build_tests_only | ||
| echo "Building and testing with wasm=wasmtime: and admin_functionality disabled ${TEST_TARGETS[*]}" |
There was a problem hiding this comment.
nit: Maybe mention admin_html too, for completeness?
| "using_deprecated_config.yaml", | ||
| "**/*.template.yaml", | ||
| "freebind/freebind.yaml", | ||
| "envoy-tap-config.yaml", |
There was a problem hiding this comment.
Out of curiosity, why does this need to be added?
There was a problem hiding this comment.
the tap filter has admin functionality. I didn't go through the exercise of carving that out, the entire tap filter simply won't compile.
Because of that we exempt tap here and add it back below as long as admin isn't disabled
| // ConfigTracker keys must be unique. We are asserting that no one has stolen the key | ||
| // from us, since the returned entry will be nullptr if the key already exists. | ||
| RELEASE_ASSERT(config_tracker_entry_, ""); | ||
| if (admin.has_value()) { |
There was a problem hiding this comment.
nit: early return
if (!admin.has_value()) {
return;
}
...
There was a problem hiding this comment.
Why not just use the ifdef?
Or do you also support (or plan to support) disabling admin at runtime via a runtime or command-line flag while still compiling it in?
There was a problem hiding this comment.
I prefer most of the code compiling in both branches and minimal use of the ifdef. it means we can get coverage for more code for example
| // from us, since the returned entry will be nullptr if the key already exists. | ||
| RELEASE_ASSERT(config_tracker_entry_, ""); | ||
| : proto_traits_(proto_traits) { | ||
| if (admin.has_value()) { |
source/exe/main_common.cc
Outdated
| void MainCommonBase::adminRequest(absl::string_view path_and_query, absl::string_view method, | ||
| const AdminRequestFn& handler) { | ||
| RELEASE_ASSERT(server_->admin().has_value(), | ||
| "adminRequest called with admin support compiled out"); |
There was a problem hiding this comment.
You'd know better than I would, but I wonder if instead of RELEASE_ASSERT if we should just ASSERT() in debug, and return in release? But I suspect you already thought about this.
There was a problem hiding this comment.
Why would we want to assert at all? Can't we just call the handler with an http error code? Maybe a 501?
There was a problem hiding this comment.
it's a bug to call admin requests with them compiled out. I think we should definitely crash in debug mode at least.
| "adding hystrix_event_stream endpoint to enable connection to hystrix dashboard"); | ||
| admin.addHandler("/hystrix_event_stream", "send hystrix event stream", | ||
| MAKE_ADMIN_HANDLER(handlerHystrixEventStream), false, false); | ||
| if (server.admin().has_value()) { |
| /** | ||
| * Closes the listening socket for the admin. | ||
| */ | ||
| virtual void closeSocket() PURE; |
There was a problem hiding this comment.
I can't seem to figure out why this new pure virtual method is needed. Oh is it because we're using std::unique_ptr<Admin> admin_ instead of std::unique_ptr<AdminImpl> admin_ in server.h? Do we need to make that change?
There was a problem hiding this comment.
we do, or the server (which now has an API pointer because it may not know about the impl class) can't close the socket.
There was a problem hiding this comment.
I believe you, but I don't yet understand how to connect all the dots :) Why does the server need an API pointer now when before it had an impl pointer?
| // Server::Instance | ||
| Admin& admin() override { return *admin_; } | ||
| OptRef<Admin> admin() override { | ||
| return makeOptRefFromPtr(reinterpret_cast<Envoy::Server::Admin*>(admin_.get())); |
There was a problem hiding this comment.
I'm surprised to see reinterpret_cast here instead of static_cast. Does static_cast work here?
There was a problem hiding this comment.
apparently - thought I tried that but must have been something else.
| @@ -1,5 +1,7 @@ | |||
| #include "envoy/extensions/http/header_formatters/preserve_case/v3/preserve_case.pb.h" | |||
|
|
|||
| #include "source/extensions/filters/http/common/pass_through_filter.h" | |||
There was a problem hiding this comment.
Out of curiosity, how did you find this to be missing?
There was a problem hiding this comment.
build failed with admin disabled flags. because Envoy doesn't IWYU sometimes when you remove one include or library you have to add others in unexpected places.
source/exe/main_common.cc
Outdated
| void MainCommonBase::adminRequest(absl::string_view path_and_query, absl::string_view method, | ||
| const AdminRequestFn& handler) { | ||
| RELEASE_ASSERT(server_->admin().has_value(), | ||
| "adminRequest called with admin support compiled out"); |
There was a problem hiding this comment.
Why would we want to assert at all? Can't we just call the handler with an http error code? Maybe a 501?
| #endif | ||
|
|
||
| #ifndef ENVOY_ADMIN_FUNCTIONALITY | ||
| #define DISABLE_IF_ADMIN_DISABLED return |
There was a problem hiding this comment.
nit: RETURN_IF_ADMIN_DISABLED may be more obvious at call-sites. If I read this in the middle of a function I might not know what DISABLE meant.
Also -- why not use this pattern in production code also? It's somewhat nice in a way :)
There was a problem hiding this comment.
don't use in production code because we don't always want returns in the production code
for tests I agree I prefer RETURN but I'm following the pattern. I'm inclined to do a follow-up and replace them all together, WDYT?
| // ConfigTracker keys must be unique. We are asserting that no one has stolen the key | ||
| // from us, since the returned entry will be nullptr if the key already exists. | ||
| RELEASE_ASSERT(config_tracker_entry_, ""); | ||
| if (admin.has_value()) { |
There was a problem hiding this comment.
Why not just use the ifdef?
Or do you also support (or plan to support) disabling admin at runtime via a runtime or command-line flag while still compiling it in?
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
source/exe/main_common.cc
Outdated
|
|
||
| void MainCommonBase::adminRequest(absl::string_view path_and_query, absl::string_view method, | ||
| const AdminRequestFn& handler) { | ||
| ASSERT(server_->admin().has_value(), "adminRequest called with admin support compiled out"); |
There was a problem hiding this comment.
ok having this assert in in debug mode seems OK. But if we are not in debug mode should we return a 501 or something?
Seems like the fall-through case is going to jus not populate response_headers at all which might be confusing.
Alternatively -- I know you are not going to like this, but this is really a C++ API for folks that instantiate main_common themselves and can call methods on it. You could ifdef out the existence of this method entirely so calling it would be a build failure rather than a crash. But it's up to you.
There was a problem hiding this comment.
I don't love it, but I'll take it over a custom error path no one actually wants but I'd otherwise feel obliged to write tests for =P
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
RyanTheOptimist
left a comment
There was a problem hiding this comment.
LGTM, though I'm still curious about the AdminImpl => Admin change which necessitated the closeSocket method being added to the interface.
| /** | ||
| * Closes the listening socket for the admin. | ||
| */ | ||
| virtual void closeSocket() PURE; |
There was a problem hiding this comment.
I believe you, but I don't yet understand how to connect all the dots :) Why does the server need an API pointer now when before it had an impl pointer?
4a3f628
|
Before the server had an admin pointer because it knew about the admin class. With this change we stick the impl behind the "is admin compiled in" flags, so the class tracks the interface (since the impl may be compiled out) and the interface needs close socket. alternately we could stick close socket behind an ifdef and down cast from the interface to the impl, but this seemed much cleaner to me. |
|
/retest |
|
Retrying Azure Pipelines: |
AH! Yeah, ok that makes perfect sense (of course :>). Conditionally compiling would also seem fine but so does this. Thanks for the explanation. Still LGTM! |
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Adding a build option to compile out Envoy's admin code.
The main API change is making the admin APIs OptRef instead of explicit references, which requires update to any code which adds config trackers for the admin console.
Risk Level: medium
Testing: new CI build with new flags
Docs Changes: n/a
Release Notes: not currently included
Platform Specific Features:
Fixes #23823