Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: adding a multi-envoy test #20016

Merged
merged 9 commits into from
Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 1 addition & 3 deletions source/common/quic/active_quic_listener.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ ActiveQuicListener::ActiveQuicListener(
ASSERT(GetQuicReloadableFlag(quic_single_ack_in_packet2));
ASSERT(!GetQuicFlag(FLAGS_quic_header_size_limit_includes_overhead));

if (Runtime::LoaderSingleton::getExisting()) {
enabled_.emplace(Runtime::FeatureFlag(enabled, runtime));
}
enabled_.emplace(Runtime::FeatureFlag(enabled, runtime));

quic::QuicRandom* const random = quic::QuicRandom::GetInstance();
random->RandBytes(random_seed_, sizeof(random_seed_));
Expand Down
3 changes: 3 additions & 0 deletions source/common/runtime/runtime_features.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ FALSE_RUNTIME_GUARD(envoy_reloadable_features_test_feature_false);
FALSE_RUNTIME_GUARD(envoy_reloadable_features_allow_multiple_dns_addresses);
// TODO(adisuissa) reset to true to enable unified mux by default
FALSE_RUNTIME_GUARD(envoy_reloadable_features_unified_mux);
// TODO(alyssar) flip false once issue complete.
FALSE_RUNTIME_GUARD(envoy_restart_features_no_runtime_singleton);

// Block of non-boolean flags. These are deprecated. Do not add more.
ABSL_FLAG(uint64_t, envoy_buffer_overflow_multiplier, 0, ""); // NOLINT
Expand Down Expand Up @@ -169,6 +171,7 @@ constexpr absl::Flag<bool>* runtime_features[] = {
&FLAGS_envoy_reloadable_features_validate_connect,
&FLAGS_envoy_restart_features_explicit_wildcard_resource,
&FLAGS_envoy_restart_features_use_apple_api_for_dns_lookups,
&FLAGS_envoy_restart_features_no_runtime_singleton,
};
// clang-format on

Expand Down
10 changes: 4 additions & 6 deletions source/common/signal/fatal_error_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,10 @@ void registerFatalActions(FatalAction::FatalActionPtrList safe_actions,
FatalAction::FatalActionPtrList unsafe_actions,
Thread::ThreadFactory& thread_factory) {
// Create a FatalActionManager and store it.
FatalAction::FatalActionManager* previous_manager =
fatal_action_manager.exchange(new FatalAction::FatalActionManager(
std::move(safe_actions), std::move(unsafe_actions), thread_factory));

// Previous manager should be NULL.
ASSERT(!previous_manager);
if (!fatal_action_manager) {
fatal_action_manager.exchange(new FatalAction::FatalActionManager(
std::move(safe_actions), std::move(unsafe_actions), thread_factory));
}
}

FatalAction::Status runSafeActions() { return runFatalActions(FatalActionType::Safe); }
Expand Down
2 changes: 2 additions & 0 deletions source/common/singleton/threadsafe_singleton.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ template <class T> class ScopedInjectableLoader {
}
~ScopedInjectableLoader() { InjectableSingleton<T>::clear(); }

T& instance() { return *instance_; }

private:
std::unique_ptr<T> instance_;
};
Expand Down
2 changes: 1 addition & 1 deletion source/server/config_validation/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class ValidationInstance final : Logger::Loggable<Logger::Id::main>,
ServerLifecycleNotifier& lifecycleNotifier() override { return *this; }
ListenerManager& listenerManager() override { return *listener_manager_; }
Secret::SecretManager& secretManager() override { return *secret_manager_; }
Runtime::Loader& runtime() override { return Runtime::LoaderSingleton::get(); }
Runtime::Loader& runtime() override { return runtime_singleton_->instance(); }
Copy link
Contributor

Choose a reason for hiding this comment

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

I would have expected this to delegate to InstanceImpl::runtime(). But does that not work because ValidationInstance does not extend InstanceImpl?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

exactly. arguably I should do the same restart flag checks here, but I'lll get there in the PR I flip the runtime guard true by default.

