diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index 6c01ffbc1742e..57fde648b248a 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -1713,7 +1713,17 @@ ProtobufTypes::MessagePtr ClusterManagerImpl::dumpClusterConfigs(const Matchers::StringMatcher& name_matcher) { auto config_dump = std::make_unique(); config_dump->set_version_info(cds_api_ != nullptr ? cds_api_->versionInfo() : ""); - for (const auto& active_cluster_pair : active_clusters_) { + // Sort `active_clusters` before dumping. + using ClusterDataElement = std::pair; + auto de_unique = [](const ClusterMap::value_type& input) { + return ClusterDataElement{input.first, input.second.get()}; + }; + std::vector active_clusters(active_clusters_.size()); + std::transform(active_clusters_.begin(), active_clusters_.end(), active_clusters.begin(), + de_unique); + std::sort(active_clusters.begin(), active_clusters.end()); + + for (const auto& active_cluster_pair : active_clusters) { const auto& cluster = *active_cluster_pair.second; if (!name_matcher.match(cluster.cluster_config_.name())) { continue; @@ -1732,7 +1742,13 @@ ClusterManagerImpl::dumpClusterConfigs(const Matchers::StringMatcher& name_match } } - for (const auto& warming_cluster_pair : warming_clusters_) { + // Sort `warming_clusters` before dumping. + std::vector warming_clusters(warming_clusters_.size()); + std::transform(warming_clusters_.begin(), warming_clusters_.end(), warming_clusters.begin(), + de_unique); + std::sort(warming_clusters.begin(), warming_clusters.end()); + + for (const auto& warming_cluster_pair : warming_clusters) { const auto& cluster = *warming_cluster_pair.second; if (!name_matcher.match(cluster.cluster_config_.name())) { continue; diff --git a/source/common/upstream/cluster_manager_impl.h b/source/common/upstream/cluster_manager_impl.h index 4469b677d021a..d19f3fc5430ae 100644 --- a/source/common/upstream/cluster_manager_impl.h +++ b/source/common/upstream/cluster_manager_impl.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,8 @@ #include "source/common/upstream/priority_conn_pool_map.h" #include "source/common/upstream/upstream_impl.h" +#include "absl/container/flat_hash_map.h" + namespace Envoy { namespace Upstream { @@ -546,7 +547,7 @@ class ClusterManagerImpl : public ClusterManager, struct TcpConnPoolsContainer { TcpConnPoolsContainer(HostHandlePtr&& host_handle) : host_handle_(std::move(host_handle)) {} - using ConnPools = std::map, Tcp::ConnectionPool::InstancePtr>; + using ConnPools = absl::flat_hash_map, Tcp::ConnectionPool::InstancePtr>; // Destroyed after pools. const HostHandlePtr host_handle_; @@ -820,8 +821,7 @@ class ClusterManagerImpl : public ClusterManager, }; using ClusterDataPtr = std::unique_ptr; - // This map is ordered so that config dumping is consistent. - using ClusterMap = std::map; + using ClusterMap = absl::flat_hash_map; struct PendingUpdates { ~PendingUpdates() { disableTimer(); } diff --git a/test/common/upstream/cluster_manager_lifecycle_test.cc b/test/common/upstream/cluster_manager_lifecycle_test.cc index ed02a278c22df..03f06f1da48e4 100644 --- a/test/common/upstream/cluster_manager_lifecycle_test.cc +++ b/test/common/upstream/cluster_manager_lifecycle_test.cc @@ -113,18 +113,22 @@ TEST_P(ClusterManagerLifecycleTest, InitializeOrder) { cluster2->info_->lb_factory_->loadConfig(factory_.server_context_, *proto_message).value(); // This part tests static init. - InSequence s; - EXPECT_CALL(factory_, clusterFromProto_(_, _, _)) - .WillOnce(Return(std::make_pair(cds_cluster, nullptr))); - ON_CALL(*cds_cluster, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Primary)); - EXPECT_CALL(factory_, clusterFromProto_(_, _, _)) - .WillOnce(Return(std::make_pair(cluster1, nullptr))); - ON_CALL(*cluster1, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Primary)); - EXPECT_CALL(factory_, clusterFromProto_(_, _, _)) - .WillOnce(Return(std::make_pair(cluster2, nullptr))); - ON_CALL(*cluster2, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Secondary)); - EXPECT_CALL(factory_, createCds_()).WillOnce(Return(cds)); - EXPECT_CALL(*cds, setInitializedCb(_)); + { + InSequence s; + EXPECT_CALL(factory_, clusterFromProto_(_, _, _)) + .WillOnce(Return(std::make_pair(cds_cluster, nullptr))); + ON_CALL(*cds_cluster, initializePhase()) + .WillByDefault(Return(Cluster::InitializePhase::Primary)); + EXPECT_CALL(factory_, clusterFromProto_(_, _, _)) + .WillOnce(Return(std::make_pair(cluster1, nullptr))); + ON_CALL(*cluster1, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Primary)); + EXPECT_CALL(factory_, clusterFromProto_(_, _, _)) + .WillOnce(Return(std::make_pair(cluster2, nullptr))); + ON_CALL(*cluster2, initializePhase()) + .WillByDefault(Return(Cluster::InitializePhase::Secondary)); + EXPECT_CALL(factory_, createCds_()).WillOnce(Return(cds)); + EXPECT_CALL(*cds, setInitializedCb(_)); + } EXPECT_CALL(*cds_cluster, initialize(_)); EXPECT_CALL(*cluster1, initialize(_));