Merge github.com:grpc/grpc into pbe2

pull/35435/head
Craig Tiller 11 months ago
commit 14de33646b
  1. 2
      .bazelci/presubmit.yml
  2. 10
      .github/CODEOWNERS
  3. 2
      .github/ISSUE_TEMPLATE/bug_report_csharp.md
  4. 2
      .github/ISSUE_TEMPLATE/feature_request_csharp.md
  5. 95
      src/core/ext/filters/stateful_session/stateful_session_filter.cc
  6. 25
      src/core/ext/filters/stateful_session/stateful_session_filter.h
  7. 3
      src/core/lib/surface/call.cc
  8. 5
      src/core/tsi/ssl_transport_security.cc
  9. 4
      tools/bazelify_tests/dockerimage_current_versions.bzl
  10. 1
      tools/dockerfile/distribtest/python_dev_ubuntu1804_x64.current_version
  11. 22
      tools/dockerfile/distribtest/python_dev_ubuntu1804_x64/Dockerfile
  12. 1
      tools/dockerfile/distribtest/python_ubuntu1804_x64.current_version
  13. 19
      tools/dockerfile/distribtest/python_ubuntu1804_x64/Dockerfile
  14. 1
      tools/dockerfile/distribtest/ruby_ubuntu1804_x64.current_version
  15. 1
      tools/dockerfile/distribtest/ruby_ubuntu2004_x64.current_version
  16. 6
      tools/dockerfile/distribtest/ruby_ubuntu2004_x64/Dockerfile
  17. 2
      tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh
  18. 2
      tools/gce/create_linux_kokoro_performance_worker.sh
  19. 2
      tools/gce/linux_kokoro_performance_worker_init.sh
  20. 2
      tools/run_tests/artifacts/distribtest_targets.py
  21. 8
      tools/run_tests/helper_scripts/build_python.sh
  22. 40
      tools/run_tests/performance/bq_upload_result.py
  23. 2
      tools/run_tests/xds_k8s_test_driver/framework/test_app/runners/k8s/gamma_server_runner.py
  24. 28
      tools/run_tests/xds_k8s_test_driver/framework/test_app/runners/k8s/k8s_base_runner.py
  25. 12
      tools/run_tests/xds_k8s_test_driver/framework/test_app/runners/k8s/k8s_xds_client_runner.py
  26. 3
      tools/run_tests/xds_k8s_test_driver/kubernetes-manifests/client.deployment.yaml
  27. 4
      tools/run_tests/xds_k8s_test_driver/kubernetes-manifests/csm/pod-monitoring.yaml
  28. 3
      tools/run_tests/xds_k8s_test_driver/kubernetes-manifests/server.deployment.yaml
  29. 48
      tools/run_tests/xds_k8s_test_driver/tests/gamma/csm_observability_test.py

@ -12,7 +12,7 @@
---
# TODO(yannic): Ideally, we should also enable buildifier and all platforms should test `//...`.
tasks:
ubuntu1804:
ubuntu2004:
build_targets:
- //:all
- //src/proto/...

