diff --git a/include/envoy/upstream/cluster_manager.h b/include/envoy/upstream/cluster_manager.h index 6db3be950d64..23d7736e1ee1 100644 --- a/include/envoy/upstream/cluster_manager.h +++ b/include/envoy/upstream/cluster_manager.h @@ -126,6 +126,14 @@ class ClusterManager { * @return GrpcMux& ADS API provider referencee. */ virtual Config::GrpcMux& adsMux() PURE; + + /** + * Return the current version info string for dynamic clusters, if CDS is setup. + * + * @return std::string the current version info string for dynamic clusters, + * or "static" if CDS is not in use. + */ + virtual const std::string versionInfo() const PURE; }; typedef std::unique_ptr ClusterManagerPtr; diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index a05038e3fa12..34e62215e0fe 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -476,6 +476,13 @@ Http::AsyncClient& ClusterManagerImpl::httpAsyncClientForCluster(const std::stri } } +const std::string ClusterManagerImpl::versionInfo() const { + if (cds_api_) { + return cds_api_->versionInfo(); + } + return "static"; +} + ClusterManagerImpl::ThreadLocalClusterManagerImpl::ThreadLocalClusterManagerImpl( ClusterManagerImpl& parent, Event::Dispatcher& dispatcher, const Optional& local_cluster_name) diff --git a/source/common/upstream/cluster_manager_impl.h b/source/common/upstream/cluster_manager_impl.h index 693b93dc96d8..f102888b4bb5 100644 --- a/source/common/upstream/cluster_manager_impl.h +++ b/source/common/upstream/cluster_manager_impl.h @@ -174,6 +174,8 @@ class ClusterManagerImpl : public ClusterManager, Logger::Loggablename(), cluster.second.get().outlierDetector(), response); diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index 52098ff0ea63..e83d88968d9d 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -130,6 +130,42 @@ envoy::api::v2::Bootstrap parseBootstrapFromV2Yaml(const std::string& yaml) { return bootstrap; } +TEST_F(ClusterManagerImplTest, VersionInfoStatic) { + const std::string json = fmt::sprintf( + R"EOF( + { + %s + } + )EOF", + clustersJson({defaultStaticClusterJson("cluster_0")})); + + create(parseBootstrapFromJson(json)); + EXPECT_EQ("static", cluster_manager_->versionInfo()); +} + +TEST_F(ClusterManagerImplTest, VersionInfoDynamic) { + const std::string json = fmt::sprintf( + R"EOF( + { + "cds": {"cluster": %s}, + %s + } + )EOF", + defaultStaticClusterJson("cds_cluster"), + clustersJson({defaultStaticClusterJson("cluster_0")})); + + // Setup cds api in order to control returned version info string. + MockCdsApi* cds = new MockCdsApi(); + EXPECT_CALL(factory_, createCds_()).WillOnce(Return(cds)); + EXPECT_CALL(*cds, setInitializedCb(_)); + EXPECT_CALL(*cds, initialize()); + + create(parseBootstrapFromJson(json)); + + EXPECT_CALL(*cds, versionInfo()).WillOnce(Return("version")); + EXPECT_EQ("version", cluster_manager_->versionInfo()); +} + TEST_F(ClusterManagerImplTest, OutlierEventLog) { const std::string json = R"EOF( { diff --git a/test/integration/integration_admin_test.cc b/test/integration/integration_admin_test.cc index bfe892aed88f..8c28e2b5259b 100644 --- a/test/integration/integration_admin_test.cc +++ b/test/integration/integration_admin_test.cc @@ -142,6 +142,7 @@ TEST_P(IntegrationAdminTest, Admin) { EXPECT_TRUE(response->complete()); EXPECT_STREQ("200", response->headers().Status()->value().c_str()); EXPECT_THAT(response->body(), testing::HasSubstr("added_via_api")); + EXPECT_THAT(response->body(), testing::HasSubstr("version_info::\n")); response = IntegrationUtil::makeSingleRequest(lookupPort("admin"), "GET", "/cpuprofiler", "", downstreamProtocol(), version_); diff --git a/test/mocks/upstream/mocks.h b/test/mocks/upstream/mocks.h index 8a326dbd5c93..195cc23b53ac 100644 --- a/test/mocks/upstream/mocks.h +++ b/test/mocks/upstream/mocks.h @@ -161,6 +161,7 @@ class MockClusterManager : public ClusterManager { MOCK_METHOD0(shutdown, void()); MOCK_CONST_METHOD0(sourceAddress, const Network::Address::InstanceConstSharedPtr&()); MOCK_METHOD0(adsMux, Config::GrpcMux&()); + MOCK_CONST_METHOD0(versionInfo, const std::string()); NiceMock conn_pool_; NiceMock async_client_;