Implement C++ Admin Interface API (#25753)

* Implement C++ Admin Interface API

* Address reviewer's requests

* Remove static asserts for raw pointers

* Make sanity tests happy

* Windows: pacify conflict between ifndef and macros

* Disable admin services test on iOS

* Make iOS happy by:

* Letting grpcpp_admin conditionally depend on grpcpp_csds

* Fix an unexpected side-effect of dependency update
pull/25793/head
Lidi Zheng 4 years ago committed by GitHub
parent 55e32434ec
commit b457f43227
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      BUILD
  2. 56
      CMakeLists.txt
  3. 18
      build_autogenerated.yaml
  4. 33
      include/grpcpp/ext/admin_services.h
  5. 52
      src/cpp/server/admin/admin_services.cc
  6. 15
      test/cpp/end2end/BUILD
  7. 103
      test/cpp/end2end/admin_services_end2end_test.cc
  8. 1
      tools/internal_ci/linux/grpc_bazel_test_in_docker.sh
  9. 24
      tools/run_tests/generated/tests.json

28
BUILD

@ -2623,11 +2623,37 @@ grpc_cc_library_xds(
"src/cpp/server/csds/csds.h",
],
language = "c++",
deps = [
":grpc++_internals",
"//src/proto/grpc/testing/xds/v3:csds_proto",
],
alwayslink = 1,
)
grpc_cc_library(
name = "grpcpp_admin",
srcs = [
"src/cpp/server/admin/admin_services.cc",
],
hdrs = [],
defines = select({
"grpc_no_xds": ["GRPC_NO_XDS"],
"//conditions:default": [],
}),
external_deps = [
"absl/memory",
],
language = "c++",
public_hdrs = [
"include/grpcpp/ext/admin_services.h",
],
select_deps = {
"grpc_no_xds": [],
"//conditions:default": ["//:grpcpp_csds"],
},
deps = [
":grpc++",
"//src/proto/grpc/testing/xds/v3:csds_proto",
":grpcpp_channelz",
],
alwayslink = 1,
)

@ -726,6 +726,7 @@ if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx address_sorting_test_unsecure)
endif()
add_dependencies(buildtests_cxx admin_services_end2end_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx alarm_test)
endif()
@ -7755,6 +7756,61 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
endif()
endif()
if(gRPC_BUILD_TESTS)
add_executable(admin_services_end2end_test
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
src/cpp/server/admin/admin_services.cc
src/cpp/server/csds/csds.cc
test/cpp/end2end/admin_services_end2end_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(admin_services_end2end_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(admin_services_end2end_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++_reflection
grpcpp_channelz
grpc++_test_util
)
endif()
if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)

@ -4131,6 +4131,24 @@ targets:
- linux
- posix
- mac
- name: admin_services_end2end_test
gtest: true
build: test
language: c++
headers:
- src/cpp/server/csds/csds.h
src:
- src/proto/grpc/testing/xds/v3/base.proto
- src/proto/grpc/testing/xds/v3/config_dump.proto
- src/proto/grpc/testing/xds/v3/csds.proto
- src/proto/grpc/testing/xds/v3/percent.proto
- src/cpp/server/admin/admin_services.cc
- src/cpp/server/csds/csds.cc
- test/cpp/end2end/admin_services_end2end_test.cc
deps:
- grpc++_reflection
- grpcpp_channelz
- grpc++_test_util
- name: alarm_test
gtest: true
build: test

@ -0,0 +1,33 @@
//
//
// Copyright 2021 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#ifndef GRPCPP_EXT_ADMIN_SERVICES_H
#define GRPCPP_EXT_ADMIN_SERVICES_H
#include <grpcpp/server_builder.h>
namespace grpc {
// Registers admin services to the given ServerBuilder. This function will add
// admin services based on build time dependencies, for example, it only adds
// CSDS service if xDS is enabled in this binary.
void AddAdminServices(grpc::ServerBuilder* builder);
} // namespace grpc
#endif // GRPCPP_EXT_ADMIN_SERVICES_H

@ -0,0 +1,52 @@
//
//
// Copyright 2021 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#include <grpc/support/port_platform.h>
#include "absl/memory/memory.h"
#include <grpcpp/ext/admin_services.h>
#include <grpcpp/impl/server_builder_plugin.h>
#include <grpcpp/server_builder.h>
// TODO(lidiz) build a real registration system that can pull in services
// automatically with minimum amount of code.
#include "src/cpp/server/channelz/channelz_service.h"
#ifndef GRPC_NO_XDS
#include "src/cpp/server/csds/csds.h"
#endif // GRPC_NO_XDS
namespace grpc {
namespace {
static auto* g_channelz_service = new ChannelzService();
#ifndef GRPC_NO_XDS
static auto* g_csds = new xds::experimental::ClientStatusDiscoveryService();
#endif // GRPC_NO_XDS
} // namespace
void AddAdminServices(ServerBuilder* builder) {
builder->RegisterService(g_channelz_service);
#ifndef GRPC_NO_XDS
builder->RegisterService(g_csds);
#endif // GRPC_NO_XDS
}
} // namespace grpc

@ -873,3 +873,18 @@ grpc_cc_test(
"//test/cpp/util:test_util",
],
)
grpc_cc_test(
name = "admin_services_end2end_test",
srcs = ["admin_services_end2end_test.cc"],
external_deps = [
"gtest",
],
deps = [
"//:grpc++",
"//:grpc++_reflection",
"//:grpcpp_admin",
"//test/core/util:grpc_test_util",
"//test/cpp/util:test_util",
],
)

