Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
6 changes: 6 additions & 0 deletions include/envoy/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ envoy_cc_library(
deps = [
":admin_interface",
":lifecycle_notifier_interface",
":process_context_interface",
"//include/envoy/access_log:access_log_interface",
"//include/envoy/api:api_interface",
"//include/envoy/http:codes_interface",
Expand Down Expand Up @@ -192,6 +193,11 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "process_context_interface",
hdrs = ["process_context.h"],
)

envoy_cc_library(
name = "transport_socket_config_interface",
hdrs = ["transport_socket_config.h"],
Expand Down
6 changes: 6 additions & 0 deletions include/envoy/server/filter_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "envoy/server/admin.h"
#include "envoy/server/lifecycle_notifier.h"
#include "envoy/server/overload_manager.h"
#include "envoy/server/process_context.h"
#include "envoy/singleton/manager.h"
#include "envoy/stats/scope.h"
#include "envoy/thread_local/thread_local.h"
Expand Down Expand Up @@ -147,6 +148,11 @@ class FactoryContext {
*/
virtual Http::Context& httpContext() PURE;

/**
* @return ProcessContext& a reference to the process context.
*/
virtual ProcessContext& processContext() PURE;

/**
* @return Api::Api& a reference to the api object.
*/
Expand Down
5 changes: 5 additions & 0 deletions include/envoy/server/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ class Instance {
*/
virtual Http::Context& httpContext() PURE;

/**
* @return the server-wide process context.
*/
virtual ProcessContext& processContext() PURE;

/**
* @return ThreadLocal::Instance& the thread local storage engine for the server. This is used to
* allow runtime lockless updates to configuration, etc. across multiple threads.
Expand Down
29 changes: 29 additions & 0 deletions include/envoy/server/process_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include "envoy/common/pure.h"

namespace Envoy {

/**
* Represents some other part of the process.
*/
class ProcessObject {
public:
virtual ~ProcessObject() {}
};

/**
* Context passed to filters to access resources from non-Envoy parts of the
* process.
*/
class ProcessContext {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we're only ever going to support get(), I guess it might be possible to eliminate ProcessObject and just pass in a subclass of ProcessContext with the bits you are after. That said, I think it's good to have this indirection as we can grow it over time.

One consideration I'm interested in your thoughts on. Let's say we have two filters and they want to get at different aspects of the state. Would it make sense to have a map from a string to the ProcessObjects, or have them aware of the internals of ProcessObject to do this? I'm thinking the former would make sense when you have multiple parties trying to collaborate on ProcessObject, the latter when it's single party.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I had envisioned a map from string to ProcessObjects inside ProcessContext at some point, and then get() would do the lookup by that name. I didn't implement it here because we don't need it for our use case, and I wasn't sure if other folks would. I certainly could if we want to go with that design from the beginning, though.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it's fine as is, the thing to be aware of then is in the future we might see an API breaking change. Let's ship and iterate.

public:
virtual ~ProcessContext() {}

/**
* @return the ProcessObject for this context.
*/
virtual const ProcessObject* get() const PURE;
};

} // namespace Envoy
7 changes: 4 additions & 3 deletions source/exe/main_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ MainCommonBase::MainCommonBase(const OptionsImpl& options, Event::TimeSystem& ti
Server::ComponentFactory& component_factory,
std::unique_ptr<Runtime::RandomGenerator>&& random_generator,
Thread::ThreadFactory& thread_factory,
Filesystem::Instance& file_system)
Filesystem::Instance& file_system,
std::unique_ptr<ProcessContext> process_context)
: options_(options), component_factory_(component_factory), thread_factory_(thread_factory),
file_system_(file_system), stats_allocator_(symbol_table_) {
switch (options_.mode()) {
Expand Down Expand Up @@ -75,7 +76,7 @@ MainCommonBase::MainCommonBase(const OptionsImpl& options, Event::TimeSystem& ti
server_ = std::make_unique<Server::InstanceImpl>(
options_, time_system, local_address, listener_hooks, *restarter_, *stats_store_,
access_log_lock, component_factory, std::move(random_generator), *tls_, thread_factory_,
file_system_);
file_system_, std::move(process_context));

break;
}
Expand Down Expand Up @@ -128,7 +129,7 @@ MainCommon::MainCommon(int argc, const char* const* argv)
: options_(argc, argv, &MainCommon::hotRestartVersion, spdlog::level::info),
base_(options_, real_time_system_, default_listener_hooks_, prod_component_factory_,
std::make_unique<Runtime::RandomGeneratorImpl>(), platform_impl_.threadFactory(),
platform_impl_.fileSystem()) {}
platform_impl_.fileSystem(), nullptr) {}

std::string MainCommon::hotRestartVersion(bool hot_restart_enabled) {
#ifdef ENVOY_HOT_RESTART
Expand Down
3 changes: 2 additions & 1 deletion source/exe/main_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class MainCommonBase {
MainCommonBase(const OptionsImpl& options, Event::TimeSystem& time_system,
ListenerHooks& listener_hooks, Server::ComponentFactory& component_factory,
std::unique_ptr<Runtime::RandomGenerator>&& random_generator,
Thread::ThreadFactory& thread_factory, Filesystem::Instance& file_system);
Thread::ThreadFactory& thread_factory, Filesystem::Instance& file_system,
std::unique_ptr<ProcessContext> process_context);

bool run();

Expand Down
7 changes: 7 additions & 0 deletions source/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "process_context_lib",
hdrs = ["process_context_impl.h"],
deps = ["//include/envoy/server:process_context_interface"],
)

envoy_cc_library(
name = "proto_descriptors_lib",
srcs = ["proto_descriptors.cc"],
Expand Down Expand Up @@ -325,6 +331,7 @@ envoy_cc_library(
"//include/envoy/server:instance_interface",
"//include/envoy/server:listener_manager_interface",
"//include/envoy/server:options_interface",
"//include/envoy/server:process_context_interface",
"//include/envoy/stats:stats_macros",
"//include/envoy/tracing:http_tracer_interface",
"//include/envoy/upstream:cluster_manager_interface",
Expand Down
1 change: 1 addition & 0 deletions source/server/config_validation/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class ValidationInstance : Logger::Loggable<Logger::Id::main>,
time_t startTimeFirstEpoch() override { NOT_IMPLEMENTED_GCOVR_EXCL_LINE; }
Stats::Store& stats() override { return stats_store_; }
Http::Context& httpContext() override { return http_context_; }
ProcessContext& processContext() override { NOT_IMPLEMENTED_GCOVR_EXCL_LINE; }
ThreadLocal::Instance& threadLocal() override { return thread_local_; }
const LocalInfo::LocalInfo& localInfo() override { return *local_info_; }
TimeSource& timeSource() override { return api_->timeSource(); }
Expand Down
1 change: 1 addition & 0 deletions source/server/listener_manager_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ class ListenerImpl : public Network::ListenerConfig,
ServerLifecycleNotifier& lifecycleNotifier() override {
return parent_.server_.lifecycleNotifier();
}
ProcessContext& processContext() override { return parent_.server_.processContext(); }

// Network::DrainDecision
bool drainClose() const override;
Expand Down
17 changes: 17 additions & 0 deletions source/server/process_context_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include "envoy/server/process_context.h"

namespace Envoy {

class ProcessContextImpl : public ProcessContext {
public:
ProcessContextImpl(ProcessObject* process_object) : process_object_(process_object) {}
Comment thread
ahedberg marked this conversation as resolved.
Outdated
// ProcessContext
const ProcessObject* get() const override { return process_object_; }

private:
const ProcessObject* process_object_;
};

} // namespace Envoy
5 changes: 3 additions & 2 deletions source/server/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ InstanceImpl::InstanceImpl(const Options& options, Event::TimeSystem& time_syste
ComponentFactory& component_factory,
Runtime::RandomGeneratorPtr&& random_generator,
ThreadLocal::Instance& tls, Thread::ThreadFactory& thread_factory,
Filesystem::Instance& file_system)
Filesystem::Instance& file_system,
std::unique_ptr<ProcessContext> process_context)
: secret_manager_(std::make_unique<Secret::SecretManagerImpl>()), shutdown_(false),
options_(options), time_source_(time_system), restarter_(restarter),
start_time_(time(nullptr)), original_start_time_(start_time_), stats_store_(store),
Expand All @@ -70,7 +71,7 @@ InstanceImpl::InstanceImpl(const Options& options, Event::TimeSystem& time_syste
terminated_(false),
mutex_tracer_(options.mutexTracingEnabled() ? &Envoy::MutexTracerImpl::getOrCreateTracer()
: nullptr),
main_thread_id_(std::this_thread::get_id()) {
process_context_(std::move(process_context)), main_thread_id_(std::this_thread::get_id()) {
try {
if (!options.logPath().empty()) {
try {
Expand Down
6 changes: 5 additions & 1 deletion source/server/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "envoy/server/drain_manager.h"
#include "envoy/server/guarddog.h"
#include "envoy/server/instance.h"
#include "envoy/server/process_context.h"
#include "envoy/server/tracer_config.h"
#include "envoy/ssl/context_manager.h"
#include "envoy/stats/stats_macros.h"
Expand Down Expand Up @@ -149,7 +150,8 @@ class InstanceImpl : Logger::Loggable<Logger::Id::main>,
HotRestart& restarter, Stats::StoreRoot& store,
Thread::BasicLockable& access_log_lock, ComponentFactory& component_factory,
Runtime::RandomGeneratorPtr&& random_generator, ThreadLocal::Instance& tls,
Thread::ThreadFactory& thread_factory, Filesystem::Instance& file_system);
Thread::ThreadFactory& thread_factory, Filesystem::Instance& file_system,
std::unique_ptr<ProcessContext> process_context);

~InstanceImpl() override;

Expand Down Expand Up @@ -185,6 +187,7 @@ class InstanceImpl : Logger::Loggable<Logger::Id::main>,
time_t startTimeFirstEpoch() override { return original_start_time_; }
Stats::Store& stats() override { return stats_store_; }
Http::Context& httpContext() override { return http_context_; }
ProcessContext& processContext() override { return *process_context_; }
ThreadLocal::Instance& threadLocal() override { return thread_local_; }
const LocalInfo::LocalInfo& localInfo() override { return *local_info_; }
TimeSource& timeSource() override { return time_source_; }
Expand Down Expand Up @@ -258,6 +261,7 @@ class InstanceImpl : Logger::Loggable<Logger::Id::main>,
std::unique_ptr<OverloadManagerImpl> overload_manager_;
Envoy::MutexTracer* mutex_tracer_;
Http::ContextImpl http_context_;
std::unique_ptr<ProcessContext> process_context_;
std::unique_ptr<Memory::HeapShrinker> heap_shrinker_;
const std::thread::id main_thread_id_;
absl::flat_hash_map<Stage, std::vector<StageCallback>> stage_callbacks_;
Expand Down
1 change: 1 addition & 0 deletions test/integration/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ envoy_cc_test_library(
"//source/server:connection_handler_lib",
"//source/server:hot_restart_nop_lib",
"//source/server:listener_hooks_lib",
"//source/server:process_context_lib",
"//source/server:server_lib",
"//test/common/runtime:utility_lib",
"//test/common/upstream:utility_lib",
Expand Down
5 changes: 4 additions & 1 deletion test/integration/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "server/hot_restart_nop_impl.h"
#include "server/options_impl.h"
#include "server/process_context_impl.h"

#include "test/common/runtime/utility.h"
#include "test/integration/integration.h"
Expand Down Expand Up @@ -174,9 +175,11 @@ void IntegrationTestServerImpl::createAndRunEnvoyServer(
Stats::HeapStatDataAllocator stats_allocator(symbol_table);
Stats::ThreadLocalStoreImpl stat_store(stats_allocator);

auto context_for_test = absl::make_unique<ProcessContextImpl>(nullptr);
Server::InstanceImpl server(options, time_system, local_address, hooks, restarter, stat_store,
access_log_lock, component_factory, std::move(random_generator), tls,
Thread::threadFactoryForTest(), Filesystem::fileSystemForTest());
Thread::threadFactoryForTest(), Filesystem::fileSystemForTest(),
std::move(context_for_test));
// This is technically thread unsafe (assigning to a shared_ptr accessed
// across threads), but because we synchronize below through serverReady(), the only
// consumer on the main test thread in ~IntegrationTestServerImpl will not race.
Expand Down
2 changes: 2 additions & 0 deletions test/mocks/server/mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ class MockInstance : public Instance {
MOCK_METHOD0(startTimeFirstEpoch, time_t());
MOCK_METHOD0(stats, Stats::Store&());
MOCK_METHOD0(httpContext, Http::Context&());
MOCK_METHOD0(processContext, ProcessContext&());
MOCK_METHOD0(threadLocal, ThreadLocal::Instance&());
MOCK_METHOD0(localInfo, const LocalInfo::LocalInfo&());
MOCK_CONST_METHOD0(statsFlushInterval, std::chrono::milliseconds());
Expand Down Expand Up @@ -445,6 +446,7 @@ class MockFactoryContext : public virtual FactoryContext {
MOCK_METHOD0(timeSource, TimeSource&());
Event::TestTimeSystem& timeSystem() { return time_system_; }
Http::Context& httpContext() override { return http_context_; }
MOCK_METHOD0(processContext, ProcessContext&());
MOCK_METHOD0(api, Api::Api&());

testing::NiceMock<AccessLog::MockAccessLogManager> access_log_manager_;
Expand Down
3 changes: 2 additions & 1 deletion test/server/server_fuzz_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ DEFINE_PROTO_FUZZER(const envoy::config::bootstrap::v2::Bootstrap& input) {
options, test_time.timeSystem(),
std::make_shared<Network::Address::Ipv4Instance>("127.0.0.1"), hooks, restart, stats_store,
fakelock, component_factory, std::make_unique<Runtime::RandomGeneratorImpl>(),
thread_local_instance, Thread::threadFactoryForTest(), Filesystem::fileSystemForTest());
thread_local_instance, Thread::threadFactoryForTest(), Filesystem::fileSystemForTest(),
nullptr);
} catch (const EnvoyException& ex) {
ENVOY_LOG_MISC(debug, "Controlled EnvoyException exit: {}", ex.what());
return;
Expand Down
40 changes: 37 additions & 3 deletions test/server/server_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "common/network/address_impl.h"
#include "common/thread_local/thread_local_impl.h"

#include "server/process_context_impl.h"
#include "server/server.h"

#include "test/integration/server.h"
Expand Down Expand Up @@ -133,7 +134,7 @@ class ServerInstanceImplTest : public testing::TestWithParam<Network::Address::I
Network::Address::InstanceConstSharedPtr(new Network::Address::Ipv4Instance("127.0.0.1")),
hooks_, restart_, stats_store_, fakelock_, component_factory_,
std::make_unique<NiceMock<Runtime::MockRandomGenerator>>(), *thread_local_,
Thread::threadFactoryForTest(), Filesystem::fileSystemForTest());
Thread::threadFactoryForTest(), Filesystem::fileSystemForTest(), nullptr);

EXPECT_TRUE(server_->api().fileSystem().fileExists("/dev/null"));
}
Expand All @@ -151,7 +152,7 @@ class ServerInstanceImplTest : public testing::TestWithParam<Network::Address::I
Network::Address::InstanceConstSharedPtr(new Network::Address::Ipv4Instance("127.0.0.1")),
hooks_, restart_, stats_store_, fakelock_, component_factory_,
std::make_unique<NiceMock<Runtime::MockRandomGenerator>>(), *thread_local_,
Thread::threadFactoryForTest(), Filesystem::fileSystemForTest());
Thread::threadFactoryForTest(), Filesystem::fileSystemForTest(), nullptr);

EXPECT_TRUE(server_->api().fileSystem().fileExists("/dev/null"));
}
Expand Down Expand Up @@ -404,7 +405,7 @@ TEST_P(ServerInstanceImplTest, NoOptionsPassed) {
Network::Address::InstanceConstSharedPtr(new Network::Address::Ipv4Instance("127.0.0.1")),
hooks_, restart_, stats_store_, fakelock_, component_factory_,
std::make_unique<NiceMock<Runtime::MockRandomGenerator>>(), *thread_local_,
Thread::threadFactoryForTest(), Filesystem::fileSystemForTest())),
Thread::threadFactoryForTest(), Filesystem::fileSystemForTest(), nullptr)),
EnvoyException, "At least one of --config-path and --config-yaml should be non-empty");
}

