mirror of https://github.com/grpc/grpc.git
commit
7b8be4d6fd
61 changed files with 1833 additions and 208 deletions
@ -0,0 +1,41 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 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_CHANNELZ_SERVICE_PLUGIN_H |
||||
#define GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpcpp/impl/server_builder_plugin.h> |
||||
#include <grpcpp/impl/server_initializer.h> |
||||
#include <grpcpp/support/config.h> |
||||
|
||||
namespace grpc { |
||||
namespace channelz { |
||||
namespace experimental { |
||||
|
||||
/// Add channelz server plugin to \a ServerBuilder. This function should
|
||||
/// be called at static initialization time. This service is experimental
|
||||
/// for now. Track progress in https://github.com/grpc/grpc/issues/15988.
|
||||
void InitChannelzService(); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace channelz
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_H
|
@ -0,0 +1,57 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 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 "src/cpp/server/channelz/channelz_service.h" |
||||
|
||||
#include <google/protobuf/text_format.h> |
||||
#include <google/protobuf/util/json_util.h> |
||||
|
||||
#include <grpc/grpc.h> |
||||
#include <grpc/support/alloc.h> |
||||
|
||||
namespace grpc { |
||||
|
||||
Status ChannelzService::GetTopChannels( |
||||
ServerContext* unused, const channelz::v1::GetTopChannelsRequest* request, |
||||
channelz::v1::GetTopChannelsResponse* response) { |
||||
char* json_str = grpc_channelz_get_top_channels(request->start_channel_id()); |
||||
google::protobuf::util::Status s = |
||||
google::protobuf::util::JsonStringToMessage(json_str, response); |
||||
gpr_free(json_str); |
||||
if (s != google::protobuf::util::Status::OK) { |
||||
return Status(INTERNAL, s.ToString()); |
||||
} |
||||
return Status::OK; |
||||
} |
||||
|
||||
Status ChannelzService::GetChannel( |
||||
ServerContext* unused, const channelz::v1::GetChannelRequest* request, |
||||
channelz::v1::GetChannelResponse* response) { |
||||
char* json_str = grpc_channelz_get_channel(request->channel_id()); |
||||
google::protobuf::util::Status s = |
||||
google::protobuf::util::JsonStringToMessage(json_str, response); |
||||
gpr_free(json_str); |
||||
if (s != google::protobuf::util::Status::OK) { |
||||
return Status(INTERNAL, s.ToString()); |
||||
} |
||||
return Status::OK; |
||||
} |
||||
|
||||
} // namespace grpc
|
@ -0,0 +1,43 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 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 GRPC_INTERNAL_CPP_SERVER_CHANNELZ_SERVICE_H |
||||
#define GRPC_INTERNAL_CPP_SERVER_CHANNELZ_SERVICE_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpcpp/grpcpp.h> |
||||
#include "src/proto/grpc/channelz/channelz.grpc.pb.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
class ChannelzService final : public channelz::v1::Channelz::Service { |
||||
private: |
||||
// implementation of GetTopChannels rpc
|
||||
Status GetTopChannels( |
||||
ServerContext* unused, const channelz::v1::GetTopChannelsRequest* request, |
||||
channelz::v1::GetTopChannelsResponse* response) override; |
||||
// implementation of GetChannel rpc
|
||||
Status GetChannel(ServerContext* unused, |
||||
const channelz::v1::GetChannelRequest* request, |
||||
channelz::v1::GetChannelResponse* response) override; |
||||
}; |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPC_INTERNAL_CPP_SERVER_CHANNELZ_SERVICE_H
|
@ -0,0 +1,79 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 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 <grpcpp/ext/channelz_service_plugin.h> |
||||
#include <grpcpp/impl/server_builder_plugin.h> |
||||
#include <grpcpp/impl/server_initializer.h> |
||||
#include <grpcpp/server.h> |
||||
|
||||
#include "src/cpp/server/channelz/channelz_service.h" |
||||
|
||||
namespace grpc { |
||||
namespace channelz { |
||||
namespace experimental { |
||||
|
||||
class ChannelzServicePlugin : public ::grpc::ServerBuilderPlugin { |
||||
public: |
||||
ChannelzServicePlugin() : channelz_service_(new grpc::ChannelzService()) {} |
||||
|
||||
grpc::string name() override { return "channelz_service"; } |
||||
|
||||
void InitServer(grpc::ServerInitializer* si) override { |
||||
si->RegisterService(channelz_service_); |
||||
} |
||||
|
||||
void Finish(grpc::ServerInitializer* si) override {} |
||||
|
||||
void ChangeArguments(const grpc::string& name, void* value) override {} |
||||
|
||||
bool has_sync_methods() const override { |
||||
if (channelz_service_) { |
||||
return channelz_service_->has_synchronous_methods(); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
bool has_async_methods() const override { |
||||
if (channelz_service_) { |
||||
return channelz_service_->has_async_methods(); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private: |
||||
std::shared_ptr<grpc::ChannelzService> channelz_service_; |
||||
}; |
||||
|
||||
static std::unique_ptr< ::grpc::ServerBuilderPlugin> |
||||
CreateChannelzServicePlugin() { |
||||
return std::unique_ptr< ::grpc::ServerBuilderPlugin>( |
||||
new ChannelzServicePlugin()); |
||||
} |
||||
|
||||
void InitChannelzService() { |
||||
static bool already_here = false; |
||||
if (already_here) return; |
||||
already_here = true; |
||||
::grpc::ServerBuilder::InternalAddPluginFactory(&CreateChannelzServicePlugin); |
||||
} |
||||
|
||||
} // namespace experimental
|
||||
} // namespace channelz
|
||||
} // namespace grpc
|
@ -0,0 +1,21 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<PropertyGroup> |
||||
<_GrpcCoreNugetNativePath Condition="'$(_GrpcCoreNugetNativePath)' == ''">$(MSBuildThisFileDirectory)..\..\</_GrpcCoreNugetNativePath> |
||||
</PropertyGroup> |
||||
|
||||
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == 'MonoAndroid'"> |
||||
<AndroidNativeLibrary Include="$(_GrpcCoreNugetNativePath)runtimes\monoandroid\arm64-v8a\libgrpc_csharp_ext.so"> |
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
||||
<Abi>arm64-v8a</Abi> |
||||
</AndroidNativeLibrary> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == 'MonoAndroid'"> |
||||
<AndroidNativeLibrary Include="$(_GrpcCoreNugetNativePath)runtimes\monoandroid\armeabi-v7a\libgrpc_csharp_ext.so"> |
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
||||
<Abi>armeabi-v7a</Abi> |
||||
</AndroidNativeLibrary> |
||||
</ItemGroup> |
||||
|
||||
</Project> |
@ -0,0 +1,352 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 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 <grpc/grpc.h> |
||||
#include <grpcpp/channel.h> |
||||
#include <grpcpp/client_context.h> |
||||
#include <grpcpp/create_channel.h> |
||||
#include <grpcpp/security/credentials.h> |
||||
#include <grpcpp/security/server_credentials.h> |
||||
#include <grpcpp/server.h> |
||||
#include <grpcpp/server_builder.h> |
||||
#include <grpcpp/server_context.h> |
||||
|
||||
#include <grpcpp/ext/channelz_service_plugin.h> |
||||
#include "src/proto/grpc/channelz/channelz.grpc.pb.h" |
||||
#include "src/proto/grpc/testing/echo.grpc.pb.h" |
||||
#include "test/core/util/port.h" |
||||
#include "test/core/util/test_config.h" |
||||
#include "test/cpp/end2end/test_service_impl.h" |
||||
|
||||
#include <gtest/gtest.h> |
||||
|
||||
using grpc::channelz::v1::GetChannelRequest; |
||||
using grpc::channelz::v1::GetChannelResponse; |
||||
using grpc::channelz::v1::GetTopChannelsRequest; |
||||
using grpc::channelz::v1::GetTopChannelsResponse; |
||||
|
||||
namespace grpc { |
||||
namespace testing { |
||||
namespace { |
||||
|
||||
// Proxy service supports N backends. Sends RPC to backend dictated by
|
||||
// request->backend_channel_idx().
|
||||
class Proxy : public ::grpc::testing::EchoTestService::Service { |
||||
public: |
||||
Proxy() {} |
||||
|
||||
void AddChannelToBackend(const std::shared_ptr<Channel>& channel) { |
||||
stubs_.push_back(grpc::testing::EchoTestService::NewStub(channel)); |
||||
} |
||||
|
||||
Status Echo(ServerContext* server_context, const EchoRequest* request, |
||||
EchoResponse* response) override { |
||||
std::unique_ptr<ClientContext> client_context = |
||||
ClientContext::FromServerContext(*server_context); |
||||
size_t idx = request->param().backend_channel_idx(); |
||||
GPR_ASSERT(idx < stubs_.size()); |
||||
return stubs_[idx]->Echo(client_context.get(), *request, response); |
||||
} |
||||
|
||||
private: |
||||
std::vector<std::unique_ptr<::grpc::testing::EchoTestService::Stub>> stubs_; |
||||
}; |
||||
|
||||
} // namespace
|
||||
|
||||
class ChannelzServerTest : public ::testing::Test { |
||||
public: |
||||
ChannelzServerTest() {} |
||||
|
||||
void SetUp() override { |
||||
// ensure channel server is brought up on all severs we build.
|
||||
::grpc::channelz::experimental::InitChannelzService(); |
||||
|
||||
// We set up a proxy server with channelz enabled.
|
||||
proxy_port_ = grpc_pick_unused_port_or_die(); |
||||
ServerBuilder proxy_builder; |
||||
grpc::string proxy_server_address = "localhost:" + to_string(proxy_port_); |
||||
proxy_builder.AddListeningPort(proxy_server_address, |
||||
InsecureServerCredentials()); |
||||
// forces channelz and channel tracing to be enabled.
|
||||
proxy_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 1); |
||||
proxy_builder.AddChannelArgument(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE, |
||||
10); |
||||
proxy_builder.RegisterService(&proxy_service_); |
||||
proxy_server_ = proxy_builder.BuildAndStart(); |
||||
} |
||||
|
||||
// Sets the proxy up to have an arbitrary number of backends.
|
||||
void ConfigureProxy(size_t num_backends) { |
||||
backends_.resize(num_backends); |
||||
for (size_t i = 0; i < num_backends; ++i) { |
||||
// create a new backend.
|
||||
backends_[i].port = grpc_pick_unused_port_or_die(); |
||||
ServerBuilder backend_builder; |
||||
grpc::string backend_server_address = |
||||
"localhost:" + to_string(backends_[i].port); |
||||
backend_builder.AddListeningPort(backend_server_address, |
||||
InsecureServerCredentials()); |
||||
backends_[i].service.reset(new TestServiceImpl); |
||||
// ensure that the backend itself has channelz disabled.
|
||||
backend_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 0); |
||||
backend_builder.RegisterService(backends_[i].service.get()); |
||||
backends_[i].server = backend_builder.BuildAndStart(); |
||||
// set up a channel to the backend. We ensure that this channel has
|
||||
// channelz enabled since these channels (proxy outbound to backends)
|
||||
// are the ones that our test will actually be validating.
|
||||
ChannelArguments args; |
||||
args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 1); |
||||
args.SetInt(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE, 10); |
||||
std::shared_ptr<Channel> channel_to_backend = CreateCustomChannel( |
||||
backend_server_address, InsecureChannelCredentials(), args); |
||||
proxy_service_.AddChannelToBackend(channel_to_backend); |
||||
} |
||||
} |
||||
|
||||
void ResetStubs() { |
||||
string target = "dns:localhost:" + to_string(proxy_port_); |
||||
ChannelArguments args; |
||||
// disable channelz. We only want to focus on proxy to backend outbound.
|
||||
args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0); |
||||
std::shared_ptr<Channel> channel = |
||||
CreateCustomChannel(target, InsecureChannelCredentials(), args); |
||||
channelz_stub_ = grpc::channelz::v1::Channelz::NewStub(channel); |
||||
echo_stub_ = grpc::testing::EchoTestService::NewStub(channel); |
||||
} |
||||
|
||||
void SendSuccessfulEcho(int channel_idx) { |
||||
EchoRequest request; |
||||
EchoResponse response; |
||||
request.set_message("Hello channelz"); |
||||
request.mutable_param()->set_backend_channel_idx(channel_idx); |
||||
ClientContext context; |
||||
Status s = echo_stub_->Echo(&context, request, &response); |
||||
EXPECT_EQ(response.message(), request.message()); |
||||
EXPECT_TRUE(s.ok()); |
||||
} |
||||
|
||||
void SendFailedEcho(int channel_idx) { |
||||
EchoRequest request; |
||||
EchoResponse response; |
||||
request.set_message("Hello channelz"); |
||||
request.mutable_param()->set_backend_channel_idx(channel_idx); |
||||
auto* error = request.mutable_param()->mutable_expected_error(); |
||||
error->set_code(13); // INTERNAL
|
||||
error->set_error_message("error"); |
||||
ClientContext context; |
||||
Status s = echo_stub_->Echo(&context, request, &response); |
||||
EXPECT_FALSE(s.ok()); |
||||
} |
||||
|
||||
static string to_string(const int number) { |
||||
std::stringstream strs; |
||||
strs << number; |
||||
return strs.str(); |
||||
} |
||||
|
||||
protected: |
||||
// package of data needed for each backend server.
|
||||
struct BackendData { |
||||
std::unique_ptr<Server> server; |
||||
int port; |
||||
std::unique_ptr<TestServiceImpl> service; |
||||
}; |
||||
|
||||
std::unique_ptr<grpc::channelz::v1::Channelz::Stub> channelz_stub_; |
||||
std::unique_ptr<grpc::testing::EchoTestService::Stub> echo_stub_; |
||||
|
||||
// proxy server to ping with channelz requests.
|
||||
std::unique_ptr<Server> proxy_server_; |
||||
int proxy_port_; |
||||
Proxy proxy_service_; |
||||
|
||||
// backends. All implement the echo service.
|
||||
std::vector<BackendData> backends_; |
||||
}; |
||||
|
||||
TEST_F(ChannelzServerTest, BasicTest) { |
||||
ResetStubs(); |
||||
ConfigureProxy(1); |
||||
GetTopChannelsRequest request; |
||||
GetTopChannelsResponse response; |
||||
request.set_start_channel_id(0); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetTopChannels(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel_size(), 1); |
||||
} |
||||
|
||||
TEST_F(ChannelzServerTest, HighStartId) { |
||||
ResetStubs(); |
||||
ConfigureProxy(1); |
||||
GetTopChannelsRequest request; |
||||
GetTopChannelsResponse response; |
||||
request.set_start_channel_id(10000); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetTopChannels(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel_size(), 0); |
||||
} |
||||
|
||||
TEST_F(ChannelzServerTest, SuccessfulRequestTest) { |
||||
ResetStubs(); |
||||
ConfigureProxy(1); |
||||
SendSuccessfulEcho(0); |
||||
GetChannelRequest request; |
||||
GetChannelResponse response; |
||||
request.set_channel_id(1); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetChannel(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel().data().calls_started(), 1); |
||||
EXPECT_EQ(response.channel().data().calls_succeeded(), 1); |
||||
EXPECT_EQ(response.channel().data().calls_failed(), 0); |
||||
} |
||||
|
||||
TEST_F(ChannelzServerTest, FailedRequestTest) { |
||||
ResetStubs(); |
||||
ConfigureProxy(1); |
||||
SendFailedEcho(0); |
||||
GetChannelRequest request; |
||||
GetChannelResponse response; |
||||
request.set_channel_id(1); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetChannel(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel().data().calls_started(), 1); |
||||
EXPECT_EQ(response.channel().data().calls_succeeded(), 0); |
||||
EXPECT_EQ(response.channel().data().calls_failed(), 1); |
||||
} |
||||
|
||||
TEST_F(ChannelzServerTest, ManyRequestsTest) { |
||||
ResetStubs(); |
||||
ConfigureProxy(1); |
||||
// send some RPCs
|
||||
const int kNumSuccess = 10; |
||||
const int kNumFailed = 11; |
||||
for (int i = 0; i < kNumSuccess; ++i) { |
||||
SendSuccessfulEcho(0); |
||||
} |
||||
for (int i = 0; i < kNumFailed; ++i) { |
||||
SendFailedEcho(0); |
||||
} |
||||
GetChannelRequest request; |
||||
GetChannelResponse response; |
||||
request.set_channel_id(1); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetChannel(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel().data().calls_started(), |
||||
kNumSuccess + kNumFailed); |
||||
EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess); |
||||
EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); |
||||
} |
||||
|
||||
TEST_F(ChannelzServerTest, ManyChannels) { |
||||
ResetStubs(); |
||||
const int kNumChannels = 4; |
||||
ConfigureProxy(kNumChannels); |
||||
GetTopChannelsRequest request; |
||||
GetTopChannelsResponse response; |
||||
request.set_start_channel_id(0); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetTopChannels(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel_size(), kNumChannels); |
||||
} |
||||
|
||||
TEST_F(ChannelzServerTest, ManyRequestsManyChannels) { |
||||
ResetStubs(); |
||||
const int kNumChannels = 4; |
||||
ConfigureProxy(kNumChannels); |
||||
const int kNumSuccess = 10; |
||||
const int kNumFailed = 11; |
||||
for (int i = 0; i < kNumSuccess; ++i) { |
||||
SendSuccessfulEcho(0); |
||||
SendSuccessfulEcho(2); |
||||
} |
||||
for (int i = 0; i < kNumFailed; ++i) { |
||||
SendFailedEcho(1); |
||||
SendFailedEcho(2); |
||||
} |
||||
|
||||
// the first channel saw only successes
|
||||
{ |
||||
GetChannelRequest request; |
||||
GetChannelResponse response; |
||||
request.set_channel_id(1); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetChannel(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel().data().calls_started(), kNumSuccess); |
||||
EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess); |
||||
EXPECT_EQ(response.channel().data().calls_failed(), 0); |
||||
} |
||||
|
||||
// the second channel saw only failures
|
||||
{ |
||||
GetChannelRequest request; |
||||
GetChannelResponse response; |
||||
request.set_channel_id(2); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetChannel(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel().data().calls_started(), kNumFailed); |
||||
EXPECT_EQ(response.channel().data().calls_succeeded(), 0); |
||||
EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); |
||||
} |
||||
|
||||
// the third channel saw both
|
||||
{ |
||||
GetChannelRequest request; |
||||
GetChannelResponse response; |
||||
request.set_channel_id(3); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetChannel(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel().data().calls_started(), |
||||
kNumSuccess + kNumFailed); |
||||
EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess); |
||||
EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); |
||||
} |
||||
|
||||
// the fourth channel saw nothing
|
||||
{ |
||||
GetChannelRequest request; |
||||
GetChannelResponse response; |
||||
request.set_channel_id(4); |
||||
ClientContext context; |
||||
Status s = channelz_stub_->GetChannel(&context, request, &response); |
||||
EXPECT_TRUE(s.ok()); |
||||
EXPECT_EQ(response.channel().data().calls_started(), 0); |
||||
EXPECT_EQ(response.channel().data().calls_succeeded(), 0); |
||||
EXPECT_EQ(response.channel().data().calls_failed(), 0); |
||||
} |
||||
} |
||||
|
||||
} // namespace testing
|
||||
} // namespace grpc
|
||||
|
||||
int main(int argc, char** argv) { |
||||
grpc_test_init(argc, argv); |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
@ -0,0 +1,26 @@ |
||||
# Copyright 2018 The 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. |
||||
|
||||
# Config file for the internal CI (in protobuf text format) |
||||
|
||||
# Location of the continuous shell script in repository. |
||||
build_file: "grpc/tools/internal_ci/linux/grpc_publish_packages.sh" |
||||
timeout_mins: 120 |
||||
action { |
||||
define_artifacts { |
||||
regex: "**/*sponge_log.xml" |
||||
regex: "github/grpc/reports/**" |
||||
regex: "github/grpc/artifacts/**" |
||||
} |
||||
} |
@ -0,0 +1,144 @@ |
||||
#!/bin/bash |
||||
# Copyright 2018 The 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. |
||||
|
||||
set -ex |
||||
|
||||
shopt -s nullglob |
||||
|
||||
INPUT_ARTIFACTS=$KOKORO_GFILE_DIR/github/grpc/artifacts |
||||
INDEX_FILENAME=index.xml |
||||
|
||||
BUILD_ID=${KOKORO_BUILD_ID:-$(uuidgen)} |
||||
BUILD_BRANCH_NAME=master |
||||
BUILD_GIT_COMMIT=${KOKORO_GIT_COMMIT:-unknown} |
||||
BUILD_TIMESTAMP=$(date -Iseconds) |
||||
BUILD_RELPATH=$(date "+%Y/%m")/$BUILD_ID/ |
||||
|
||||
GCS_ROOT=gs://packages.grpc.io/ |
||||
GCS_ARCHIVE_PREFIX=archive/ |
||||
GCS_ARCHIVE_ROOT=$GCS_ROOT$GCS_ARCHIVE_PREFIX |
||||
GCS_INDEX=$GCS_ROOT$INDEX_FILENAME |
||||
|
||||
LOCAL_STAGING_TEMPDIR=$(mktemp -d) |
||||
LOCAL_BUILD_ROOT=$LOCAL_STAGING_TEMPDIR/$BUILD_RELPATH |
||||
LOCAL_BUILD_INDEX=$LOCAL_BUILD_ROOT$INDEX_FILENAME |
||||
|
||||
mkdir -p "$LOCAL_BUILD_ROOT" |
||||
|
||||
find "$INPUT_ARTIFACTS" -type f |
||||
|
||||
UNZIPPED_CSHARP_PACKAGES=$(mktemp -d) |
||||
unzip "$INPUT_ARTIFACTS/csharp_nugets_windows_dotnetcli.zip" -d "$UNZIPPED_CSHARP_PACKAGES" |
||||
CSHARP_PACKAGES=( |
||||
"$UNZIPPED_CSHARP_PACKAGES"/* |
||||
) |
||||
|
||||
PYTHON_PACKAGES=( |
||||
"$INPUT_ARTIFACTS"/grpcio-[0-9]*.tar.gz |
||||
"$INPUT_ARTIFACTS"/grpcio-[0-9]*.whl |
||||
"$INPUT_ARTIFACTS"/python_linux_extra_arm*/grpcio-[0-9]*.whl |
||||
|
||||
"$INPUT_ARTIFACTS"/grpcio-tools-[0-9]*.tar.gz |
||||
"$INPUT_ARTIFACTS"/grpcio_tools-[0-9]*.whl |
||||
"$INPUT_ARTIFACTS"/python_linux_extra_arm*/grpcio_tools-[0-9]*.whl |
||||
|
||||
"$INPUT_ARTIFACTS"/grpcio-health-checking-[0-9]*.tar.gz |
||||
"$INPUT_ARTIFACTS"/grpcio-reflection-[0-9]*.tar.gz |
||||
"$INPUT_ARTIFACTS"/grpcio-testing-[0-9]*.tar.gz |
||||
) |
||||
|
||||
PHP_PACKAGES=( |
||||
"$INPUT_ARTIFACTS"/grpc-[0-9]*.tgz |
||||
) |
||||
|
||||
RUBY_PACKAGES=( |
||||
"$INPUT_ARTIFACTS"/grpc-[0-9]*.gem |
||||
"$INPUT_ARTIFACTS"/grpc-tools-[0-9]*.gem |
||||
) |
||||
|
||||
function add_to_manifest() { |
||||
local artifact_type=$1 |
||||
local artifact_file=$2 |
||||
local artifact_name |
||||
artifact_name=$(basename "$artifact_file") |
||||
local artifact_sha256 |
||||
artifact_sha256=$(openssl sha256 -r "$artifact_file" | cut -d " " -f 1) |
||||
local artifact_target=$LOCAL_BUILD_ROOT/$artifact_type |
||||
mkdir -p "$artifact_target" |
||||
cp "$artifact_file" "$artifact_target" |
||||
cat <<EOF |
||||
<artifact name='$artifact_name' |
||||
type='$artifact_type' |
||||
path='$artifact_type/$artifact_name' |
||||
sha256='$artifact_sha256' /> |
||||
EOF |
||||
} |
||||
|
||||
{ |
||||
cat <<EOF |
||||
<?xml version="1.0"?> |
||||
<?xml-stylesheet href="/web-assets/build-201807.xsl" type="text/xsl"?> |
||||
<build id='$BUILD_ID' timestamp='$BUILD_TIMESTAMP'> |
||||
<metadata> |
||||
<project>gRPC</project> |
||||
<repository>https://github.com/grpc/grpc</repository> |
||||
<branch>$BUILD_BRANCH_NAME</branch> |
||||
<commit>$BUILD_GIT_COMMIT</commit> |
||||
</metadata> |
||||
<artifacts> |
||||
EOF |
||||
|
||||
for pkg in "${CSHARP_PACKAGES[@]}"; do add_to_manifest csharp "$pkg"; done |
||||
for pkg in "${PHP_PACKAGES[@]}"; do add_to_manifest php "$pkg"; done |
||||
for pkg in "${PYTHON_PACKAGES[@]}"; do add_to_manifest python "$pkg"; done |
||||
for pkg in "${RUBY_PACKAGES[@]}"; do add_to_manifest ruby "$pkg"; done |
||||
|
||||
cat <<EOF |
||||
</artifacts> |
||||
</build> |
||||
EOF |
||||
}> "$LOCAL_BUILD_INDEX" |
||||
|
||||
LOCAL_BUILD_INDEX_SHA256=$(openssl sha256 -r "$LOCAL_BUILD_INDEX" | cut -d " " -f 1) |
||||
|
||||
OLD_INDEX=$(mktemp) |
||||
NEW_INDEX=$(mktemp) |
||||
|
||||
# Download the current /index.xml into $OLD_INDEX |
||||
gsutil cp "$GCS_INDEX" "$OLD_INDEX" |
||||
|
||||
{ |
||||
# we want to add an entry as the first child under <builds> tag |
||||
# we can get by without a real XML parser by rewriting the header, |
||||
# injecting our new tag, and then dumping the rest of the file as is. |
||||
cat <<EOF |
||||
<?xml version="1.0"?> |
||||
<?xml-stylesheet href="/web-assets/home.xsl" type="text/xsl"?> |
||||
<packages> |
||||
<builds> |
||||
<build id='$BUILD_ID' |
||||
timestamp='$BUILD_TIMESTAMP' |
||||
branch='$BUILD_BRANCH_NAME' |
||||
commit='$BUILD_GIT_COMMIT' |
||||
path='$GCS_ARCHIVE_PREFIX$BUILD_RELPATH$INDEX_FILENAME' |
||||
sha256='$LOCAL_BUILD_INDEX_SHA256' /> |
||||
EOF |
||||
tail --lines=+5 "$OLD_INDEX" |
||||
}> "$NEW_INDEX" |
||||
|
||||
# Upload the current build artifacts |
||||
gsutil -m cp -r "$LOCAL_STAGING_TEMPDIR/${BUILD_RELPATH%%/*}" "$GCS_ARCHIVE_ROOT" |
||||
# Upload the new /index.xml |
||||
gsutil -h "Content-Type:application/xml" cp "$NEW_INDEX" "$GCS_INDEX" |
Loading…
Reference in new issue