diff --git a/api/BUILD b/api/BUILD index fe373e4533d5..37b0818d0a54 100644 --- a/api/BUILD +++ b/api/BUILD @@ -163,6 +163,7 @@ proto_library( "//envoy/extensions/common/tap/v3:pkg", "//envoy/extensions/filters/common/fault/v3:pkg", "//envoy/extensions/filters/http/adaptive_concurrency/v3:pkg", + "//envoy/extensions/filters/http/admin/v3:pkg", "//envoy/extensions/filters/http/aws_lambda/v3:pkg", "//envoy/extensions/filters/http/aws_request_signing/v3:pkg", "//envoy/extensions/filters/http/buffer/v3:pkg", diff --git a/api/envoy/config/bootstrap/v3/bootstrap.proto b/api/envoy/config/bootstrap/v3/bootstrap.proto index c20109884d90..68bf3bbf0d0e 100644 --- a/api/envoy/config/bootstrap/v3/bootstrap.proto +++ b/api/envoy/config/bootstrap/v3/bootstrap.proto @@ -181,6 +181,7 @@ message Bootstrap { // Administration interface :ref:`operations documentation // `. +// [#next-free-field: 6] message Admin { option (udpa.annotations.versioning).previous_message_type = "envoy.config.bootstrap.v2.Admin"; @@ -200,6 +201,9 @@ message Admin { // Additional socket options that may not be present in Envoy source code or // precompiled binaries. repeated core.v3.SocketOption socket_options = 4; + + // Static :ref:`Listener `. + listener.v3.Listener listener = 5; } // Cluster manager :ref:`architecture overview `. diff --git a/api/envoy/config/bootstrap/v4alpha/bootstrap.proto b/api/envoy/config/bootstrap/v4alpha/bootstrap.proto index ce6aa147fba2..34e23d72aa16 100644 --- a/api/envoy/config/bootstrap/v4alpha/bootstrap.proto +++ b/api/envoy/config/bootstrap/v4alpha/bootstrap.proto @@ -173,6 +173,7 @@ message Bootstrap { // Administration interface :ref:`operations documentation // `. +// [#next-free-field: 6] message Admin { option (udpa.annotations.versioning).previous_message_type = "envoy.config.bootstrap.v3.Admin"; @@ -192,6 +193,9 @@ message Admin { // Additional socket options that may not be present in Envoy source code or // precompiled binaries. repeated core.v4alpha.SocketOption socket_options = 4; + + // Static :ref:`Listener `. + listener.v4alpha.Listener listener = 5; } // Cluster manager :ref:`architecture overview `. diff --git a/api/envoy/extensions/filters/http/admin/v3/BUILD b/api/envoy/extensions/filters/http/admin/v3/BUILD new file mode 100644 index 000000000000..ef3541ebcb1d --- /dev/null +++ b/api/envoy/extensions/filters/http/admin/v3/BUILD @@ -0,0 +1,9 @@ +# DO NOT EDIT. This file is generated by tools/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"], +) diff --git a/api/envoy/extensions/filters/http/admin/v3/admin.proto b/api/envoy/extensions/filters/http/admin/v3/admin.proto new file mode 100644 index 000000000000..9666d023880f --- /dev/null +++ b/api/envoy/extensions/filters/http/admin/v3/admin.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package envoy.extensions.filters.http.admin.v3; + +import "google/protobuf/wrappers.proto"; + +import "udpa/annotations/migrate.proto"; +import "udpa/annotations/status.proto"; +import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.filters.http.admin.v3"; +option java_outer_classname = "AdminProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Admin] +// Admin:ref:`configuration overview `. +// [#extension: envoy.filters.http.admin] + +message Admin { +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index 992e9a33342b..851f07075ecd 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -46,6 +46,7 @@ proto_library( "//envoy/extensions/common/tap/v3:pkg", "//envoy/extensions/filters/common/fault/v3:pkg", "//envoy/extensions/filters/http/adaptive_concurrency/v3:pkg", + "//envoy/extensions/filters/http/admin/v3:pkg", "//envoy/extensions/filters/http/aws_lambda/v3:pkg", "//envoy/extensions/filters/http/aws_request_signing/v3:pkg", "//envoy/extensions/filters/http/buffer/v3:pkg", diff --git a/generated_api_shadow/envoy/config/bootstrap/v3/bootstrap.proto b/generated_api_shadow/envoy/config/bootstrap/v3/bootstrap.proto index 994af34c7ac2..d0f1610d180e 100644 --- a/generated_api_shadow/envoy/config/bootstrap/v3/bootstrap.proto +++ b/generated_api_shadow/envoy/config/bootstrap/v3/bootstrap.proto @@ -182,6 +182,7 @@ message Bootstrap { // Administration interface :ref:`operations documentation // `. +// [#next-free-field: 6] message Admin { option (udpa.annotations.versioning).previous_message_type = "envoy.config.bootstrap.v2.Admin"; @@ -201,6 +202,9 @@ message Admin { // Additional socket options that may not be present in Envoy source code or // precompiled binaries. repeated core.v3.SocketOption socket_options = 4; + + // Static :ref:`Listener `. + listener.v3.Listener listener = 5; } // Cluster manager :ref:`architecture overview `. diff --git a/generated_api_shadow/envoy/config/bootstrap/v4alpha/bootstrap.proto b/generated_api_shadow/envoy/config/bootstrap/v4alpha/bootstrap.proto index cd05d6f4e46d..79f8f6d8a590 100644 --- a/generated_api_shadow/envoy/config/bootstrap/v4alpha/bootstrap.proto +++ b/generated_api_shadow/envoy/config/bootstrap/v4alpha/bootstrap.proto @@ -181,6 +181,7 @@ message Bootstrap { // Administration interface :ref:`operations documentation // `. +// [#next-free-field: 6] message Admin { option (udpa.annotations.versioning).previous_message_type = "envoy.config.bootstrap.v3.Admin"; @@ -200,6 +201,9 @@ message Admin { // Additional socket options that may not be present in Envoy source code or // precompiled binaries. repeated core.v4alpha.SocketOption socket_options = 4; + + // Static :ref:`Listener `. + listener.v4alpha.Listener listener = 5; } // Cluster manager :ref:`architecture overview `. diff --git a/generated_api_shadow/envoy/extensions/filters/http/admin/v3/BUILD b/generated_api_shadow/envoy/extensions/filters/http/admin/v3/BUILD new file mode 100644 index 000000000000..ef3541ebcb1d --- /dev/null +++ b/generated_api_shadow/envoy/extensions/filters/http/admin/v3/BUILD @@ -0,0 +1,9 @@ +# DO NOT EDIT. This file is generated by tools/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"], +) diff --git a/generated_api_shadow/envoy/extensions/filters/http/admin/v3/admin.proto b/generated_api_shadow/envoy/extensions/filters/http/admin/v3/admin.proto new file mode 100644 index 000000000000..9666d023880f --- /dev/null +++ b/generated_api_shadow/envoy/extensions/filters/http/admin/v3/admin.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package envoy.extensions.filters.http.admin.v3; + +import "google/protobuf/wrappers.proto"; + +import "udpa/annotations/migrate.proto"; +import "udpa/annotations/status.proto"; +import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.filters.http.admin.v3"; +option java_outer_classname = "AdminProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Admin] +// Admin:ref:`configuration overview `. +// [#extension: envoy.filters.http.admin] + +message Admin { +} diff --git a/source/extensions/filters/http/well_known_names.h b/source/extensions/filters/http/well_known_names.h index 68bc5c361be4..2c49c7af7538 100644 --- a/source/extensions/filters/http/well_known_names.h +++ b/source/extensions/filters/http/well_known_names.h @@ -12,6 +12,8 @@ namespace HttpFilters { */ class HttpFilterNameValues { public: + // Admin filter + const std::string Admin = "envoy.filters.http.admin"; // Buffer filter const std::string Buffer = "envoy.filters.http.buffer"; // Cache filter diff --git a/source/server/http/BUILD b/source/server/http/BUILD index 2e4d47c4c694..95493a5062a7 100644 --- a/source/server/http/BUILD +++ b/source/server/http/BUILD @@ -24,6 +24,7 @@ envoy_cc_library( "//include/envoy/http:request_id_extension_interface", "//include/envoy/network:filter_interface", "//include/envoy/network:listen_socket_interface", + "//include/envoy/registry", "//include/envoy/server:admin_interface", "//include/envoy/server:hot_restart_interface", "//include/envoy/server:instance_interface", @@ -63,9 +64,12 @@ envoy_cc_library( "//source/common/stats:isolated_store_lib", "//source/common/upstream:host_utility_lib", "//source/extensions/access_loggers/file:file_access_log_lib", + "//source/extensions/filters/http:well_known_names", + "//source/extensions/filters/http/common:factory_base_lib", "@envoy_api//envoy/admin/v3:pkg_cc_proto", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/config/route/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/filters/http/admin/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg_cc_proto", ], ) diff --git a/source/server/http/admin.cc b/source/server/http/admin.cc index d2a0bd87c317..ab8dacbbc076 100644 --- a/source/server/http/admin.cc +++ b/source/server/http/admin.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,19 @@ namespace Envoy { namespace Server { +Http::FilterFactoryCb AdminFilterConfig::createFilterFactoryFromProtoTyped( + const envoy::extensions::filters::http::admin::v3::Admin&, const std::string&, + Server::Configuration::FactoryContext& context) { + + return [&context](Http::FilterChainFactoryCallbacks& callbacks) -> void { + // TODO: figure out how to handle this without downcasting + callbacks.addStreamDecoderFilter(std::make_shared( + dynamic_cast(context.admin()).createCallbackFunction())); + }; +} + +REGISTER_FACTORY(AdminFilterConfig, Server::Configuration::NamedHttpFilterConfigFactory); + namespace { /** diff --git a/source/server/http/admin.h b/source/server/http/admin.h index 15946837b3ff..73fd34c19487 100644 --- a/source/server/http/admin.h +++ b/source/server/http/admin.h @@ -36,6 +36,11 @@ #include "common/router/scoped_config_impl.h" #include "common/stats/isolated_store_impl.h" +#include "extensions/filters/http/common/factory_base.h" +#include "extensions/filters/http/well_known_names.h" +#include "envoy/extensions/filters/http/admin/v3/admin.pb.h" +#include "envoy/extensions/filters/http/admin/v3/admin.pb.validate.h" + #include "server/http/admin_filter.h" #include "server/http/config_tracker_impl.h" #include "server/http/listeners_handler.h" @@ -49,6 +54,22 @@ namespace Envoy { namespace Server { +/** + * Config registration for the Admin filter. @see NamedHttpFilterConfigFactory. + */ +class AdminFilterConfig : public Extensions::HttpFilters::Common::FactoryBase< + envoy::extensions::filters::http::admin::v3::Admin> { +public: + AdminFilterConfig() : FactoryBase(Extensions::HttpFilters::HttpFilterNames::get().Admin) {} + +private: + Http::FilterFactoryCb createFilterFactoryFromProtoTyped( + const envoy::extensions::filters::http::admin::v3::Admin& proto_config, const std::string&, + Server::Configuration::FactoryContext& context) override; + + bool isTerminalFilter() override { return true; } +}; + class AdminInternalAddressConfig : public Http::InternalAddressConfig { bool isInternalAddress(const Network::Address::Instance&) const override { return false; } }; diff --git a/source/server/server.cc b/source/server/server.cc index 02de2aa305d2..575852e3abff 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -370,7 +370,9 @@ void InstanceImpl::initialize(const Options& options, // Learn original_start_time_ if our parent is still around to inform us of it. restarter_.sendParentAdminShutdownRequest(original_start_time_); admin_ = std::make_unique(initial_config.admin().profilePath(), *this); - if (initial_config.admin().address()) { + if (bootstrap_.admin().has_listener()) { + // this case is handled later on. + } else if (initial_config.admin().address()) { if (initial_config.admin().accessLogPath().empty()) { throw EnvoyException("An admin access log path is required for a listening server."); } @@ -455,6 +457,9 @@ void InstanceImpl::initialize(const Options& options, // cluster_manager_factory_ is available. config_.initialize(bootstrap_, *this, *cluster_manager_factory_); + // TODO: where should this go? + listener_manager_->addOrUpdateListener(bootstrap_.admin().listener(), "", false); + // Instruct the listener manager to create the LDS provider if needed. This must be done later // because various items do not yet exist when the listener manager is created. if (bootstrap_.dynamic_resources().has_lds_config()) {