Expand Down Expand Up @@ -465,6 +466,39 @@ TEST_P(ServerInstanceImplTest, ZipkinHttpTracingEnabled) {
EXPECT_NE(nullptr, dynamic_cast<Tracing::HttpTracerImpl*>(tracer()));
}

class TestObject : public ProcessObject {
public:
TestObject() {}
Comment thread
ahedberg marked this conversation as resolved.
Outdated
void setFlag(bool value) { boolean_flag_ = value; }

bool boolean_flag_ = true;
};

TEST_P(ServerInstanceImplTest, WithProcessContext) {
TestObject object;

options_.config_path_ = TestEnvironment::temporaryFileSubstitute(
"test/server/empty_bootstrap.yaml", {{"upstream_0", 0}, {"upstream_1", 0}}, version_);
thread_local_ = std::make_unique<ThreadLocal::InstanceImpl>();

auto server = std::make_unique<InstanceImpl>(
Comment thread
ahedberg marked this conversation as resolved.
Outdated
options_, test_time_.timeSystem(),
Network::Address::InstanceConstSharedPtr(new Network::Address::Ipv4Instance("127.0.0.1")),
hooks_, restart_, stats_store_, fakelock_, component_factory_,
std::make_unique<NiceMock<Runtime::MockRandomGenerator>>(), *thread_local_,
Thread::threadFactoryForTest(), Filesystem::fileSystemForTest(),
std::make_unique<ProcessContextImpl>(&object));

ProcessContext& context = server->processContext();
const auto* object_from_context = dynamic_cast<const TestObject*>(context.get());
ASSERT_NE(object_from_context, nullptr);
EXPECT_EQ(object_from_context, &object);
EXPECT_TRUE(object_from_context->boolean_flag_);

object.boolean_flag_ = false;
EXPECT_FALSE(object_from_context->boolean_flag_);
}

} // namespace
} // namespace Server
} // namespace Envoy