@ -0,0 +1,103 @@
//
//
// Copyright 2021 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "absl/strings/str_cat.h"
#include <grpcpp/ext/admin_services.h>
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
namespace grpc {
namespace testing {
class AdminServicesTest : public ::testing::Test {
public:
void SetUp() override {
std::string address =
absl::StrCat("localhost:", grpc_pick_unused_port_or_die());
// Create admin server
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;
builder.AddListeningPort(address, InsecureServerCredentials());
::grpc::AddAdminServices(&builder);
server_ = builder.BuildAndStart();
// Create channel
auto reflection_stub = reflection::v1alpha::ServerReflection::NewStub(
CreateChannel(address, InsecureChannelCredentials()));
stream_ = reflection_stub->ServerReflectionInfo(&reflection_ctx_);
}
std::vector<std::string> GetServiceList() {
std::vector<std::string> services;
reflection::v1alpha::ServerReflectionRequest request;
reflection::v1alpha::ServerReflectionResponse response;
request.set_list_services("");
stream_->Write(request);
stream_->Read(&response);
for (auto& service : response.list_services_response().service()) {
services.push_back(service.name());
}
return services;
}
private:
std::unique_ptr<Server> server_;
ClientContext reflection_ctx_;
std::shared_ptr<
ClientReaderWriter<reflection::v1alpha::ServerReflectionRequest,
reflection::v1alpha::ServerReflectionResponse>>
stream_;
};
#ifndef GRPC_NO_XDS
// The ifndef conflicts with TEST_F and EXPECT_THAT macros, so we better isolate
// the condition at test case level.
TEST_F(AdminServicesTest, XdsEnabled) {
EXPECT_THAT(GetServiceList(),
::testing::UnorderedElementsAre(
"envoy.service.status.v3.ClientStatusDiscoveryService",
"grpc.channelz.v1.Channelz",
"grpc.reflection.v1alpha.ServerReflection"));
}
#endif // GRPC_NO_XDS
#ifdef GRPC_NO_XDS
TEST_F(AdminServicesTest, XdsDisabled) {
EXPECT_THAT(GetServiceList(),
::testing::UnorderedElementsAre(
"grpc.channelz.v1.Channelz",
"grpc.reflection.v1alpha.ServerReflection"));
}
#endif // GRPC_NO_XDS
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}

@ -26,3 +26,4 @@ ${name}')
cd /var/local/git/grpc
bazel test //test/...
bazel test //test/cpp/end2end:admin_services_end2end_test --define=grpc_no_xds=true

@ -3171,6 +3171,30 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "admin_services_end2end_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save