void shutdown() override;
bool isShutdown() override { return false; }
void shutdownAdmin() override {}
Expand Down
31 changes: 20 additions & 11 deletions source/server/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,12 @@ void InstanceImpl::initialize(Network::Address::InstanceConstSharedPtr local_add

// Runtime gets initialized before the main configuration since during main configuration
// load things may grab a reference to the loader for later use.
runtime_singleton_ = std::make_unique<Runtime::ScopedLoaderSingleton>(
component_factory.createRuntime(*this, initial_config));
Runtime::LoaderPtr runtime_ptr = component_factory.createRuntime(*this, initial_config);
if (runtime_ptr->snapshot().getBoolean("envoy.restart_features.no_runtime_singleton", false)) {
runtime_ = std::move(runtime_ptr);
} else {
runtime_singleton_ = std::make_unique<Runtime::ScopedLoaderSingleton>(std::move(runtime_ptr));
}
initial_config.initAdminAccessLog(bootstrap_, *this);
validation_context_.setRuntime(runtime());

Expand Down Expand Up @@ -648,10 +652,10 @@ void InstanceImpl::initialize(Network::Address::InstanceConstSharedPtr local_add
dns_resolver_factory.createDnsResolver(dispatcher(), api(), typed_dns_resolver_config);

cluster_manager_factory_ = std::make_unique<Upstream::ProdClusterManagerFactory>(
*admin_, Runtime::LoaderSingleton::get(), stats_store_, thread_local_, dns_resolver_,
*ssl_context_manager_, *dispatcher_, *local_info_, *secret_manager_,
messageValidationContext(), *api_, http_context_, grpc_context_, router_context_,
access_log_manager_, *singleton_manager_, options_, quic_stat_names_);
*admin_, runtime(), stats_store_, thread_local_, dns_resolver_, *ssl_context_manager_,
*dispatcher_, *local_info_, *secret_manager_, messageValidationContext(), *api_,
http_context_, grpc_context_, router_context_, access_log_manager_, *singleton_manager_,
options_, quic_stat_names_);

// Now the configuration gets parsed. The configuration may start setting
// thread local data per above. See MainImpl::initialize() for why ConfigImpl
Expand All @@ -675,7 +679,7 @@ void InstanceImpl::initialize(Network::Address::InstanceConstSharedPtr local_add

// We have to defer RTDS initialization until after the cluster manager is
// instantiated (which in turn relies on runtime...).
Runtime::LoaderSingleton::get().initialize(clusterManager());
runtime().initialize(clusterManager());

clusterManager().setPrimaryClustersInitializedCb(
[this]() { onClusterManagerPrimaryInitializationComplete(); });
Expand Down Expand Up @@ -706,7 +710,7 @@ void InstanceImpl::initialize(Network::Address::InstanceConstSharedPtr local_add

void InstanceImpl::onClusterManagerPrimaryInitializationComplete() {
// If RTDS was not configured the `onRuntimeReady` callback is immediately invoked.
Runtime::LoaderSingleton::get().startRtdsSubscriptions([this]() { onRuntimeReady(); });
runtime().startRtdsSubscriptions([this]() { onRuntimeReady(); });
}

void InstanceImpl::onRuntimeReady() {
Expand All @@ -730,8 +734,8 @@ void InstanceImpl::onRuntimeReady() {
Config::Utility::factoryForGrpcApiConfigSource(*async_client_manager_, hds_config,
stats_store_, false)
->createUncachedRawAsyncClient(),
*dispatcher_, Runtime::LoaderSingleton::get(), stats_store_, *ssl_context_manager_,
info_factory_, access_log_manager_, *config_.clusterManager(), *local_info_, *admin_,
*dispatcher_, runtime(), stats_store_, *ssl_context_manager_, info_factory_,
access_log_manager_, *config_.clusterManager(), *local_info_, *admin_,
*singleton_manager_, thread_local_, messageValidationContext().dynamicValidationVisitor(),
*api_, options_);
}
Expand Down Expand Up @@ -931,7 +935,12 @@ void InstanceImpl::terminate() {
FatalErrorHandler::clearFatalActionsOnTerminate();
}

Runtime::Loader& InstanceImpl::runtime() { return Runtime::LoaderSingleton::get(); }
Runtime::Loader& InstanceImpl::runtime() {
if (runtime_singleton_) {
return runtime_singleton_->instance();
}
return *runtime_;
}

void InstanceImpl::shutdown() {
ENVOY_LOG(info, "shutting down server instance");
Expand Down
1 change: 1 addition & 0 deletions source/server/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ class InstanceImpl final : Logger::Loggable<Logger::Id::main>,
Singleton::ManagerPtr singleton_manager_;
Network::ConnectionHandlerPtr handler_;
std::unique_ptr<Runtime::ScopedLoaderSingleton> runtime_singleton_;
std::unique_ptr<Runtime::Loader> runtime_;
std::unique_ptr<Ssl::ContextManager> ssl_context_manager_;
ProdListenerComponentFactory listener_component_factory_;
ProdWorkerFactory worker_factory_;
Expand Down
7 changes: 0 additions & 7 deletions test/common/signal/fatal_action_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,6 @@ TEST_F(FatalActionTest, ShouldNotBeAbleToRunActionsBeforeRegistration) {
EXPECT_EQ(FatalErrorHandler::runUnsafeActions(), Status::ActionManagerUnset);
}

TEST_F(FatalActionTest, ShouldOnlyBeAbleToRegisterFatalActionsOnce) {
// Register empty list of actions
FatalErrorHandler::registerFatalActions({}, {}, Thread::threadFactoryForTest());
EXPECT_DEBUG_DEATH(
{ FatalErrorHandler::registerFatalActions({}, {}, Thread::threadFactoryForTest()); }, "");
}

TEST_F(FatalActionTest, CanCallRegisteredActions) {
// Set up Fatal Actions
safe_actions_.emplace_back(std::make_unique<TestFatalAction>(true, &counter_));
Expand Down
10 changes: 10 additions & 0 deletions test/integration/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,16 @@ envoy_cc_test(
],
)

envoy_cc_test(
name = "multi_envoy_test",
srcs = [
"multi_envoy_test.cc",
],
deps = [
":http_protocol_integration_lib",
],
)

envoy_cc_test(
name = "multiplexed_upstream_integration_test",
srcs = [
Expand Down
67 changes: 41 additions & 26 deletions test/integration/base_integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -157,19 +157,14 @@ void BaseIntegrationTest::createUpstreams() {
}
}

void BaseIntegrationTest::createEnvoy() {
std::vector<uint32_t> ports;
for (auto& upstream : fake_upstreams_) {
if (upstream->localAddress()->ip()) {
ports.push_back(upstream->localAddress()->ip()->port());
}
}

if (use_lds_) {
std::string BaseIntegrationTest::finalizeConfigWithPorts(ConfigHelper& config_helper,
std::vector<uint32_t>& ports,
bool use_lds) {
if (use_lds) {
ENVOY_LOG_MISC(debug, "Setting up file-based LDS");
// Before finalization, set up a real lds path, replacing the default /dev/null
std::string lds_path = TestEnvironment::temporaryPath(TestUtility::uniqueFilename());
config_helper_.addConfigModifier(
config_helper.addConfigModifier(
[lds_path](envoy::config::bootstrap::v3::Bootstrap& bootstrap) -> void {
bootstrap.mutable_dynamic_resources()->mutable_lds_config()->set_resource_api_version(
envoy::config::core::v3::V3);
Expand All @@ -183,16 +178,16 @@ void BaseIntegrationTest::createEnvoy() {
// Note that finalize assumes that every fake_upstream_ must correspond to a bootstrap config
// static entry. So, if you want to manually create a fake upstream without specifying it in the
// config, you will need to do so *after* initialize() (which calls this function) is done.
config_helper_.finalize(ports);
config_helper.finalize(ports);

envoy::config::bootstrap::v3::Bootstrap bootstrap = config_helper_.bootstrap();
if (use_lds_) {
envoy::config::bootstrap::v3::Bootstrap bootstrap = config_helper.bootstrap();
if (use_lds) {
// After the config has been finalized, write the final listener config to the lds file.
const std::string lds_path =
config_helper_.bootstrap().dynamic_resources().lds_config().path_config_source().path();
config_helper.bootstrap().dynamic_resources().lds_config().path_config_source().path();
envoy::service::discovery::v3::DiscoveryResponse lds;
lds.set_version_info("0");
for (auto& listener : config_helper_.bootstrap().static_resources().listeners()) {
for (auto& listener : config_helper.bootstrap().static_resources().listeners()) {
ProtobufWkt::Any* resource = lds.add_resources();
resource->PackFrom(listener);
}
Expand All @@ -208,6 +203,18 @@ void BaseIntegrationTest::createEnvoy() {

const std::string bootstrap_path = TestEnvironment::writeStringToFileForTest(
"bootstrap.pb", TestUtility::getProtobufBinaryStringFromMessage(bootstrap));
return bootstrap_path;
}

void BaseIntegrationTest::createEnvoy() {
std::vector<uint32_t> ports;
for (auto& upstream : fake_upstreams_) {
if (upstream->localAddress()->ip()) {
ports.push_back(upstream->localAddress()->ip()->port());
}
}

const std::string bootstrap_path = finalizeConfigWithPorts(config_helper_, ports, use_lds_);

std::vector<std::string> named_ports;
const auto& static_resources = config_helper_.bootstrap().static_resources();
Expand Down Expand Up @@ -295,12 +302,13 @@ void BaseIntegrationTest::setUpstreamAddress(
socket_address->set_port_value(fake_upstreams_[upstream_index]->localAddress()->ip()->port());
}

void BaseIntegrationTest::registerTestServerPorts(const std::vector<std::string>& port_names) {
void BaseIntegrationTest::registerTestServerPorts(const std::vector<std::string>& port_names,
IntegrationTestServerPtr& test_server) {
bool listeners_ready = false;
absl::Mutex l;
std::vector<std::reference_wrapper<Network::ListenerConfig>> listeners;
test_server_->server().dispatcher().post([this, &listeners, &listeners_ready, &l]() {
listeners = test_server_->server().listenerManager().listeners();
test_server->server().dispatcher().post([&listeners, &listeners_ready, &l, &test_server]() {
listeners = test_server->server().listenerManager().listeners();
l.Lock();
listeners_ready = true;
l.Unlock();
Expand All @@ -318,7 +326,7 @@ void BaseIntegrationTest::registerTestServerPorts(const std::vector<std::string>
}
}
const auto admin_addr =
test_server_->server().admin().socket().connectionInfoProvider().localAddress();
test_server->server().admin().socket().connectionInfoProvider().localAddress();
if (admin_addr->type() == Network::Address::Type::Ip) {
registerPort("admin", admin_addr->ip()->port());
}
Expand All @@ -334,8 +342,15 @@ std::string getListenerDetails(Envoy::Server::Instance& server) {
void BaseIntegrationTest::createGeneratedApiTestServer(
const std::string& bootstrap_path, const std::vector<std::string>& port_names,
Server::FieldValidationConfig validator_config, bool allow_lds_rejection) {
createGeneratedApiTestServer(bootstrap_path, port_names, validator_config, allow_lds_rejection,
test_server_);
}

test_server_ = IntegrationTestServer::create(
void BaseIntegrationTest::createGeneratedApiTestServer(
const std::string& bootstrap_path, const std::vector<std::string>& port_names,
Server::FieldValidationConfig validator_config, bool allow_lds_rejection,
IntegrationTestServerPtr& test_server) {
test_server = IntegrationTestServer::create(
bootstrap_path, version_, on_server_ready_function_, on_server_init_function_,
deterministic_value_, timeSystem(), *api_, defer_listener_finalization_, process_object_,
validator_config, concurrency_, drain_time_, drain_strategy_, proxy_buffer_factory_,
Expand All @@ -350,27 +365,27 @@ void BaseIntegrationTest::createGeneratedApiTestServer(
Event::TestTimeSystem::RealTimeBound bound(2 * TestUtility::DefaultTimeout);
const char* success = "listener_manager.listener_create_success";
const char* rejected = "listener_manager.lds.update_rejected";
for (Stats::CounterSharedPtr success_counter = test_server_->counter(success),
rejected_counter = test_server_->counter(rejected);
for (Stats::CounterSharedPtr success_counter = test_server->counter(success),
rejected_counter = test_server->counter(rejected);
(success_counter == nullptr ||
success_counter->value() <
concurrency_ * config_helper_.bootstrap().static_resources().listeners_size()) &&
(!allow_lds_rejection || rejected_counter == nullptr || rejected_counter->value() == 0);
success_counter = test_server_->counter(success),
rejected_counter = test_server_->counter(rejected)) {
success_counter = test_server->counter(success),
rejected_counter = test_server->counter(rejected)) {
if (!bound.withinBound()) {
RELEASE_ASSERT(0, "Timed out waiting for listeners.");
}
if (!allow_lds_rejection) {
RELEASE_ASSERT(rejected_counter == nullptr || rejected_counter->value() == 0,
absl::StrCat("Lds update failed. Details\n",
getListenerDetails(test_server_->server())));
getListenerDetails(test_server->server())));
}
// TODO(mattklein123): Switch to events and waitFor().
time_system_.realSleepDoNotUseWithoutScrutiny(std::chrono::milliseconds(10));
}

registerTestServerPorts(port_names);
registerTestServerPorts(port_names, test_server);
}
}

Expand Down
15 changes: 14 additions & 1 deletion test/integration/base_integration_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ class BaseIntegrationTest : protected Logger::Loggable<Logger::Id::testing> {
makeClientConnectionWithOptions(uint32_t port,
const Network::ConnectionSocket::OptionsSharedPtr& options);

void registerTestServerPorts(const std::vector<std::string>& port_names);
void registerTestServerPorts(const std::vector<std::string>& port_names) {
registerTestServerPorts(port_names, test_server_);
}
void registerTestServerPorts(const std::vector<std::string>& port_names,
IntegrationTestServerPtr& test_server);
void createGeneratedApiTestServer(const std::string& bootstrap_path,
const std::vector<std::string>& port_names,
Server::FieldValidationConfig validator_config,
Expand All @@ -104,6 +108,12 @@ class BaseIntegrationTest : protected Logger::Loggable<Logger::Id::testing> {
Server::FieldValidationConfig validator_config,
bool allow_lds_rejection);

void createGeneratedApiTestServer(const std::string& bootstrap_path,
const std::vector<std::string>& port_names,
Server::FieldValidationConfig validator_config,
bool allow_lds_rejection,
IntegrationTestServerPtr& test_server);

Event::TestTimeSystem& timeSystem() { return time_system_; }

Stats::IsolatedStoreImpl stats_store_;
Expand Down Expand Up @@ -333,6 +343,9 @@ class BaseIntegrationTest : protected Logger::Loggable<Logger::Id::testing> {
}

protected:
static std::string finalizeConfigWithPorts(ConfigHelper& helper, std::vector<uint32_t>& ports,
bool use_lds);

void setUdpFakeUpstream(absl::optional<FakeUpstreamConfig::UdpConfig> config) {
upstream_config_.udp_fake_upstream_ = config;
}
Expand Down
2 changes: 1 addition & 1 deletion test/integration/http_integration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ void HttpIntegrationTest::initialize() {
config_helper_.addQuicDownstreamTransportSocketConfig();

BaseIntegrationTest::initialize();
registerTestServerPorts({"http"});
registerTestServerPorts({"http"}, test_server_);

// Needs to outlive all QUIC connections.
auto quic_connection_persistent_info =
Expand Down
Loading