@ -1,13 +1,11 @@
# Auto-generated by the tools/mkowners/mkowners.py tool
# Uses OWNERS files in different modules throughout the
# repository as the source of truth for module ownership.
/**/OWNERS @markdroth @a11r
/bazel/** @jtattermusch @veblush @gnossen
/cmake/** @jtattermusch @apolcyn
/bazel/** @veblush @gnossen
/bazel/experiments.yaml
/cmake/** @veblush @apolcyn
/src/core/ext/filters/client_channel/** @markdroth
/src/core/ext/transport/chttp2/transport/** @ctiller
/src/core/ext/xds/** @markdroth
/src/core/lib/resolver/** @markdroth
/src/core/lib/service_config/** @markdroth
/tools/dockerfile/** @jtattermusch @apolcyn
/tools/dockerfile/** @drfloob @apolcyn @gnossen
/tools/run_tests/xds_k8s_test_driver/** @sergiitk @XuanWang-Amos @gnossen

@ -2,7 +2,7 @@
name: Report a gRPC C# bug
about: Create a report to help us improve
labels: kind/bug, priority/P2, lang/C#
assignees: jtattermusch
assignees: apolcyn
---

@ -2,7 +2,7 @@
name: Request a gRPC C# feature
about: Suggest an idea for this project
labels: kind/enhancement, priority/P2, lang/C#
assignees: jtattermusch
assignees: apolcyn
---

@ -58,6 +58,9 @@
namespace grpc_core {
TraceFlag grpc_stateful_session_filter_trace(false, "stateful_session_filter");
const NoInterceptor StatefulSessionFilter::Call::OnClientToServerMessage;
const NoInterceptor StatefulSessionFilter::Call::OnServerToClientMessage;
const NoInterceptor StatefulSessionFilter::Call::OnFinalize;
UniqueTypeName XdsOverrideHostAttribute::TypeName() {
static UniqueTypeName::Factory kFactory("xds_override_host");
@ -103,7 +106,7 @@ void MaybeUpdateServerInitialMetadata(
bool cluster_changed, absl::string_view actual_cluster,
absl::string_view cookie_address_list,
XdsOverrideHostAttribute* override_host_attribute,
ServerMetadata* server_initial_metadata) {
ServerMetadata& server_initial_metadata) {
// If cookie doesn't need to change, do nothing.
if (cookie_address_list == override_host_attribute->actual_address_list() &&
!cluster_changed) {
@ -121,7 +124,7 @@ void MaybeUpdateServerInitialMetadata(
parts.emplace_back(
absl::StrCat("Max-Age=", cookie_config->ttl.as_timespec().tv_sec));
}
server_initial_metadata->Append(
server_initial_metadata.Append(
"set-cookie", Slice::FromCopiedString(absl::StrJoin(parts, "; ")),
[](absl::string_view error, const Slice&) {
Crash(absl::StrCat("ERROR ADDING set-cookie METADATA: ", error));
@ -168,12 +171,11 @@ absl::string_view GetClusterToUse(
return absl::StripPrefix(arena_allocated_cluster, kClusterPrefix);
}
std::string GetCookieValue(const ClientMetadataHandle& client_initial_metadata,
std::string GetCookieValue(const ClientMetadata& client_initial_metadata,
absl::string_view cookie_name) {
// Check to see if the cookie header is present.
std::string buffer;
auto header_value =
client_initial_metadata->GetStringValue("cookie", &buffer);
auto header_value = client_initial_metadata.GetStringValue("cookie", &buffer);
if (!header_value.has_value()) return "";
// Parse cookie header.
std::vector<absl::string_view> values;
@ -193,13 +195,14 @@ std::string GetCookieValue(const ClientMetadataHandle& client_initial_metadata,
}
bool IsConfiguredPath(absl::string_view configured_path,
const ClientMetadataHandle& client_initial_metadata) {
const ClientMetadata& client_initial_metadata) {
// No path configured meaning all paths match
if (configured_path.empty()) {
return true;
}
// Check to see if the configured path matches the request path.
Slice* path_slice = client_initial_metadata->get_pointer(HttpPathMetadata());
const Slice* path_slice =
client_initial_metadata.get_pointer(HttpPathMetadata());
GPR_ASSERT(path_slice != nullptr);
absl::string_view path = path_slice->as_string_view();
// Matching criteria from
@ -218,9 +221,8 @@ bool IsConfiguredPath(absl::string_view configured_path,
}
} // namespace
// Construct a promise for one call.
ArenaPromise<ServerMetadataHandle> StatefulSessionFilter::MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) {
void StatefulSessionFilter::Call::OnClientInitialMetadata(
ClientMetadata& md, StatefulSessionFilter* filter) {
// Get config.
auto* service_config_call_data = static_cast<ServiceConfigCallData*>(
GetContext<
@ -229,62 +231,57 @@ ArenaPromise<ServerMetadataHandle> StatefulSessionFilter::MakeCallPromise(
GPR_ASSERT(service_config_call_data != nullptr);
auto* method_params = static_cast<StatefulSessionMethodParsedConfig*>(
service_config_call_data->GetMethodParsedConfig(
service_config_parser_index_));
filter->service_config_parser_index_));
GPR_ASSERT(method_params != nullptr);
auto* cookie_config = method_params->GetConfig(index_);
GPR_ASSERT(cookie_config != nullptr);
if (!cookie_config->name.has_value() ||
!IsConfiguredPath(cookie_config->path,
call_args.client_initial_metadata)) {
return next_promise_factory(std::move(call_args));
cookie_config_ = method_params->GetConfig(filter->index_);
GPR_ASSERT(cookie_config_ != nullptr);
if (!cookie_config_->name.has_value() ||
!IsConfiguredPath(cookie_config_->path, md)) {
return;
}
// Base64-decode cookie value.
std::string cookie_value =
GetCookieValue(call_args.client_initial_metadata, *cookie_config->name);
std::string cookie_value = GetCookieValue(md, *cookie_config_->name);
// Cookie format is "host;cluster"
std::pair<absl::string_view, absl::string_view> host_cluster =
absl::StrSplit(cookie_value, absl::MaxSplits(';', 1));
absl::string_view cookie_address_list;
// Allocate the string on the arena, so that it has the right lifetime.
if (!host_cluster.first.empty()) {
cookie_address_list = AllocateStringOnArena(host_cluster.first);
cookie_address_list_ = AllocateStringOnArena(host_cluster.first);
}
// Set override host attribute.
auto* override_host_attribute =
override_host_attribute_ =
GetContext<Arena>()->ManagedNew<XdsOverrideHostAttribute>(
cookie_address_list);
service_config_call_data->SetCallAttribute(override_host_attribute);
cookie_address_list_);
service_config_call_data->SetCallAttribute(override_host_attribute_);
// Check if the cluster override is valid, and apply it if necessary.
// Note that cluster_name will point to an arena-allocated string
// that will still be alive when we see the server initial metadata.
// If the cluster name is empty, that means we cannot use a
// cluster override (i.e., the route uses a cluster specifier plugin).
absl::string_view cluster_name =
cluster_name_ =
GetClusterToUse(host_cluster.second, service_config_call_data);
bool cluster_changed = cluster_name != host_cluster.second;
// Intercept server initial metadata.
call_args.server_initial_metadata->InterceptAndMap(
[cookie_config, cluster_changed, cluster_name, cookie_address_list,
override_host_attribute](ServerMetadataHandle md) {
// Add cookie to server initial metadata if needed.
MaybeUpdateServerInitialMetadata(cookie_config, cluster_changed,
cluster_name, cookie_address_list,
override_host_attribute, md.get());
return md;
});
return Map(next_promise_factory(std::move(call_args)),
[cookie_config, cluster_changed, cluster_name, cookie_address_list,
override_host_attribute](ServerMetadataHandle md) {
// If we got a Trailers-Only response, then add the
// cookie to the trailing metadata instead of the
// initial metadata.
if (md->get(GrpcTrailersOnly()).value_or(false)) {
MaybeUpdateServerInitialMetadata(
cookie_config, cluster_changed, cluster_name,
cookie_address_list, override_host_attribute, md.get());
}
return md;
});
cluster_changed_ = cluster_name_ != host_cluster.second;
perform_filtering_ = true;
}
void StatefulSessionFilter::Call::OnServerInitialMetadata(ServerMetadata& md) {
if (!perform_filtering_) return;
// Add cookie to server initial metadata if needed.
MaybeUpdateServerInitialMetadata(cookie_config_, cluster_changed_,
cluster_name_, cookie_address_list_,
override_host_attribute_, md);
}
void StatefulSessionFilter::Call::OnServerTrailingMetadata(ServerMetadata& md) {
if (!perform_filtering_) return;
// If we got a Trailers-Only response, then add the
// cookie to the trailing metadata instead of the
// initial metadata.
if (md.get(GrpcTrailersOnly()).value_or(false)) {
MaybeUpdateServerInitialMetadata(cookie_config_, cluster_changed_,
cluster_name_, cookie_address_list_,
override_host_attribute_, md);
}
}
void StatefulSessionFilterRegister(CoreConfiguration::Builder* builder) {

@ -26,6 +26,7 @@
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "src/core/ext/filters/stateful_session/stateful_session_service_config_parser.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/channel/promise_based_filter.h"
@ -68,16 +69,32 @@ class XdsOverrideHostAttribute
};
// A filter to provide cookie-based stateful session affinity.
class StatefulSessionFilter : public ChannelFilter {
class StatefulSessionFilter
: public ImplementChannelFilter<StatefulSessionFilter> {
public:
static const grpc_channel_filter kFilter;
static absl::StatusOr<StatefulSessionFilter> Create(
const ChannelArgs& args, ChannelFilter::Args filter_args);
// Construct a promise for one call.
ArenaPromise<ServerMetadataHandle> MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) override;
class Call {
public:
void OnClientInitialMetadata(ClientMetadata& md,
StatefulSessionFilter* filter);
void OnServerInitialMetadata(ServerMetadata& md);
void OnServerTrailingMetadata(ServerMetadata& md);
static const NoInterceptor OnClientToServerMessage;
static const NoInterceptor OnServerToClientMessage;
static const NoInterceptor OnFinalize;
private:
const StatefulSessionMethodParsedConfig::CookieConfig* cookie_config_;
XdsOverrideHostAttribute* override_host_attribute_;
absl::string_view cluster_name_;
absl::string_view cookie_address_list_;
bool cluster_changed_;
bool perform_filtering_ = false;
};
private:
explicit StatefulSessionFilter(ChannelFilter::Args filter_args);

@ -4072,8 +4072,7 @@ RefCountedPtr<CallSpineInterface> MakeServerCall(Server* server,
return RefCountedPtr<ServerCallSpine>(call);
}
#else
RefCountedPtr<CallSpineInterface> MakeServerCall(Server* server,
Channel* channel) {
RefCountedPtr<CallSpineInterface> MakeServerCall(Server*, Channel*) {
Crash("not implemented");
}
#endif

@ -269,13 +269,14 @@ static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8,
X509_NAME* subject_name = X509_get_subject_name(cert);
int utf8_returned_size = 0;
if (subject_name == nullptr) {
gpr_log(GPR_INFO, "Could not get subject name from certificate.");
gpr_log(GPR_DEBUG, "Could not get subject name from certificate.");
return TSI_NOT_FOUND;
}
common_name_index =
X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
if (common_name_index == -1) {
gpr_log(GPR_INFO, "Could not get common name of subject from certificate.");
gpr_log(GPR_DEBUG,
"Could not get common name of subject from certificate.");
return TSI_NOT_FOUND;
}
common_name_entry = X509_NAME_get_entry(subject_name, common_name_index);

@ -47,20 +47,18 @@ DOCKERIMAGE_CURRENT_VERSIONS = {
"tools/dockerfile/distribtest/python_dev_buster_x86.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_dev_buster_x86@sha256:179146fd5d5cc15846c6bf0284c2e261f383caf944559d2d9f7a5af0e0f7152d",
"tools/dockerfile/distribtest/python_dev_centos7_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_dev_centos7_x64@sha256:e6e9a1b23a0a543050db91e17d621aa899bad04308adaf961c11fa88ba941a95",
"tools/dockerfile/distribtest/python_dev_fedora36_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_dev_fedora36_x64@sha256:d10ea0c54ecaa861b67942b4adc69178585cd071c9d0c8997fa274a362beea55",
"tools/dockerfile/distribtest/python_dev_ubuntu1804_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_dev_ubuntu1804_x64@sha256:157a89cd6d0e69b89ac1975e0314aade556a35aafbaa5fe9f9890f90321d6c89",
"tools/dockerfile/distribtest/python_dev_ubuntu2004_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_dev_ubuntu2004_x64@sha256:91f0d88c43ec52ecd63f99acb424c88ff9a67fa046fae207a75e99bee37eef11",
"tools/dockerfile/distribtest/python_dev_ubuntu2204_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_dev_ubuntu2204_x64@sha256:9e6c9ddc738afcd73fcf2de27b22fdc22a74f1e90e214345838373d9c65ea215",
"tools/dockerfile/distribtest/python_fedora36_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_fedora36_x64@sha256:85b2d2fbbcfc1b995ce3916dcf8240c29dbc72f91bd47f04187c2db008570ba4",
"tools/dockerfile/distribtest/python_opensuse_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_opensuse_x64@sha256:da52566b078d10e537aa219e59641731a57e5dc7d17d6737f5e5a7d447acf5cc",
"tools/dockerfile/distribtest/python_python38_buster_aarch64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_python38_buster_aarch64@sha256:487b9af2ad1459ee2630694e61074d4ac525d4f90b2bdb026dbf6f77fb3e9878",
"tools/dockerfile/distribtest/python_ubuntu1804_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_ubuntu1804_x64@sha256:edcd5f342d77ad9129cc0a0e6988b47b144815e7a93091d5b45e850111eefbcf",
"tools/dockerfile/distribtest/python_ubuntu2004_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_ubuntu2004_x64@sha256:342e9dc23b674ad256b220745745be818708a1baa25a2690f0d4f777e28a22a3",
"tools/dockerfile/distribtest/python_ubuntu2204_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/python_ubuntu2204_x64@sha256:b6ca497348741615406d1d571cf5042008da934c4f708877aa06a66b5dc3036c",
"tools/dockerfile/distribtest/ruby_centos7_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_centos7_x64@sha256:4d529b984b78ca179086f7f9b416605e2d9a96ca0a28a71f4421bb5ffdc18f96",
"tools/dockerfile/distribtest/ruby_debian10_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_debian10_x64@sha256:1298c39c950b2a48261555b6cff1ae66230a5020f100d3b381759285f0caf84e",
"tools/dockerfile/distribtest/ruby_debian10_x64_ruby_2_7.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_debian10_x64_ruby_2_7@sha256:5ee26ad3abe2683c9a8ee03987ab0ae63f50793c3d3f5e4be6e6cbacb4556fcf",
"tools/dockerfile/distribtest/ruby_debian10_x64_ruby_3_0.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_debian10_x64_ruby_3_0@sha256:9190da90a2a95eca1370cef64dcba7ddee9f59cc7487093da6711c1280a0b0f9",
"tools/dockerfile/distribtest/ruby_ubuntu1804_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_ubuntu1804_x64@sha256:d38b3dd34cffc027e9a1bf82bc7ace75b8a9829c2d04d5cf7cc8323655edd27a",
"tools/dockerfile/distribtest/ruby_ubuntu2004_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_ubuntu2004_x64@sha256:426cbf625df0c0e7451b9716041996dc6a35a3788c1a24d68891256f84733d8e",
"tools/dockerfile/distribtest/ruby_ubuntu2204_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_ubuntu2204_x64@sha256:1c74c312f8a4ab37e629732a35daa3056e12136b90f37540cdf9fa11303c7eb8",
"tools/dockerfile/grpc_artifact_centos6_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/grpc_artifact_centos6_x64@sha256:3285047265ea2b7c5d4df4c769b2d05f56288d947c75e16d27ae2dee693f791b",
"tools/dockerfile/grpc_artifact_centos6_x86.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/grpc_artifact_centos6_x86@sha256:19783239da92208f0f39cf563529cd02e889920497ef81c60d20391fa998af62",

@ -1 +0,0 @@
us-docker.pkg.dev/grpc-testing/testing-images-public/python_dev_ubuntu1804_x64:483ff054a378bc704ae38ff1e1713947472c60d6@sha256:157a89cd6d0e69b89ac1975e0314aade556a35aafbaa5fe9f9890f90321d6c89

@ -1,22 +0,0 @@
# Copyright 2020 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.
FROM ubuntu:18.04
RUN apt-get update -y && apt-get install -y python3 python3-pip
RUN apt-get install -y build-essential
RUN apt-get install -y python3-dev
RUN python3 -m pip install virtualenv

@ -1 +0,0 @@
us-docker.pkg.dev/grpc-testing/testing-images-public/python_ubuntu1804_x64:ee3ea8950f46d21ef06d3848294ae518c68f144f@sha256:edcd5f342d77ad9129cc0a0e6988b47b144815e7a93091d5b45e850111eefbcf

@ -1,19 +0,0 @@
# Copyright 2020 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.
FROM ubuntu:18.04
RUN apt-get update -y && apt-get install -y python3 python3-pip
RUN python3 -m pip install virtualenv

@ -1 +0,0 @@
us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_ubuntu1804_x64:aca247e97f04a9cd5922a310337a4b5ee646fb9d@sha256:d38b3dd34cffc027e9a1bf82bc7ace75b8a9829c2d04d5cf7cc8323655edd27a

@ -0,0 +1 @@
us-docker.pkg.dev/grpc-testing/testing-images-public/ruby_ubuntu2004_x64:41b5e3380e01ef6687e29071fedc6d9b90d96d09@sha256:426cbf625df0c0e7451b9716041996dc6a35a3788c1a24d68891256f84733d8e

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM ubuntu:18.04
FROM ubuntu:20.04
# Install Git and basic packages.
RUN apt-get update -y && apt-get install -y \
@ -30,4 +30,6 @@ RUN /bin/bash -l -c "rvm use --default ruby-2.7"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.7' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-document"
# TODO(apolcyn): Bundler v2.4.22 is the last to support ruby 2.7. Latest bundler
# requires ruby 3.
RUN /bin/bash -l -c "gem install bundler --no-document -v 2.4.22"

@ -30,4 +30,4 @@ cd /var/local/git/grpc
rvm --default use ruby-2.7
# build Ruby interop client and server
(cd src/ruby && gem install bundler && bundle && bundle exec rake compile)
(cd src/ruby && gem install bundler -v 2.4.22 && bundle && bundle exec rake compile)

@ -37,7 +37,7 @@ gcloud compute instances create "$INSTANCE_NAME" \
--zone "$ZONE" \
--machine-type $MACHINE_TYPE \
--image-project ubuntu-os-cloud \
--image-family ubuntu-1804-lts \
--image-family ubuntu-2004-lts \
--boot-disk-size 300 \
--scopes https://www.googleapis.com/auth/bigquery \
--tags=allow-ssh

@ -117,7 +117,7 @@ sudo apt-get update
sudo apt-get install -y mono-devel
# C# .NET Core dependencies (https://www.microsoft.com/net/download)
wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
wget -q https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get install -y apt-transport-https

@ -477,7 +477,7 @@ def targets():
"linux", "x64", "debian10", ruby_version="ruby_3_0", presubmit=True
),
RubyDistribTest("linux", "x64", "centos7"),
RubyDistribTest("linux", "x64", "ubuntu1804"),
RubyDistribTest("linux", "x64", "ubuntu2004"),
RubyDistribTest("linux", "x64", "ubuntu2204", presubmit=True),
# PHP7
PHP7DistribTest("linux", "x64", "debian10", presubmit=True),

@ -124,9 +124,9 @@ if [[ "$(inside_venv)" ]]; then
else
# Instantiate the virtualenv from the Python version passed in.
$PYTHON -m pip install --user virtualenv==20.25.0
# Use --no-seed to prevent virtualenv from installing seed packages.
# Otherwise it might not find cython module while building grpcio.
$PYTHON -m virtualenv --no-seed "$VENV"
# Skip wheel and setuptools and manually install later. Otherwise we might
# not find cython module while building grpcio.
$PYTHON -m virtualenv --no-wheel --no-setuptools "$VENV"
VENV_PYTHON="$(pwd)/$VENV/$VENV_RELATIVE_PYTHON"
fi
@ -134,7 +134,7 @@ pip_install() {
$VENV_PYTHON -m pip install "$@"
}
$VENV_PYTHON -m ensurepip --upgrade
pip_install --upgrade pip
pip_install --upgrade wheel
pip_install --upgrade setuptools==66.1.0

@ -29,10 +29,12 @@ gcp_utils_dir = os.path.abspath(
sys.path.append(gcp_utils_dir)
import big_query_utils
_PROJECT_ID = "grpc-testing"
_DEFAULT_PROJECT_ID = "grpc-testing"
def _upload_netperf_latency_csv_to_bigquery(dataset_id, table_id, result_file):
def _upload_netperf_latency_csv_to_bigquery(
project_id, dataset_id, table_id, result_file
):
with open(result_file, "r") as f:
(col1, col2, col3) = f.read().split(",")
latency50 = float(col1.strip()) * 1000
@ -52,13 +54,14 @@ def _upload_netperf_latency_csv_to_bigquery(dataset_id, table_id, result_file):
_create_results_table(bq, dataset_id, table_id)
if not _insert_result(
bq, dataset_id, table_id, scenario_result, flatten=False
bq, project_id, dataset_id, table_id, scenario_result, flatten=False
):
print("Error uploading result to bigquery.")
sys.exit(1)
def _upload_scenario_result_to_bigquery(
project_id,
dataset_id,
table_id,
result_file,
@ -74,6 +77,7 @@ def _upload_scenario_result_to_bigquery(
if not _insert_scenario_result(
bq,
project_id,
dataset_id,
table_id,
scenario_result,
@ -85,18 +89,21 @@ def _upload_scenario_result_to_bigquery(
sys.exit(1)
def _insert_result(bq, dataset_id, table_id, scenario_result, flatten=True):
def _insert_result(
bq, project_id, dataset_id, table_id, scenario_result, flatten=True
):
if flatten:
_flatten_result_inplace(scenario_result)
_populate_metadata_inplace(scenario_result)
row = big_query_utils.make_row(str(uuid.uuid4()), scenario_result)
return big_query_utils.insert_rows(
bq, _PROJECT_ID, dataset_id, table_id, [row]
bq, project_id, dataset_id, table_id, [row]
)
def _insert_scenario_result(
bq,
project_id,
dataset_id,
table_id,
scenario_result,
@ -114,18 +121,18 @@ def _insert_scenario_result(
)
row = big_query_utils.make_row(str(uuid.uuid4()), scenario_result)
return big_query_utils.insert_rows(
bq, _PROJECT_ID, dataset_id, table_id, [row]
bq, project_id, dataset_id, table_id, [row]
)
def _create_results_table(bq, dataset_id, table_id):
def _create_results_table(bq, project_id, dataset_id, table_id):
with open(
os.path.dirname(__file__) + "/scenario_result_schema.json", "r"
) as f:
table_schema = json.loads(f.read())
desc = "Results of performance benchmarks."
return big_query_utils.create_table2(
bq, _PROJECT_ID, dataset_id, table_id, table_schema, desc
bq, project_id, dataset_id, table_id, table_schema, desc
)
@ -333,7 +340,7 @@ argp.add_argument(
required=True,
default=None,
type=str,
help='Bigquery "dataset.table" to upload results to.',
help='Bigquery "dataset.table" or "project.dataset.table" to upload results to. The default project is "grpc-testing".',
)
argp.add_argument(
"--file_to_upload",
@ -368,14 +375,25 @@ argp.add_argument(
args = argp.parse_args()
dataset_id, table_id = args.bq_result_table.split(".", 2)
bq_words = args.bq_result_table.split(".", 2)
if len(bq_words) == 3:
project_id, dataset_id, table_id = bq_words
elif len(bq_words) == 2:
project_id = _DEFAULT_PROJECT_ID
dataset_id, table_id = bq_words
else:
print(
"BigQuery table must be in the format dataset.table or project.dataset.table."
)
sys.exit(1)
if args.file_format == "netperf_latency_csv":
_upload_netperf_latency_csv_to_bigquery(
dataset_id, table_id, args.file_to_upload
project_id, dataset_id, table_id, args.file_to_upload
)
else:
_upload_scenario_result_to_bigquery(
project_id,
dataset_id,
table_id,
args.file_to_upload,

@ -115,6 +115,7 @@ class GammaServerRunner(KubernetesServerRunner):
log_to_stdout: bool = False,
bootstrap_version: Optional[str] = None,
route_template: str = "gamma/route_http.yaml",
enable_csm_observability: bool = False,
) -> List[XdsTestServer]:
if not maintenance_port:
maintenance_port = self._get_default_maintenance_port(secure_mode)
@ -206,6 +207,7 @@ class GammaServerRunner(KubernetesServerRunner):
bootstrap_version=bootstrap_version,
termination_grace_period_seconds=self.termination_grace_period_seconds,
pre_stop_hook=self.pre_stop_hook,
enable_csm_observability=enable_csm_observability,
)
servers = self._make_servers_for_deployment(

@ -299,6 +299,34 @@ class KubernetesBaseRunner(base_runner.BaseRunner, metaclass=ABCMeta):
logger.info("Reusing namespace: %s", self.k8s_namespace.name)
return self.k8s_namespace.get()
def _create_pod_monitoring(self, template, **kwargs) -> None:
if not kwargs["namespace_name"]:
raise _RunnerError(
"namespace_name required to create PodMonitoring resource"
)
if not kwargs["deployment_id"]:
raise _RunnerError(
"deployment_id required to create PodMonitoring resource"
)
if not kwargs["pod_monitoring_name"]:
raise _RunnerError(
"pod_monitoring_name required to create PodMonitoring resource"
)
pod_monitoring = self._create_from_template(
template, custom_object=True, **kwargs
)
if pod_monitoring.metadata.namespace != kwargs["namespace_name"]:
raise _RunnerError(
"PodMonitoring resource created with unexpected namespace: "
f"{pod_monitoring.metadata.namespace}"
)
logger.debug(
"PodMonitoring %s created at %s",
pod_monitoring.metadata.name,
pod_monitoring.metadata.creation_timestamp,
)
return pod_monitoring
def _create_namespace(self, template, **kwargs) -> k8s.V1Namespace:
namespace = self._create_from_template(template, **kwargs)
if not isinstance(namespace, k8s.V1Namespace):

@ -104,6 +104,7 @@ class KubernetesClientRunner(k8s_base_runner.KubernetesBaseRunner):
generate_mesh_id=False,
print_response=False,
log_to_stdout: bool = False,
enable_csm_observability: bool = False,
) -> XdsTestClient:
logger.info(
(
@ -158,8 +159,19 @@ class KubernetesClientRunner(k8s_base_runner.KubernetesBaseRunner):
config_mesh=config_mesh,
generate_mesh_id=generate_mesh_id,
print_response=print_response,
enable_csm_observability=enable_csm_observability,
)
# Create a PodMonitoring resource if CSM Observability is enabled
# This is GMP (Google Managed Prometheus)
if enable_csm_observability:
self._create_pod_monitoring(
"csm/pod-monitoring.yaml",
namespace_name=self.k8s_namespace.name,
deployment_id=self.deployment_id,
pod_monitoring_name="%s-gmp" % self.deployment_id,
)
# Load test client pod. We need only one client at the moment
pod_name = self._wait_deployment_pod_count(self.deployment)[0]
pod: k8s.V1Pod = self._wait_pod_started(pod_name)

@ -42,6 +42,9 @@ spec:
- "--rpc=${rpc}"
- "--metadata=${metadata}"
- "--print_response=${print_response}"
% if enable_csm_observability:
- "--enable_csm_observability"
% endif
ports:
- containerPort: ${stats_port}
env:

@ -3,7 +3,9 @@ apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
namespace: ${namespace_name}
name: ${deployment_id}-gmp
name: ${pod_monitoring_name}
labels:
owner: xds-k8s-interop-test
spec:
selector:
matchLabels:

@ -40,6 +40,9 @@ spec:
failureThreshold: 1000
args:
- "--port=${test_port}"
% if enable_csm_observability:
- "--enable_csm_observability"
% endif
ports:
- containerPort: ${test_port}
env:

@ -0,0 +1,48 @@
# Copyright 2023 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.
import logging
from absl import flags
from absl.testing import absltest
from framework import xds_gamma_testcase
from framework import xds_k8s_testcase
logger = logging.getLogger(__name__)
flags.adopt_module_key_flags(xds_k8s_testcase)
_XdsTestServer = xds_k8s_testcase.XdsTestServer
_XdsTestClient = xds_k8s_testcase.XdsTestClient
class CsmObservabilityTest(xds_gamma_testcase.GammaXdsKubernetesTestCase):
def test_ping_pong(self):
# TODO(sergiitk): [GAMMA] Consider moving out custom gamma
# resource creation out of self.startTestServers()
with self.subTest("1_run_test_server"):
test_server: _XdsTestServer = self.startTestServers(
enable_csm_observability=True
)[0]
with self.subTest("2_start_test_client"):
test_client: _XdsTestClient = self.startTestClient(
test_server, enable_csm_observability=True
)
with self.subTest("3_test_server_received_rpcs_from_test_client"):
self.assertSuccessfulRpcs(test_client)
if __name__ == "__main__":
absltest.main()
Loading…
Cancel
Save