diff --git a/BUILD b/BUILD
index b3c97ca5e2a..4fc1091b635 100644
--- a/BUILD
+++ b/BUILD
@@ -956,6 +956,7 @@ grpc_cc_library(
external_deps = [
"madler_zlib",
"absl/container:inlined_vector",
+ "absl/status",
"absl/types:optional",
],
language = "c++",
diff --git a/BUILD.gn b/BUILD.gn
index 035d6bddde6..b38ffc2301b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -991,6 +991,7 @@ config("grpc_config") {
":upb",
":absl/types:optional",
":absl/strings:strings",
+ ":absl/status:status",
":absl/container:inlined_vector",
"//third_party/cares",
":address_sorting",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce8a7e338c0..d7fb543e242 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -111,23 +111,32 @@ set(gRPC_ABSL_USED_TARGETS
absl_civil_time
absl_compressed_tuple
absl_config
+ absl_cord
absl_core_headers
+ absl_debugging_internal
+ absl_demangle_internal
absl_dynamic_annotations
absl_endian
absl_errno_saver
+ absl_fixed_array
+ absl_function_ref
absl_inlined_vector
absl_inlined_vector_internal
absl_int128
absl_log_severity
+ absl_malloc_internal
absl_memory
absl_optional
absl_raw_logging_internal
absl_span
absl_spinlock_wait
+ absl_stacktrace
+ absl_status
absl_str_format
absl_str_format_internal
absl_strings
absl_strings_internal
+ absl_symbolize
absl_throw_delegate
absl_time
absl_time_zone
@@ -1793,6 +1802,7 @@ target_link_libraries(grpc
upb
absl::optional
absl::strings
+ absl::status
absl::inlined_vector
)
if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
@@ -2395,6 +2405,7 @@ target_link_libraries(grpc_unsecure
upb
absl::optional
absl::strings
+ absl::status
absl::inlined_vector
)
if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
@@ -15546,7 +15557,7 @@ generate_pkgconfig(
"high performance general RPC framework"
"${gRPC_CORE_VERSION}"
"gpr openssl"
- "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
+ "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
""
"grpc.pc")
@@ -15556,7 +15567,7 @@ generate_pkgconfig(
"high performance general RPC framework without SSL"
"${gRPC_CORE_VERSION}"
"gpr"
- "-lgrpc_unsecure -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
+ "-lgrpc_unsecure -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
""
"grpc_unsecure.pc")
@@ -15566,7 +15577,7 @@ generate_pkgconfig(
"C++ wrapper for gRPC"
"${gRPC_CPP_VERSION}"
"grpc"
- "-lgrpc++ -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
+ "-lgrpc++ -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
""
"grpc++.pc")
@@ -15576,6 +15587,6 @@ generate_pkgconfig(
"C++ wrapper for gRPC without SSL"
"${gRPC_CPP_VERSION}"
"grpc_unsecure"
- "-lgrpc++_unsecure -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
+ "-lgrpc++_unsecure -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
""
"grpc++_unsecure.pc")
diff --git a/Makefile b/Makefile
index b86df824e22..fcb70c554dc 100644
--- a/Makefile
+++ b/Makefile
@@ -6236,6 +6236,7 @@ endif
LIBGRPC_ABSEIL_SRC = \
third_party/abseil-cpp/absl/base/dynamic_annotations.cc \
third_party/abseil-cpp/absl/base/internal/cycleclock.cc \
+ third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc \
third_party/abseil-cpp/absl/base/internal/raw_logging.cc \
third_party/abseil-cpp/absl/base/internal/spinlock.cc \
third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc \
@@ -6244,9 +6245,18 @@ LIBGRPC_ABSEIL_SRC = \
third_party/abseil-cpp/absl/base/internal/throw_delegate.cc \
third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc \
third_party/abseil-cpp/absl/base/log_severity.cc \
+ third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc \
+ third_party/abseil-cpp/absl/debugging/internal/demangle.cc \
+ third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc \
+ third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc \
+ third_party/abseil-cpp/absl/debugging/stacktrace.cc \
+ third_party/abseil-cpp/absl/debugging/symbolize.cc \
third_party/abseil-cpp/absl/numeric/int128.cc \
+ third_party/abseil-cpp/absl/status/status.cc \
+ third_party/abseil-cpp/absl/status/status_payload_printer.cc \
third_party/abseil-cpp/absl/strings/ascii.cc \
third_party/abseil-cpp/absl/strings/charconv.cc \
+ third_party/abseil-cpp/absl/strings/cord.cc \
third_party/abseil-cpp/absl/strings/escaping.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \
diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml
index 23a3e3c0554..8720ff88b96 100644
--- a/build_autogenerated.yaml
+++ b/build_autogenerated.yaml
@@ -1163,6 +1163,7 @@ libs:
- upb
- absl/types:optional
- absl/strings:strings
+ - absl/status:status
- absl/container:inlined_vector
baselib: true
deps_linkage: static
@@ -1952,6 +1953,7 @@ libs:
- upb
- absl/types:optional
- absl/strings:strings
+ - absl/status:status
- absl/container:inlined_vector
baselib: true
deps_linkage: static
diff --git a/config.m4 b/config.m4
index 8cf43fc8a52..bc75131dc70 100644
--- a/config.m4
+++ b/config.m4
@@ -509,6 +509,7 @@ if test "$PHP_GRPC" != "no"; then
src/php/ext/grpc/timeval.c \
third_party/abseil-cpp/absl/base/dynamic_annotations.cc \
third_party/abseil-cpp/absl/base/internal/cycleclock.cc \
+ third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc \
third_party/abseil-cpp/absl/base/internal/raw_logging.cc \
third_party/abseil-cpp/absl/base/internal/spinlock.cc \
third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc \
@@ -517,9 +518,18 @@ if test "$PHP_GRPC" != "no"; then
third_party/abseil-cpp/absl/base/internal/throw_delegate.cc \
third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc \
third_party/abseil-cpp/absl/base/log_severity.cc \
+ third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc \
+ third_party/abseil-cpp/absl/debugging/internal/demangle.cc \
+ third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc \
+ third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc \
+ third_party/abseil-cpp/absl/debugging/stacktrace.cc \
+ third_party/abseil-cpp/absl/debugging/symbolize.cc \
third_party/abseil-cpp/absl/numeric/int128.cc \
+ third_party/abseil-cpp/absl/status/status.cc \
+ third_party/abseil-cpp/absl/status/status_payload_printer.cc \
third_party/abseil-cpp/absl/strings/ascii.cc \
third_party/abseil-cpp/absl/strings/charconv.cc \
+ third_party/abseil-cpp/absl/strings/cord.cc \
third_party/abseil-cpp/absl/strings/escaping.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \
@@ -971,7 +981,10 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/base)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/base/internal)
+ PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/debugging)
+ PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/debugging/internal)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/numeric)
+ PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/status)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings/internal)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings/internal/str_format)
diff --git a/config.w32 b/config.w32
index 8f027adf682..de58a2c5bea 100644
--- a/config.w32
+++ b/config.w32
@@ -477,6 +477,7 @@ if (PHP_GRPC != "no") {
"src\\php\\ext\\grpc\\timeval.c " +
"third_party\\abseil-cpp\\absl\\base\\dynamic_annotations.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\cycleclock.cc " +
+ "third_party\\abseil-cpp\\absl\\base\\internal\\low_level_alloc.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\raw_logging.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\spinlock.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\spinlock_wait.cc " +
@@ -485,9 +486,18 @@ if (PHP_GRPC != "no") {
"third_party\\abseil-cpp\\absl\\base\\internal\\throw_delegate.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\unscaledcycleclock.cc " +
"third_party\\abseil-cpp\\absl\\base\\log_severity.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\internal\\address_is_readable.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\internal\\demangle.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\internal\\elf_mem_image.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\internal\\vdso_support.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\stacktrace.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\symbolize.cc " +
"third_party\\abseil-cpp\\absl\\numeric\\int128.cc " +
+ "third_party\\abseil-cpp\\absl\\status\\status.cc " +
+ "third_party\\abseil-cpp\\absl\\status\\status_payload_printer.cc " +
"third_party\\abseil-cpp\\absl\\strings\\ascii.cc " +
"third_party\\abseil-cpp\\absl\\strings\\charconv.cc " +
+ "third_party\\abseil-cpp\\absl\\strings\\cord.cc " +
"third_party\\abseil-cpp\\absl\\strings\\escaping.cc " +
"third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_bigint.cc " +
"third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_parse.cc " +
@@ -1007,7 +1017,10 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\base");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\base\\internal");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\debugging");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\debugging\\internal");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\numeric");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\status");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings\\internal");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings\\internal\\str_format");
diff --git a/doc/python/sphinx/grpc.rst b/doc/python/sphinx/grpc.rst
index 4717eb12332..819e2e2f9e4 100644
--- a/doc/python/sphinx/grpc.rst
+++ b/doc/python/sphinx/grpc.rst
@@ -41,6 +41,7 @@ Create Client Credentials
.. autofunction:: composite_call_credentials
.. autofunction:: composite_channel_credentials
.. autofunction:: local_channel_credentials(local_connect_type=grpc.LocalConnectionType.LOCAL_TCP)
+.. autofunction:: compute_engine_channel_credentials
Create Server
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index a0844acf9a9..c74f5fa8e95 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -210,6 +210,7 @@ Pod::Spec.new do |s|
abseil_version = '1.20200225.0'
ss.dependency 'abseil/container/inlined_vector', abseil_version
ss.dependency 'abseil/memory/memory', abseil_version
+ ss.dependency 'abseil/status/status', abseil_version
ss.dependency 'abseil/strings/str_format', abseil_version
ss.dependency 'abseil/strings/strings', abseil_version
ss.dependency 'abseil/time/time', abseil_version
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 9ac673e2c3d..869def405bb 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -176,6 +176,7 @@ Pod::Spec.new do |s|
abseil_version = '1.20200225.0'
ss.dependency 'abseil/container/inlined_vector', abseil_version
ss.dependency 'abseil/memory/memory', abseil_version
+ ss.dependency 'abseil/status/status', abseil_version
ss.dependency 'abseil/strings/str_format', abseil_version
ss.dependency 'abseil/strings/strings', abseil_version
ss.dependency 'abseil/time/time', abseil_version
diff --git a/grpc.def b/grpc.def
index ad0dca2f0d4..e451ad5bc1d 100644
--- a/grpc.def
+++ b/grpc.def
@@ -97,12 +97,12 @@ EXPORTS
grpc_ssl_session_cache_create_lru
grpc_ssl_session_cache_destroy
grpc_ssl_session_cache_create_channel_arg
+ grpc_call_credentials_release
grpc_channel_credentials_release
grpc_google_default_credentials_create
grpc_set_ssl_roots_override_callback
grpc_ssl_credentials_create
grpc_ssl_credentials_create_ex
- grpc_call_credentials_release
grpc_composite_channel_credentials_create
grpc_composite_call_credentials_create
grpc_google_compute_engine_credentials_create
diff --git a/grpc.gemspec b/grpc.gemspec
index 5b84d4ecf26..157b8dc766c 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -969,12 +969,15 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/base/internal/bits.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.cc )
s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.h )
+ s.files += %w( third_party/abseil-cpp/absl/base/internal/direct_mmap.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/endian.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/errno_saver.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/hide_ptr.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/identity.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/inline_variable.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/invoke.h )
+ s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc )
+ s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_alloc.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/per_thread_tls.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/raw_logging.cc )
@@ -1007,19 +1010,52 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/base/policy_checks.h )
s.files += %w( third_party/abseil-cpp/absl/base/port.h )
s.files += %w( third_party/abseil-cpp/absl/base/thread_annotations.h )
+ s.files += %w( third_party/abseil-cpp/absl/container/fixed_array.h )
s.files += %w( third_party/abseil-cpp/absl/container/inlined_vector.h )
s.files += %w( third_party/abseil-cpp/absl/container/internal/compressed_tuple.h )
s.files += %w( third_party/abseil-cpp/absl/container/internal/inlined_vector.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/address_is_readable.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/demangle.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/demangle.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/symbolize.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/vdso_support.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/stacktrace.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/stacktrace.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize_elf.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize_unimplemented.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize_win32.inc )
+ s.files += %w( third_party/abseil-cpp/absl/functional/function_ref.h )
+ s.files += %w( third_party/abseil-cpp/absl/functional/internal/function_ref.h )
s.files += %w( third_party/abseil-cpp/absl/memory/memory.h )
s.files += %w( third_party/abseil-cpp/absl/meta/type_traits.h )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128.cc )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128.h )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc )
+ s.files += %w( third_party/abseil-cpp/absl/status/status.cc )
+ s.files += %w( third_party/abseil-cpp/absl/status/status.h )
+ s.files += %w( third_party/abseil-cpp/absl/status/status_payload_printer.cc )
+ s.files += %w( third_party/abseil-cpp/absl/status/status_payload_printer.h )
s.files += %w( third_party/abseil-cpp/absl/strings/ascii.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/ascii.h )
s.files += %w( third_party/abseil-cpp/absl/strings/charconv.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/charconv.h )
+ s.files += %w( third_party/abseil-cpp/absl/strings/cord.cc )
+ s.files += %w( third_party/abseil-cpp/absl/strings/cord.h )
s.files += %w( third_party/abseil-cpp/absl/strings/escaping.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/escaping.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/char_map.h )
@@ -1027,6 +1063,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.h )
+ s.files += %w( third_party/abseil-cpp/absl/strings/internal/cord_internal.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/memutil.cc )
diff --git a/grpc.gyp b/grpc.gyp
index a7cae5e3f8b..f0ff7c76d25 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -432,6 +432,7 @@
'upb',
'absl/types:optional',
'absl/strings:strings',
+ 'absl/status:status',
'absl/container:inlined_vector',
],
'sources': [
@@ -941,6 +942,7 @@
'upb',
'absl/types:optional',
'absl/strings:strings',
+ 'absl/status:status',
'absl/container:inlined_vector',
],
'sources': [
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 99635ea8807..3ff2e8de2cd 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -119,6 +119,18 @@ GRPCAPI void grpc_ssl_session_cache_destroy(grpc_ssl_session_cache* cache);
GRPCAPI grpc_arg
grpc_ssl_session_cache_create_channel_arg(grpc_ssl_session_cache* cache);
+/** --- grpc_call_credentials object.
+
+ A call credentials object represents a way to authenticate on a particular
+ call. These credentials can be composed with a channel credentials object
+ so that they are sent with every call on this channel. */
+
+typedef struct grpc_call_credentials grpc_call_credentials;
+
+/** Releases a call credentials object.
+ The creator of the credentials object is responsible for its release. */
+GRPCAPI void grpc_call_credentials_release(grpc_call_credentials* creds);
+
/** --- grpc_channel_credentials object. ---
A channel credentials object represents a way to authenticate a client on a
@@ -133,8 +145,23 @@ GRPCAPI void grpc_channel_credentials_release(grpc_channel_credentials* creds);
/** Creates default credentials to connect to a google gRPC service.
WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak. The security level of the
- resulting connection is GRPC_PRIVACY_AND_INTEGRITY. */
-GRPCAPI grpc_channel_credentials* grpc_google_default_credentials_create(void);
+ resulting connection is GRPC_PRIVACY_AND_INTEGRITY.
+
+ If specified, the supplied call credentials object will be attached to the
+ returned channel credentials object. The call_credentials object must remain
+ valid throughout the lifetime of the returned grpc_channel_credentials
+ object. It is expected that the call credentials object was generated
+ according to the Application Default Credentials mechanism and asserts the
+ identity of the default service account of the machine. Supplying any other
+ sort of call credential will result in undefined behavior, up to and
+ including the sudden and unexpected failure of RPCs.
+
+ If nullptr is supplied, the returned channel credentials object will use a
+ call credentials object based on the Application Default Credentials
+ mechanism.
+*/
+GRPCAPI grpc_channel_credentials* grpc_google_default_credentials_create(
+ grpc_call_credentials* call_credentials);
/** Callback for getting the SSL roots override from the application.
In case of success, *pem_roots_certs must be set to a NULL terminated string
@@ -272,24 +299,14 @@ GRPCAPI grpc_channel_credentials* grpc_ssl_credentials_create_ex(
const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
const grpc_ssl_verify_peer_options* verify_options, void* reserved);
-/** --- grpc_call_credentials object.
-
- A call credentials object represents a way to authenticate on a particular
- call. These credentials can be composed with a channel credentials object
- so that they are sent with every call on this channel. */
-
-typedef struct grpc_call_credentials grpc_call_credentials;
-
-/** Releases a call credentials object.
- The creator of the credentials object is responsible for its release. */
-GRPCAPI void grpc_call_credentials_release(grpc_call_credentials* creds);
-
/** Creates a composite channel credentials object. The security level of
* resulting connection is determined by channel_creds. */
GRPCAPI grpc_channel_credentials* grpc_composite_channel_credentials_create(
grpc_channel_credentials* channel_creds, grpc_call_credentials* call_creds,
void* reserved);
+/** --- composite credentials. */
+
/** Creates a composite call credentials object. */
GRPCAPI grpc_call_credentials* grpc_composite_call_credentials_create(
grpc_call_credentials* creds1, grpc_call_credentials* creds2,
diff --git a/package.xml b/package.xml
index 36399edc3e1..2d755e4d7dc 100644
--- a/package.xml
+++ b/package.xml
@@ -971,12 +971,15 @@
+
+
+
@@ -1009,19 +1012,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1029,6 +1065,7 @@
+
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index 2028c8ebb99..1b48d6a4d37 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -214,7 +214,8 @@ class ChannelData {
grpc_closure* on_complete,
bool cancel);
- void Notify(grpc_connectivity_state state) override;
+ void Notify(grpc_connectivity_state state,
+ const absl::Status& /* status */) override;
void Cancel();
@@ -260,7 +261,8 @@ class ChannelData {
~ChannelData();
void UpdateStateAndPickerLocked(
- grpc_connectivity_state state, const char* reason,
+ grpc_connectivity_state state, const absl::Status& status,
+ const char* reason,
std::unique_ptr picker);
void UpdateServiceConfigInDataPlaneLocked(
@@ -1212,7 +1214,7 @@ void ChannelData::ExternalConnectivityWatcher::
}
void ChannelData::ExternalConnectivityWatcher::Notify(
- grpc_connectivity_state state) {
+ grpc_connectivity_state state, const absl::Status& /* status */) {
bool done = false;
if (!done_.CompareExchangeStrong(&done, true, MemoryOrder::RELAXED,
MemoryOrder::RELAXED)) {
@@ -1352,19 +1354,21 @@ class ChannelData::ClientChannelControlHelper
}
void UpdateState(
- grpc_connectivity_state state,
+ grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
grpc_error* disconnect_error = chand_->disconnect_error();
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
const char* extra = disconnect_error == GRPC_ERROR_NONE
? ""
: " (ignoring -- channel shutting down)";
- gpr_log(GPR_INFO, "chand=%p: update: state=%s picker=%p%s", chand_,
- ConnectivityStateName(state), picker.get(), extra);
+ gpr_log(GPR_INFO, "chand=%p: update: state=%s status=(%s) picker=%p%s",
+ chand_, ConnectivityStateName(state), status.ToString().c_str(),
+ picker.get(), extra);
}
// Do update only if not shutting down.
if (disconnect_error == GRPC_ERROR_NONE) {
- chand_->UpdateStateAndPickerLocked(state, "helper", std::move(picker));
+ chand_->UpdateStateAndPickerLocked(state, status, "helper",
+ std::move(picker));
}
}
@@ -1701,7 +1705,8 @@ ChannelData::~ChannelData() {
}
void ChannelData::UpdateStateAndPickerLocked(
- grpc_connectivity_state state, const char* reason,
+ grpc_connectivity_state state, const absl::Status& status,
+ const char* reason,
std::unique_ptr picker) {
// Clean the control plane when entering IDLE.
if (picker_ == nullptr) {
@@ -1711,7 +1716,7 @@ void ChannelData::UpdateStateAndPickerLocked(
received_first_resolver_result_ = false;
}
// Update connectivity state.
- state_tracker_.SetState(state, reason);
+ state_tracker_.SetState(state, status, reason);
if (channelz_node_ != nullptr) {
channelz_node_->SetConnectivityState(state);
channelz_node_->AddTraceEvent(
@@ -1938,8 +1943,8 @@ void ChannelData::StartTransportOpLocked(grpc_transport_op* op) {
static_cast(value) == GRPC_CHANNEL_IDLE) {
if (disconnect_error() == GRPC_ERROR_NONE) {
// Enter IDLE state.
- UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE, "channel entering IDLE",
- nullptr);
+ UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE, absl::Status(),
+ "channel entering IDLE", nullptr);
}
GRPC_ERROR_UNREF(op->disconnect_with_error);
} else {
@@ -1948,7 +1953,7 @@ void ChannelData::StartTransportOpLocked(grpc_transport_op* op) {
GRPC_ERROR_NONE);
disconnect_error_.Store(op->disconnect_with_error, MemoryOrder::RELEASE);
UpdateStateAndPickerLocked(
- GRPC_CHANNEL_SHUTDOWN, "shutdown from API",
+ GRPC_CHANNEL_SHUTDOWN, absl::Status(), "shutdown from API",
absl::make_unique(
GRPC_ERROR_REF(op->disconnect_with_error)));
}
diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc
index e708a59c571..5d65293af29 100644
--- a/src/core/ext/filters/client_channel/health/health_check_client.cc
+++ b/src/core/ext/filters/client_channel/health/health_check_client.cc
@@ -91,7 +91,11 @@ void HealthCheckClient::SetHealthStatusLocked(grpc_connectivity_state state,
gpr_log(GPR_INFO, "HealthCheckClient %p: setting state=%s reason=%s", this,
ConnectivityStateName(state), reason);
}
- if (watcher_ != nullptr) watcher_->Notify(state);
+ if (watcher_ != nullptr)
+ watcher_->Notify(state,
+ state == GRPC_CHANNEL_TRANSIENT_FAILURE
+ ? absl::Status(absl::StatusCode::kUnavailable, reason)
+ : absl::Status());
}
void HealthCheckClient::Orphan() {
diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h
index 6a290a3f51b..81f5bb33b20 100644
--- a/src/core/ext/filters/client_channel/lb_policy.h
+++ b/src/core/ext/filters/client_channel/lb_policy.h
@@ -24,6 +24,7 @@
#include
#include
+#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "src/core/ext/filters/client_channel/server_address.h"
@@ -283,6 +284,7 @@ class LoadBalancingPolicy : public InternallyRefCounted {
/// Sets the connectivity state and returns a new picker to be used
/// by the client channel.
virtual void UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr) = 0;
/// Requests that the resolver re-resolve.
diff --git a/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc b/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
index 8d8003d185a..1464c718602 100644
--- a/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
@@ -45,7 +45,7 @@ class ChildPolicyHandler::Helper
return parent_->channel_control_helper()->CreateSubchannel(args);
}
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
if (parent_->shutting_down_) return;
// If this request is from the pending child policy, ignore it until
@@ -55,8 +55,9 @@ class ChildPolicyHandler::Helper
if (GRPC_TRACE_FLAG_ENABLED(*(parent_->tracer_))) {
gpr_log(GPR_INFO,
"[child_policy_handler %p] helper %p: pending child policy %p "
- "reports state=%s",
- parent_.get(), this, child_, ConnectivityStateName(state));
+ "reports state=%s (%s)",
+ parent_.get(), this, child_, ConnectivityStateName(state),
+ status.ToString().c_str());
}
if (state == GRPC_CHANNEL_CONNECTING) return;
grpc_pollset_set_del_pollset_set(
@@ -67,7 +68,8 @@ class ChildPolicyHandler::Helper
// This request is from an outdated child, so ignore it.
return;
}
- parent_->channel_control_helper()->UpdateState(state, std::move(picker));
+ parent_->channel_control_helper()->UpdateState(state, status,
+ std::move(picker));
}
void RequestReresolution() override {
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index e4248a6f556..878951866ee 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -304,7 +304,7 @@ class GrpcLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -323,15 +323,16 @@ class GrpcLb : public LoadBalancingPolicy {
~StateWatcher() { parent_.reset(DEBUG_LOCATION, "StateWatcher"); }
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
if (parent_->fallback_at_startup_checks_pending_ &&
new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
// In TRANSIENT_FAILURE. Cancel the fallback timer and go into
// fallback mode immediately.
gpr_log(GPR_INFO,
- "[grpclb %p] balancer channel in state TRANSIENT_FAILURE; "
+ "[grpclb %p] balancer channel in state:TRANSIENT_FAILURE (%s); "
"entering fallback mode",
- parent_.get());
+ parent_.get(), status.ToString().c_str());
parent_->fallback_at_startup_checks_pending_ = false;
grpc_timer_cancel(&parent_->lb_fallback_timer_);
parent_->fallback_mode_ = true;
@@ -660,6 +661,7 @@ RefCountedPtr GrpcLb::Helper::CreateSubchannel(
}
void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) {
if (parent_->shutting_down_) return;
// Record whether child policy reports READY.
@@ -690,16 +692,22 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
state != GRPC_CHANNEL_READY)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO,
- "[grpclb %p helper %p] state=%s passing child picker %p as-is",
- parent_.get(), this, ConnectivityStateName(state), picker.get());
+ "[grpclb %p helper %p] state=%s (%s) passing "
+ "child picker %p as-is",
+ parent_.get(), this, ConnectivityStateName(state),
+ status.ToString().c_str(), picker.get());
}
- parent_->channel_control_helper()->UpdateState(state, std::move(picker));
+ parent_->channel_control_helper()->UpdateState(state, status,
+ std::move(picker));
return;
}
// Cases 2 and 3a: wrap picker from the child in our own picker.
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
- gpr_log(GPR_INFO, "[grpclb %p helper %p] state=%s wrapping child picker %p",
- parent_.get(), this, ConnectivityStateName(state), picker.get());
+ gpr_log(GPR_INFO,
+ "[grpclb %p helper %p] state=%s (%s) wrapping child "
+ "picker %p",
+ parent_.get(), this, ConnectivityStateName(state),
+ status.ToString().c_str(), picker.get());
}
RefCountedPtr client_stats;
if (parent_->lb_calld_ != nullptr &&
@@ -707,7 +715,7 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
client_stats = parent_->lb_calld_->client_stats()->Ref();
}
parent_->channel_control_helper()->UpdateState(
- state,
+ state, status,
absl::make_unique(parent_.get(), parent_->serverlist_,
std::move(picker), std::move(client_stats)));
}
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
index 246b15a3549..4a1f006cf64 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
@@ -30,6 +30,7 @@
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
@@ -200,7 +201,7 @@ void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
return;
}
@@ -318,12 +319,13 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
"selected subchannel failed; switching to pending update"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
} else {
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING, absl::make_unique(p->Ref(
- DEBUG_LOCATION, "QueuePicker")));
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
+ absl::make_unique(
+ p->Ref(DEBUG_LOCATION, "QueuePicker")));
}
} else {
if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
@@ -338,20 +340,22 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
p->selected_ = nullptr;
p->subchannel_list_.reset();
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_IDLE, absl::make_unique(
- p->Ref(DEBUG_LOCATION, "QueuePicker")));
+ GRPC_CHANNEL_IDLE, absl::Status(),
+ absl::make_unique(
+ p->Ref(DEBUG_LOCATION, "QueuePicker")));
} else {
// This is unlikely but can happen when a subchannel has been asked
// to reconnect by a different channel and this channel has dropped
// some connectivity state notifications.
if (connectivity_state == GRPC_CHANNEL_READY) {
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_READY,
+ GRPC_CHANNEL_READY, absl::Status(),
absl::make_unique(subchannel()->Ref()));
} else { // CONNECTING
p->channel_control_helper()->UpdateState(
- connectivity_state, absl::make_unique(
- p->Ref(DEBUG_LOCATION, "QueuePicker")));
+ connectivity_state, absl::Status(),
+ absl::make_unique(
+ p->Ref(DEBUG_LOCATION, "QueuePicker")));
}
}
}
@@ -394,7 +398,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
"failed to connect to all addresses"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
}
}
@@ -406,8 +410,9 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
// Only update connectivity state in case 1.
if (subchannel_list() == p->subchannel_list_.get()) {
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING, absl::make_unique(p->Ref(
- DEBUG_LOCATION, "QueuePicker")));
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
+ absl::make_unique(
+ p->Ref(DEBUG_LOCATION, "QueuePicker")));
}
break;
}
@@ -446,7 +451,8 @@ void PickFirst::PickFirstSubchannelData::ProcessUnselectedReadyLocked() {
}
p->selected_ = this;
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_READY, absl::make_unique(subchannel()->Ref()));
+ GRPC_CHANNEL_READY, absl::Status(),
+ absl::make_unique(subchannel()->Ref()));
for (size_t i = 0; i < subchannel_list()->num_subchannels(); ++i) {
if (i != Index()) {
subchannel_list()->subchannel(i)->ShutdownLocked();
diff --git a/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc b/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
index 19fc45f4f87..6b0489ceb16 100644
--- a/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
@@ -20,6 +20,7 @@
#include
#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
#include
@@ -33,6 +34,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
+#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
@@ -113,6 +115,11 @@ class PriorityLb : public LoadBalancingPolicy {
grpc_connectivity_state connectivity_state() const {
return connectivity_state_;
}
+
+ const absl::Status& connectivity_status() const {
+ return connectivity_status_;
+ }
+
bool failover_timer_callback_pending() const {
return failover_timer_callback_pending_;
}
@@ -150,6 +157,7 @@ class PriorityLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -164,7 +172,7 @@ class PriorityLb : public LoadBalancingPolicy {
const grpc_channel_args* args);
void OnConnectivityStateUpdateLocked(
- grpc_connectivity_state state,
+ grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker);
void StartFailoverTimerLocked();
@@ -180,6 +188,7 @@ class PriorityLb : public LoadBalancingPolicy {
OrphanablePtr child_policy_;
grpc_connectivity_state connectivity_state_ = GRPC_CHANNEL_CONNECTING;
+ absl::Status connectivity_status_;
RefCountedPtr picker_wrapper_;
// States for delayed removal.
@@ -334,6 +343,7 @@ void PriorityLb::HandleChildConnectivityStateChangeLocked(
// If it's still READY or IDLE, we stick with this child, so pass
// the new picker up to our parent.
channel_control_helper()->UpdateState(child->connectivity_state(),
+ child->connectivity_status(),
child->GetPicker());
} else {
// If it's no longer READY or IDLE, we should stop using it.
@@ -380,6 +390,7 @@ void PriorityLb::HandleChildConnectivityStateChangeLocked(
// The current priority has returned a new picker, so pass it up to
// our parent.
channel_control_helper()->UpdateState(child->connectivity_state(),
+ child->connectivity_status(),
child->GetPicker());
}
@@ -409,7 +420,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
if (child == nullptr) {
if (report_connecting) {
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING,
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker")));
}
child = MakeOrphanable(
@@ -436,7 +447,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
}
if (report_connecting) {
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING,
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker")));
}
return;
@@ -456,7 +467,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ready priority"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
}
@@ -476,6 +487,7 @@ void PriorityLb::SelectPriorityLocked(uint32_t priority) {
// Update picker.
auto& child = children_[config_->priorities()[priority]];
channel_control_helper()->UpdateState(child->connectivity_state(),
+ child->connectivity_status(),
child->GetPicker());
}
@@ -584,15 +596,18 @@ void PriorityLb::ChildPriority::ResetBackoffLocked() {
}
void PriorityLb::ChildPriority::OnConnectivityStateUpdateLocked(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) {
gpr_log(GPR_INFO,
- "[priority_lb %p] child %s (%p): state update: %s, picker %p",
+ "[priority_lb %p] child %s (%p): state update: %s (%s) picker %p",
priority_policy_.get(), name_.c_str(), this,
- ConnectivityStateName(state), picker.get());
+ ConnectivityStateName(state), status.ToString().c_str(),
+ picker.get());
}
// Store the state and picker.
connectivity_state_ = state;
+ connectivity_status_ = status;
picker_wrapper_ = MakeRefCounted(std::move(picker));
// If READY or TRANSIENT_FAILURE, cancel failover timer.
if (state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
@@ -646,7 +661,10 @@ void PriorityLb::ChildPriority::OnFailoverTimerLocked(grpc_error* error) {
priority_policy_.get(), name_.c_str(), this);
}
failover_timer_callback_pending_ = false;
- OnConnectivityStateUpdateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, nullptr);
+ OnConnectivityStateUpdateLocked(
+ GRPC_CHANNEL_TRANSIENT_FAILURE,
+ absl::Status(absl::StatusCode::kUnavailable, "failover timer fired"),
+ nullptr);
}
Unref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked");
GRPC_ERROR_UNREF(error);
@@ -725,10 +743,11 @@ PriorityLb::ChildPriority::Helper::CreateSubchannel(
}
void PriorityLb::ChildPriority::Helper::UpdateState(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
if (priority_->priority_policy_->shutting_down_) return;
// Notify the priority.
- priority_->OnConnectivityStateUpdateLocked(state, std::move(picker));
+ priority_->OnConnectivityStateUpdateLocked(state, status, std::move(picker));
}
void PriorityLb::ChildPriority::Helper::AddTraceEvent(
diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
index 56b71b69dfc..d1ad2ca35e7 100644
--- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
@@ -40,6 +40,7 @@
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/static_metadata.h"
namespace grpc_core {
@@ -322,11 +323,11 @@ void RoundRobin::RoundRobinSubchannelList::
if (num_ready_ > 0) {
/* 1) READY */
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_READY, absl::make_unique(p, this));
+ GRPC_CHANNEL_READY, absl::Status(), absl::make_unique(p, this));
} else if (num_connecting_ > 0) {
/* 2) CONNECTING */
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING,
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique(p->Ref(DEBUG_LOCATION, "QueuePicker")));
} else if (num_transient_failure_ == num_subchannels()) {
/* 3) TRANSIENT_FAILURE */
@@ -335,7 +336,7 @@ void RoundRobin::RoundRobinSubchannelList::
"connections to all backends failing"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
}
}
@@ -452,7 +453,7 @@ void RoundRobin::UpdateLocked(UpdateArgs args) {
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
subchannel_list_ = std::move(latest_pending_subchannel_list_);
} else if (subchannel_list_ == nullptr) {
diff --git a/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc b/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
index 96491b68642..83bc6cc9a54 100644
--- a/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
@@ -36,6 +36,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
+#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
@@ -146,6 +147,7 @@ class WeightedTargetLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -160,7 +162,7 @@ class WeightedTargetLb : public LoadBalancingPolicy {
const grpc_channel_args* args);
void OnConnectivityStateUpdateLocked(
- grpc_connectivity_state state,
+ grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker);
static void OnDelayedRemovalTimer(void* arg, grpc_error* error);
@@ -375,6 +377,7 @@ void WeightedTargetLb::UpdateStateLocked() {
this, ConnectivityStateName(connectivity_state));
}
std::unique_ptr picker;
+ absl::Status status;
switch (connectivity_state) {
case GRPC_CHANNEL_READY:
picker = absl::make_unique(std::move(picker_list));
@@ -385,11 +388,15 @@ void WeightedTargetLb::UpdateStateLocked() {
absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker"));
break;
default:
- picker = absl::make_unique(
+ grpc_error* error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "weighted_target: all children report state TRANSIENT_FAILURE"));
+ "weighted_target: all children report state TRANSIENT_FAILURE"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+ status = grpc_error_to_absl_status(error);
+ picker = absl::make_unique(error);
}
- channel_control_helper()->UpdateState(connectivity_state, std::move(picker));
+ channel_control_helper()->UpdateState(connectivity_state, status,
+ std::move(picker));
}
//
@@ -508,15 +515,17 @@ void WeightedTargetLb::WeightedChild::ResetBackoffLocked() {
}
void WeightedTargetLb::WeightedChild::OnConnectivityStateUpdateLocked(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
// Cache the picker in the WeightedChild.
picker_wrapper_ = MakeRefCounted(std::move(picker));
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_weighted_target_trace)) {
gpr_log(GPR_INFO,
"[weighted_target_lb %p] WeightedChild %p %s: connectivity "
- "state update: state=%s picker_wrapper=%p",
+ "state update: state=%s (%s) picker_wrapper=%p",
weighted_target_policy_.get(), this, name_.c_str(),
- ConnectivityStateName(state), picker_wrapper_.get());
+ ConnectivityStateName(state), status.ToString().c_str(),
+ picker_wrapper_.get());
}
// If the child reports IDLE, immediately tell it to exit idle.
if (state == GRPC_CHANNEL_IDLE) child_policy_->ExitIdleLocked();
@@ -589,9 +598,11 @@ WeightedTargetLb::WeightedChild::Helper::CreateSubchannel(
}
void WeightedTargetLb::WeightedChild::Helper::UpdateState(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
if (weighted_child_->weighted_target_policy_->shutting_down_) return;
- weighted_child_->OnConnectivityStateUpdateLocked(state, std::move(picker));
+ weighted_child_->OnConnectivityStateUpdateLocked(state, status,
+ std::move(picker));
}
void WeightedTargetLb::WeightedChild::Helper::RequestReresolution() {
diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
index 500f1ac056b..fb161fcb26c 100644
--- a/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
@@ -29,6 +29,7 @@
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
@@ -79,7 +80,7 @@ class CdsLb : public LoadBalancingPolicy {
explicit Helper(RefCountedPtr parent) : parent_(std::move(parent)) {}
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -209,7 +210,7 @@ void CdsLb::ClusterWatcher::OnError(grpc_error* error) {
// we keep running with the data we had previously.
if (parent_->child_policy_ == nullptr) {
parent_->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
} else {
GRPC_ERROR_UNREF(error);
@@ -221,13 +222,15 @@ void CdsLb::ClusterWatcher::OnResourceDoesNotExist() {
"[cdslb %p] CDS resource for %s does not exist -- reporting "
"TRANSIENT_FAILURE",
parent_.get(), parent_->config_->cluster().c_str());
+ grpc_error* error = grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("CDS resource \"", parent_->config_->cluster(),
+ "\" does not exist")
+ .c_str()),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
parent_->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
- absl::make_unique(
- GRPC_ERROR_CREATE_FROM_COPIED_STRING(
- absl::StrCat("CDS resource \"", parent_->config_->cluster(),
- "\" does not exist")
- .c_str())));
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
+ absl::make_unique(error));
parent_->MaybeDestroyChildPolicyLocked();
}
@@ -242,13 +245,16 @@ RefCountedPtr CdsLb::Helper::CreateSubchannel(
}
void CdsLb::Helper::UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) {
if (parent_->shutting_down_ || parent_->child_policy_ == nullptr) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
- gpr_log(GPR_INFO, "[cdslb %p] state updated by child: %s", this,
- ConnectivityStateName(state));
+ gpr_log(GPR_INFO,
+ "[cdslb %p] state updated by child: %s message_state: (%s)", this,
+ ConnectivityStateName(state), status.ToString().c_str());
}
- parent_->channel_control_helper()->UpdateState(state, std::move(picker));
+ parent_->channel_control_helper()->UpdateState(state, status,
+ std::move(picker));
}
void CdsLb::Helper::RequestReresolution() {
diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
index c1bbf742cee..da9d0aaff7d 100644
--- a/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
@@ -40,6 +40,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
+#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/uri/uri_parser.h"
#define GRPC_EDS_DEFAULT_FALLBACK_TIMEOUT 10000
@@ -133,7 +134,7 @@ class EdsLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override;
// This is a no-op, because we get the addresses from the xds
// client, which is a watch-based API.
@@ -214,6 +215,7 @@ class EdsLb : public LoadBalancingPolicy {
// The latest state and picker returned from the child policy.
grpc_connectivity_state child_state_;
+ absl::Status child_status_;
RefCountedPtr child_picker_;
};
@@ -265,16 +267,21 @@ RefCountedPtr EdsLb::Helper::CreateSubchannel(
}
void EdsLb::Helper::UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) {
if (eds_policy_->shutting_down_ || eds_policy_->child_policy_ == nullptr) {
return;
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
- gpr_log(GPR_INFO, "[edslb %p] child policy updated state=%s picker=%p",
- eds_policy_.get(), ConnectivityStateName(state), picker.get());
+ gpr_log(GPR_INFO,
+ "[edslb %p] child policy updated state=%s (%s) "
+ "picker=%p",
+ eds_policy_.get(), ConnectivityStateName(state),
+ status.ToString().c_str(), picker.get());
}
// Save the state and picker.
eds_policy_->child_state_ = state;
+ eds_policy_->child_status_ = status;
eds_policy_->child_picker_ =
MakeRefCounted(std::move(picker));
// Wrap the picker in a DropPicker and pass it up.
@@ -339,7 +346,7 @@ class EdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
// we keep running with the data we had previously.
if (eds_policy_->child_policy_ == nullptr) {
eds_policy_->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
} else {
GRPC_ERROR_UNREF(error);
@@ -351,11 +358,12 @@ class EdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
GPR_ERROR,
"[edslb %p] EDS resource does not exist -- reporting TRANSIENT_FAILURE",
eds_policy_.get());
+ grpc_error* error = grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("EDS resource does not exist"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
eds_policy_->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
- absl::make_unique(
- GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "EDS resource does not exist")));
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
+ absl::make_unique(error));
eds_policy_->MaybeDestroyChildPolicyLocked();
}
@@ -688,7 +696,7 @@ EdsLb::CreateChildPolicyConfigLocked() {
error),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL);
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
return nullptr;
}
@@ -769,13 +777,13 @@ void EdsLb::MaybeUpdateDropPickerLocked() {
// If we're dropping all calls, report READY, regardless of what (or
// whether) the child has reported.
if (drop_config_ != nullptr && drop_config_->drop_all()) {
- channel_control_helper()->UpdateState(GRPC_CHANNEL_READY,
+ channel_control_helper()->UpdateState(GRPC_CHANNEL_READY, absl::Status(),
absl::make_unique(this));
return;
}
// Update only if we have a child picker.
if (child_picker_ != nullptr) {
- channel_control_helper()->UpdateState(child_state_,
+ channel_control_helper()->UpdateState(child_state_, child_status_,
absl::make_unique(this));
}
}
diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc b/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
index 0aca12dfed2..51027574b32 100644
--- a/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
@@ -120,7 +120,7 @@ class LrsLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -157,6 +157,7 @@ class LrsLb : public LoadBalancingPolicy {
// Latest state and picker reported by the child policy.
grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE;
+ absl::Status status_;
RefCountedPtr picker_;
};
@@ -266,10 +267,14 @@ void LrsLb::MaybeUpdatePickerLocked() {
auto lrs_picker =
absl::make_unique(picker_, locality_stats_);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) {
- gpr_log(GPR_INFO, "[lrs_lb %p] updating connectivity: state=%s picker=%p",
- this, ConnectivityStateName(state_), lrs_picker.get());
+ gpr_log(
+ GPR_INFO,
+ "[lrs_lb %p] updating connectivity: state=%s status=(%s) picker=%p",
+ this, ConnectivityStateName(state_), status_.ToString().c_str(),
+ lrs_picker.get());
}
- channel_control_helper()->UpdateState(state_, std::move(lrs_picker));
+ channel_control_helper()->UpdateState(state_, status_,
+ std::move(lrs_picker));
}
}
@@ -325,15 +330,19 @@ RefCountedPtr LrsLb::Helper::CreateSubchannel(
}
void LrsLb::Helper::UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) {
if (lrs_policy_->shutting_down_) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) {
- gpr_log(GPR_INFO,
- "[lrs_lb %p] child connectivity state update: state=%s picker=%p",
- lrs_policy_.get(), ConnectivityStateName(state), picker.get());
+ gpr_log(
+ GPR_INFO,
+ "[lrs_lb %p] child connectivity state update: state=%s (%s) picker=%p",
+ lrs_policy_.get(), ConnectivityStateName(state),
+ status.ToString().c_str(), picker.get());
}
// Save the state and picker.
lrs_policy_->state_ = state;
+ lrs_policy_->status_ = status;
lrs_policy_->picker_ = MakeRefCounted(std::move(picker));
// Wrap the picker and return it to the channel.
lrs_policy_->MaybeUpdatePickerLocked();
diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
index 2adc7cd9551..a3672e14bce 100644
--- a/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
@@ -42,6 +42,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
+#include "src/core/lib/transport/error_utils.h"
#define GRPC_XDS_ROUTING_CHILD_RETENTION_INTERVAL_MS (15 * 60 * 1000)
@@ -165,6 +166,7 @@ class XdsRoutingLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -464,6 +466,7 @@ void XdsRoutingLb::UpdateStateLocked() {
ConnectivityStateName(connectivity_state));
}
std::unique_ptr picker;
+ absl::Status status;
switch (connectivity_state) {
case GRPC_CHANNEL_READY: {
RoutePicker::RouteTable route_table;
@@ -493,12 +496,15 @@ void XdsRoutingLb::UpdateStateLocked() {
absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker"));
break;
default:
- picker = absl::make_unique(grpc_error_set_int(
+ grpc_error* error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"TRANSIENT_FAILURE from XdsRoutingLb"),
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+ status = grpc_error_to_absl_status(error);
+ picker = absl::make_unique(error);
}
- channel_control_helper()->UpdateState(connectivity_state, std::move(picker));
+ channel_control_helper()->UpdateState(connectivity_state, status,
+ std::move(picker));
}
//
@@ -654,13 +660,15 @@ XdsRoutingLb::XdsRoutingChild::Helper::CreateSubchannel(
}
void XdsRoutingLb::XdsRoutingChild::Helper::UpdateState(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO,
- "[xds_routing_lb %p] child %s: received update: state=%s picker=%p",
+ "[xds_routing_lb %p] child %s: received update: state=%s (%s) "
+ "picker=%p",
xds_routing_child_->xds_routing_policy_.get(),
xds_routing_child_->name_.c_str(), ConnectivityStateName(state),
- picker.get());
+ status.ToString().c_str(), picker.get());
}
if (xds_routing_child_->xds_routing_policy_->shutting_down_) return;
// Cache the picker in the XdsRoutingChild.
diff --git a/src/core/ext/filters/client_channel/resolving_lb_policy.cc b/src/core/ext/filters/client_channel/resolving_lb_policy.cc
index 356123c50ae..ce204f030e7 100644
--- a/src/core/ext/filters/client_channel/resolving_lb_policy.cc
+++ b/src/core/ext/filters/client_channel/resolving_lb_policy.cc
@@ -114,10 +114,11 @@ class ResolvingLoadBalancingPolicy::ResolvingControlHelper
return parent_->channel_control_helper()->CreateSubchannel(args);
}
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
if (parent_->resolver_ == nullptr) return; // Shutting down.
- parent_->channel_control_helper()->UpdateState(state, std::move(picker));
+ parent_->channel_control_helper()->UpdateState(state, status,
+ std::move(picker));
}
void RequestReresolution() override {
@@ -160,7 +161,7 @@ ResolvingLoadBalancingPolicy::ResolvingLoadBalancingPolicy(
if (GRPC_TRACE_FLAG_ENABLED(*tracer_)) {
gpr_log(GPR_INFO, "resolving_lb=%p: starting name resolution", this);
}
- channel_control_helper()->UpdateState(GRPC_CHANNEL_CONNECTING,
+ channel_control_helper()->UpdateState(GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique(Ref()));
resolver_->StartLocked();
}
@@ -214,7 +215,7 @@ void ResolvingLoadBalancingPolicy::OnResolverError(grpc_error* error) {
"Resolver transient failure", &error, 1);
helper_->ResolverTransientFailure(GRPC_ERROR_REF(state_error));
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(state_error),
absl::make_unique(state_error));
}
GRPC_ERROR_UNREF(error);
diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc
index 89a13a3ef74..26bc7f8549f 100644
--- a/src/core/ext/filters/client_channel/subchannel.cc
+++ b/src/core/ext/filters/client_channel/subchannel.cc
@@ -26,6 +26,8 @@
#include
#include
+#include "absl/strings/str_format.h"
+
#include
#include
@@ -325,7 +327,8 @@ class Subchannel::ConnectedSubchannelStateWatcher
}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
Subchannel* c = subchannel_;
MutexLock lock(&c->mu_);
switch (new_state) {
@@ -343,7 +346,15 @@ class Subchannel::ConnectedSubchannelStateWatcher
if (c->channelz_node() != nullptr) {
c->channelz_node()->SetChildSocket(nullptr);
}
- c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
+ // We need to construct our own status if the underlying state was
+ // shutdown since the accompanying status will be StatusCode::OK
+ // otherwise.
+ c->SetConnectivityStateLocked(
+ GRPC_CHANNEL_TRANSIENT_FAILURE,
+ new_state == GRPC_CHANNEL_SHUTDOWN
+ ? absl::Status(absl::StatusCode::kUnavailable,
+ "Subchannel has disconnected.")
+ : status);
c->backoff_begun_ = false;
c->backoff_.Reset();
}
@@ -354,7 +365,7 @@ class Subchannel::ConnectedSubchannelStateWatcher
// a callback for READY, because that was the state we started
// this watch from. And a connected subchannel should never go
// from READY to CONNECTING or IDLE.
- c->SetConnectivityStateLocked(new_state);
+ c->SetConnectivityStateLocked(new_state, status);
}
}
}
@@ -368,14 +379,15 @@ class Subchannel::AsyncWatcherNotifierLocked {
public:
AsyncWatcherNotifierLocked(
RefCountedPtr watcher,
- Subchannel* subchannel, grpc_connectivity_state state)
+ Subchannel* subchannel, grpc_connectivity_state state,
+ const absl::Status& status)
: watcher_(std::move(watcher)) {
RefCountedPtr connected_subchannel;
if (state == GRPC_CHANNEL_READY) {
connected_subchannel = subchannel->connected_subchannel_;
}
watcher_->PushConnectivityStateChange(
- {state, std::move(connected_subchannel)});
+ {state, status, std::move(connected_subchannel)});
ExecCtx::Run(
DEBUG_LOCATION,
GRPC_CLOSURE_INIT(&closure_,
@@ -409,9 +421,10 @@ void Subchannel::ConnectivityStateWatcherList::RemoveWatcherLocked(
}
void Subchannel::ConnectivityStateWatcherList::NotifyLocked(
- Subchannel* subchannel, grpc_connectivity_state state) {
+ Subchannel* subchannel, grpc_connectivity_state state,
+ const absl::Status& status) {
for (const auto& p : watchers_) {
- new AsyncWatcherNotifierLocked(p.second, subchannel, state);
+ new AsyncWatcherNotifierLocked(p.second, subchannel, state, status);
}
}
@@ -450,7 +463,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
grpc_connectivity_state initial_state,
RefCountedPtr watcher) {
if (state_ != initial_state) {
- new AsyncWatcherNotifierLocked(watcher, subchannel_, state_);
+ new AsyncWatcherNotifierLocked(watcher, subchannel_, state_, status_);
}
watcher_list_.AddWatcherLocked(std::move(watcher));
}
@@ -462,7 +475,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
bool HasWatchers() const { return !watcher_list_.empty(); }
- void NotifyLocked(grpc_connectivity_state state) {
+ void NotifyLocked(grpc_connectivity_state state, const absl::Status& status) {
if (state == GRPC_CHANNEL_READY) {
// If we had not already notified for CONNECTING state, do so now.
// (We may have missed this earlier, because if the transition
@@ -470,13 +483,15 @@ class Subchannel::HealthWatcherMap::HealthWatcher
// subchannel may not have sent us a notification for CONNECTING.)
if (state_ != GRPC_CHANNEL_CONNECTING) {
state_ = GRPC_CHANNEL_CONNECTING;
- watcher_list_.NotifyLocked(subchannel_, state_);
+ status_ = status;
+ watcher_list_.NotifyLocked(subchannel_, state_, status);
}
// If we've become connected, start health checking.
StartHealthCheckingLocked();
} else {
state_ = state;
- watcher_list_.NotifyLocked(subchannel_, state_);
+ status_ = status;
+ watcher_list_.NotifyLocked(subchannel_, state_, status);
// We're not connected, so stop health checking.
health_check_client_.reset();
}
@@ -489,11 +504,13 @@ class Subchannel::HealthWatcherMap::HealthWatcher
}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
MutexLock lock(&subchannel_->mu_);
if (new_state != GRPC_CHANNEL_SHUTDOWN && health_check_client_ != nullptr) {
state_ = new_state;
- watcher_list_.NotifyLocked(subchannel_, new_state);
+ status_ = status;
+ watcher_list_.NotifyLocked(subchannel_, new_state, status);
}
}
@@ -508,6 +525,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
grpc_core::UniquePtr health_check_service_name_;
OrphanablePtr health_check_client_;
grpc_connectivity_state state_;
+ absl::Status status_;
ConnectivityStateWatcherList watcher_list_;
};
@@ -547,9 +565,10 @@ void Subchannel::HealthWatcherMap::RemoveWatcherLocked(
if (!it->second->HasWatchers()) map_.erase(it);
}
-void Subchannel::HealthWatcherMap::NotifyLocked(grpc_connectivity_state state) {
+void Subchannel::HealthWatcherMap::NotifyLocked(grpc_connectivity_state state,
+ const absl::Status& status) {
for (const auto& p : map_) {
- p.second->NotifyLocked(state);
+ p.second->NotifyLocked(state, status);
}
}
@@ -826,7 +845,7 @@ void Subchannel::WatchConnectivityState(
}
if (health_check_service_name == nullptr) {
if (state_ != initial_state) {
- new AsyncWatcherNotifierLocked(watcher, this, state_);
+ new AsyncWatcherNotifierLocked(watcher, this, state_, status_);
}
watcher_list_.AddWatcherLocked(std::move(watcher));
} else {
@@ -928,8 +947,10 @@ const char* SubchannelConnectivityStateChangeString(
} // namespace
// Note: Must be called with a state that is different from the current state.
-void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state) {
+void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state,
+ const absl::Status& status) {
state_ = state;
+ status_ = status;
if (channelz_node_ != nullptr) {
channelz_node_->UpdateConnectivityState(state);
channelz_node_->AddTraceEvent(
@@ -938,9 +959,9 @@ void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state) {
SubchannelConnectivityStateChangeString(state)));
}
// Notify non-health watchers.
- watcher_list_.NotifyLocked(this, state);
+ watcher_list_.NotifyLocked(this, state, status);
// Notify health watchers.
- health_watcher_map_.NotifyLocked(state);
+ health_watcher_map_.NotifyLocked(state, status);
}
void Subchannel::MaybeStartConnectingLocked() {
@@ -1012,7 +1033,7 @@ void Subchannel::ContinueConnectingLocked() {
next_attempt_deadline_ = backoff_.NextAttemptTime();
args.deadline = std::max(next_attempt_deadline_, min_deadline);
args.channel_args = args_;
- SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING);
+ SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, absl::Status());
connector_->Connect(args, &connecting_result_, &on_connecting_finished_);
}
@@ -1031,7 +1052,8 @@ void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) {
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
} else {
gpr_log(GPR_INFO, "Connect failed: %s", grpc_error_string(error));
- c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
+ c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
+ grpc_error_to_absl_status(error));
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
}
}
@@ -1091,7 +1113,7 @@ bool Subchannel::PublishTransportLocked() {
connected_subchannel_->StartWatch(
pollset_set_, MakeOrphanable(this));
// Report initial state.
- SetConnectivityStateLocked(GRPC_CHANNEL_READY);
+ SetConnectivityStateLocked(GRPC_CHANNEL_READY, absl::Status());
return true;
}
diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h
index 9478fa7340c..e615c18c944 100644
--- a/src/core/ext/filters/client_channel/subchannel.h
+++ b/src/core/ext/filters/client_channel/subchannel.h
@@ -182,6 +182,7 @@ class Subchannel {
public:
struct ConnectivityStateChange {
grpc_connectivity_state state;
+ absl::Status status;
RefCountedPtr connected_subchannel;
};
@@ -306,7 +307,8 @@ class Subchannel {
void RemoveWatcherLocked(ConnectivityStateWatcherInterface* watcher);
// Notifies all watchers in the list about a change to state.
- void NotifyLocked(Subchannel* subchannel, grpc_connectivity_state state);
+ void NotifyLocked(Subchannel* subchannel, grpc_connectivity_state state,
+ const absl::Status& status);
void Clear() { watchers_.clear(); }
@@ -339,7 +341,8 @@ class Subchannel {
ConnectivityStateWatcherInterface* watcher);
// Notifies the watcher when the subchannel's state changes.
- void NotifyLocked(grpc_connectivity_state state);
+ void NotifyLocked(grpc_connectivity_state state,
+ const absl::Status& status);
grpc_connectivity_state CheckConnectivityStateLocked(
Subchannel* subchannel, const char* health_check_service_name);
@@ -357,7 +360,8 @@ class Subchannel {
class AsyncWatcherNotifierLocked;
// Sets the subchannel's connectivity state to \a state.
- void SetConnectivityStateLocked(grpc_connectivity_state state);
+ void SetConnectivityStateLocked(grpc_connectivity_state state,
+ const absl::Status& status);
// Methods for connection.
void MaybeStartConnectingLocked();
@@ -400,6 +404,7 @@ class Subchannel {
// Connectivity state tracking.
grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE;
+ absl::Status status_;
// The list of watchers without a health check service name.
ConnectivityStateWatcherList watcher_list_;
// The map of watchers with health check service names.
diff --git a/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc b/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
index c218db86a17..9252e553cee 100644
--- a/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
+++ b/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
@@ -73,7 +73,7 @@ grpc_channel* CreateXdsChannel(const XdsBootstrap& bootstrap,
if (!bootstrap.server().channel_creds.empty()) {
for (size_t i = 0; i < bootstrap.server().channel_creds.size(); ++i) {
if (bootstrap.server().channel_creds[i].type == "google_default") {
- creds = grpc_google_default_credentials_create();
+ creds = grpc_google_default_credentials_create(nullptr);
break;
} else if (bootstrap.server().channel_creds[i].type == "fake") {
creds = grpc_fake_transport_security_credentials_create();
diff --git a/src/core/ext/filters/client_channel/xds/xds_client.cc b/src/core/ext/filters/client_channel/xds/xds_client.cc
index 3010c6b23d0..88e335087e1 100644
--- a/src/core/ext/filters/client_channel/xds/xds_client.cc
+++ b/src/core/ext/filters/client_channel/xds/xds_client.cc
@@ -398,13 +398,15 @@ class XdsClient::ChannelState::StateWatcher
parent_(std::move(parent)) {}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
if (!parent_->shutting_down_ &&
new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
// In TRANSIENT_FAILURE. Notify all watchers of error.
gpr_log(GPR_INFO,
- "[xds_client %p] xds channel in state TRANSIENT_FAILURE",
- parent_->xds_client());
+ "[xds_client %p] xds channel in state:TRANSIENT_FAILURE "
+ "status_message:(%s)",
+ parent_->xds_client(), status.ToString().c_str());
parent_->xds_client()->NotifyOnError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"xds channel in TRANSIENT_FAILURE"));
}
diff --git a/src/core/ext/filters/max_age/max_age_filter.cc b/src/core/ext/filters/max_age/max_age_filter.cc
index 0cf6f542414..ef59d675770 100644
--- a/src/core/ext/filters/max_age/max_age_filter.cc
+++ b/src/core/ext/filters/max_age/max_age_filter.cc
@@ -229,7 +229,8 @@ class ConnectivityWatcher : public AsyncConnectivityStateWatcherInterface {
}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& /* status */) override {
if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
{
MutexLock lock(&chand_->max_age_timer_mu);
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index 8b7c7fe3db5..ddaed426bf6 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -18,6 +18,8 @@
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "absl/strings/str_format.h"
+
#include
#include
#include
@@ -29,7 +31,6 @@
#include
#include
-#include "absl/strings/str_format.h"
#include "src/core/ext/transport/chttp2/transport/context_list.h"
#include "src/core/ext/transport/chttp2/transport/frame_data.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
@@ -125,6 +126,7 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t);
static void connectivity_state_set(grpc_chttp2_transport* t,
grpc_connectivity_state state,
+ const absl::Status& status,
const char* reason);
static void benign_reclaimer(void* t, grpc_error* error);
@@ -560,7 +562,8 @@ static void close_transport_locked(grpc_chttp2_transport* t,
}
GPR_ASSERT(error != GRPC_ERROR_NONE);
t->closed_with_error = GRPC_ERROR_REF(error);
- connectivity_state_set(t, GRPC_CHANNEL_SHUTDOWN, "close_transport");
+ connectivity_state_set(t, GRPC_CHANNEL_SHUTDOWN, absl::Status(),
+ "close_transport");
if (t->ping_state.is_delayed_ping_timer_set) {
grpc_timer_cancel(&t->ping_state.delayed_ping_timer);
}
@@ -1103,9 +1106,11 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
: static_cast(current_keepalive_time_ms *
KEEPALIVE_TIME_BACKOFF_MULTIPLIER);
}
+ absl::Status status = grpc_error_to_absl_status(t->goaway_error);
// lie: use transient failure from the transport to indicate goaway has been
- // received
- connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE, "got_goaway");
+ // received.
+ connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE, status,
+ "got_goaway");
}
static void maybe_start_some_streams(grpc_chttp2_transport* t) {
@@ -1140,6 +1145,8 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
if (t->next_stream_id >= MAX_CLIENT_STREAM_ID) {
connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE,
+ absl::Status(absl::StatusCode::kUnavailable,
+ "Transport Stream IDs exhausted"),
"no_more_stream_ids");
}
@@ -2915,10 +2922,11 @@ static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error) {
static void connectivity_state_set(grpc_chttp2_transport* t,
grpc_connectivity_state state,
+ const absl::Status& status,
const char* reason) {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_INFO, "transport %p set connectivity_state=%d", t, state));
- t->state_tracker.SetState(state, reason);
+ t->state_tracker.SetState(state, status, reason);
}
//
diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc
index 49b9bf093ba..d40bffd6d09 100644
--- a/src/core/ext/transport/inproc/inproc_transport.cc
+++ b/src/core/ext/transport/inproc/inproc_transport.cc
@@ -1132,7 +1132,8 @@ void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
void close_transport_locked(inproc_transport* t) {
INPROC_LOG(GPR_INFO, "close_transport %p %d", t, t->is_closed);
- t->state_tracker.SetState(GRPC_CHANNEL_SHUTDOWN, "close transport");
+ t->state_tracker.SetState(GRPC_CHANNEL_SHUTDOWN, absl::Status(),
+ "close transport");
if (!t->is_closed) {
t->is_closed = true;
/* Also end all streams on this transport */
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
index 4edbd86037f..9162bad47bc 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
@@ -49,6 +49,8 @@ using grpc_core::Json;
/* -- Constants. -- */
#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal."
+#define GRPC_GOOGLE_CREDENTIAL_CREATION_ERROR \
+ "Failed to create Google credentials"
/* -- Default credentials. -- */
@@ -57,7 +59,6 @@ using grpc_core::Json;
* means the detection is done via network test that is unreliable and the
* unreliable result should not be referred by successive calls. */
static int g_metadata_server_available = 0;
-static int g_is_on_gce = 0;
static gpr_mu g_state_mu;
/* Protect a metadata_server_detector instance that can be modified by more than
* one gRPC threads */
@@ -89,7 +90,7 @@ grpc_google_default_channel_credentials::create_security_connector(
bool use_alts =
is_grpclb_load_balancer || is_backend_from_grpclb_load_balancer;
/* Return failure if ALTS is selected but not running on GCE. */
- if (use_alts && !g_is_on_gce) {
+ if (use_alts && alts_creds_ == nullptr) {
gpr_log(GPR_ERROR, "ALTS is selected, but not running on GCE.");
return nullptr;
}
@@ -273,59 +274,78 @@ end:
return error;
}
-grpc_channel_credentials* grpc_google_default_credentials_create() {
- grpc_channel_credentials* result = nullptr;
- grpc_core::RefCountedPtr call_creds;
- grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "Failed to create Google credentials");
- grpc_error* err;
- grpc_core::ExecCtx exec_ctx;
+static void update_tenancy() {
+ gpr_once_init(&g_once, init_default_credentials);
+ grpc_core::MutexLock lock(&g_state_mu);
- GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
+ /* Try a platform-provided hint for GCE. */
+ if (!g_metadata_server_available) {
+ g_metadata_server_available = g_gce_tenancy_checker();
+ }
+ /* TODO: Add a platform-provided hint for GAE. */
- gpr_once_init(&g_once, init_default_credentials);
+ /* Do a network test for metadata server. */
+ if (!g_metadata_server_available) {
+ g_metadata_server_available = is_metadata_server_reachable();
+ }
+}
+
+static bool metadata_server_available() {
+ grpc_core::MutexLock lock(&g_state_mu);
+ return static_cast(g_metadata_server_available);
+}
+
+static grpc_core::RefCountedPtr make_default_call_creds(
+ grpc_error** error) {
+ grpc_core::RefCountedPtr call_creds;
+ grpc_error* err;
/* First, try the environment variable. */
char* path_from_env = gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR);
if (path_from_env != nullptr) {
err = create_default_creds_from_path(path_from_env, &call_creds);
gpr_free(path_from_env);
- if (err == GRPC_ERROR_NONE) goto end;
- error = grpc_error_add_child(error, err);
+ if (err == GRPC_ERROR_NONE) return call_creds;
+ *error = grpc_error_add_child(*error, err);
}
/* Then the well-known file. */
err = create_default_creds_from_path(
grpc_get_well_known_google_credentials_file_path(), &call_creds);
- if (err == GRPC_ERROR_NONE) goto end;
- error = grpc_error_add_child(error, err);
+ if (err == GRPC_ERROR_NONE) return call_creds;
+ *error = grpc_error_add_child(*error, err);
- gpr_mu_lock(&g_state_mu);
+ update_tenancy();
- /* Try a platform-provided hint for GCE. */
- if (!g_metadata_server_available) {
- g_is_on_gce = g_gce_tenancy_checker();
- g_metadata_server_available = g_is_on_gce;
- }
- /* TODO: Add a platform-provided hint for GAE. */
-
- /* Do a network test for metadata server. */
- if (!g_metadata_server_available) {
- g_metadata_server_available = is_metadata_server_reachable();
- }
- gpr_mu_unlock(&g_state_mu);
-
- if (g_metadata_server_available) {
+ if (metadata_server_available()) {
call_creds = grpc_core::RefCountedPtr(
grpc_google_compute_engine_credentials_create(nullptr));
if (call_creds == nullptr) {
- error = grpc_error_add_child(
- error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "Failed to get credentials from network"));
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ GRPC_GOOGLE_CREDENTIAL_CREATION_ERROR);
+ *error = grpc_error_add_child(
+ *error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Failed to get credentials from network"));
}
}
-end:
+ return call_creds;
+}
+
+grpc_channel_credentials* grpc_google_default_credentials_create(
+ grpc_call_credentials* call_credentials) {
+ grpc_channel_credentials* result = nullptr;
+ grpc_core::RefCountedPtr call_creds(call_credentials);
+ grpc_error* error = nullptr;
+ grpc_core::ExecCtx exec_ctx;
+
+ GRPC_API_TRACE("grpc_google_default_credentials_create(%p)", 1,
+ (call_credentials));
+
+ if (call_creds == nullptr) {
+ call_creds = make_default_call_creds(&error);
+ }
+
if (call_creds != nullptr) {
/* Create google default credentials. */
grpc_channel_credentials* ssl_creds =
@@ -338,10 +358,8 @@ end:
grpc_alts_credentials_options_destroy(options);
auto creds =
grpc_core::MakeRefCounted(
- alts_creds != nullptr ? alts_creds->Ref() : nullptr,
- ssl_creds != nullptr ? ssl_creds->Ref() : nullptr);
- if (ssl_creds) ssl_creds->Unref();
- if (alts_creds) alts_creds->Unref();
+ grpc_core::RefCountedPtr(alts_creds),
+ grpc_core::RefCountedPtr(ssl_creds));
result = grpc_composite_channel_credentials_create(
creds.get(), call_creds.get(), nullptr);
GPR_ASSERT(result != nullptr);
diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc
index cab0cd56c40..9b7c2262137 100644
--- a/src/core/lib/surface/server.cc
+++ b/src/core/lib/surface/server.cc
@@ -1271,7 +1271,8 @@ class ConnectivityWatcher : public AsyncConnectivityStateWatcherInterface {
}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& /* status */) override {
// Don't do anything until we are being shut down.
if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
// Shut down channel.
diff --git a/src/core/lib/transport/connectivity_state.cc b/src/core/lib/transport/connectivity_state.cc
index 2d34f52e635..c2008ab82b7 100644
--- a/src/core/lib/transport/connectivity_state.cc
+++ b/src/core/lib/transport/connectivity_state.cc
@@ -58,9 +58,9 @@ const char* ConnectivityStateName(grpc_connectivity_state state) {
class AsyncConnectivityStateWatcherInterface::Notifier {
public:
Notifier(RefCountedPtr watcher,
- grpc_connectivity_state state,
+ grpc_connectivity_state state, const absl::Status& status,
const std::shared_ptr& work_serializer)
- : watcher_(std::move(watcher)), state_(state) {
+ : watcher_(std::move(watcher)), state_(state), status_(status) {
if (work_serializer != nullptr) {
work_serializer->Run(
[this]() { SendNotification(this, GRPC_ERROR_NONE); },
@@ -76,21 +76,24 @@ class AsyncConnectivityStateWatcherInterface::Notifier {
static void SendNotification(void* arg, grpc_error* /*ignored*/) {
Notifier* self = static_cast(arg);
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
- gpr_log(GPR_INFO, "watcher %p: delivering async notification for %s",
- self->watcher_.get(), ConnectivityStateName(self->state_));
+ gpr_log(GPR_INFO, "watcher %p: delivering async notification for %s (%s)",
+ self->watcher_.get(), ConnectivityStateName(self->state_),
+ self->status_.ToString().c_str());
}
- self->watcher_->OnConnectivityStateChange(self->state_);
+ self->watcher_->OnConnectivityStateChange(self->state_, self->status_);
delete self;
}
RefCountedPtr watcher_;
const grpc_connectivity_state state_;
+ const absl::Status status_;
grpc_closure closure_;
};
void AsyncConnectivityStateWatcherInterface::Notify(
- grpc_connectivity_state state) {
- new Notifier(Ref(), state, work_serializer_); // Deletes itself when done.
+ grpc_connectivity_state state, const absl::Status& status) {
+ new Notifier(Ref(), state, status,
+ work_serializer_); // Deletes itself when done.
}
//
@@ -107,7 +110,7 @@ ConnectivityStateTracker::~ConnectivityStateTracker() {
name_, this, p.first, ConnectivityStateName(current_state),
ConnectivityStateName(GRPC_CHANNEL_SHUTDOWN));
}
- p.second->Notify(GRPC_CHANNEL_SHUTDOWN);
+ p.second->Notify(GRPC_CHANNEL_SHUTDOWN, absl::Status());
}
}
@@ -126,7 +129,7 @@ void ConnectivityStateTracker::AddWatcher(
name_, this, watcher.get(), ConnectivityStateName(initial_state),
ConnectivityStateName(current_state));
}
- watcher->Notify(current_state);
+ watcher->Notify(current_state, status_);
}
// If we're in state SHUTDOWN, don't add the watcher, so that it will
// be orphaned immediately.
@@ -145,15 +148,17 @@ void ConnectivityStateTracker::RemoveWatcher(
}
void ConnectivityStateTracker::SetState(grpc_connectivity_state state,
+ const absl::Status& status,
const char* reason) {
grpc_connectivity_state current_state = state_.Load(MemoryOrder::RELAXED);
if (state == current_state) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
- gpr_log(GPR_INFO, "ConnectivityStateTracker %s[%p]: %s -> %s (%s)", name_,
- this, ConnectivityStateName(current_state),
- ConnectivityStateName(state), reason);
+ gpr_log(GPR_INFO, "ConnectivityStateTracker %s[%p]: %s -> %s (%s, %s)",
+ name_, this, ConnectivityStateName(current_state),
+ ConnectivityStateName(state), reason, status.ToString().c_str());
}
state_.Store(state, MemoryOrder::RELAXED);
+ status_ = status;
for (const auto& p : watchers_) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO,
@@ -161,7 +166,7 @@ void ConnectivityStateTracker::SetState(grpc_connectivity_state state,
name_, this, p.first, ConnectivityStateName(current_state),
ConnectivityStateName(state));
}
- p.second->Notify(state);
+ p.second->Notify(state, status);
}
// If the new state is SHUTDOWN, orphan all of the watchers. This
// avoids the need for the callers to explicitly cancel them.
diff --git a/src/core/lib/transport/connectivity_state.h b/src/core/lib/transport/connectivity_state.h
index 5ab62bed40c..f8a945eb035 100644
--- a/src/core/lib/transport/connectivity_state.h
+++ b/src/core/lib/transport/connectivity_state.h
@@ -21,6 +21,8 @@
#include
+#include "absl/status/status.h"
+
#include
#include "src/core/lib/debug/trace.h"
@@ -49,7 +51,8 @@ class ConnectivityStateWatcherInterface
virtual ~ConnectivityStateWatcherInterface() = default;
// Notifies the watcher that the state has changed to new_state.
- virtual void Notify(grpc_connectivity_state new_state) = 0;
+ virtual void Notify(grpc_connectivity_state new_state,
+ const absl::Status& status) = 0;
void Orphan() override { Unref(); }
};
@@ -64,7 +67,8 @@ class AsyncConnectivityStateWatcherInterface
// Schedules a closure on the ExecCtx to invoke
// OnConnectivityStateChange() asynchronously.
- void Notify(grpc_connectivity_state new_state) override final;
+ void Notify(grpc_connectivity_state new_state,
+ const absl::Status& status) override final;
protected:
class Notifier;
@@ -76,7 +80,8 @@ class AsyncConnectivityStateWatcherInterface
: work_serializer_(std::move(work_serializer)) {}
// Invoked asynchronously when Notify() is called.
- virtual void OnConnectivityStateChange(grpc_connectivity_state new_state) = 0;
+ virtual void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) = 0;
private:
std::shared_ptr work_serializer_;
@@ -91,8 +96,9 @@ class AsyncConnectivityStateWatcherInterface
class ConnectivityStateTracker {
public:
ConnectivityStateTracker(const char* name,
- grpc_connectivity_state state = GRPC_CHANNEL_IDLE)
- : name_(name), state_(state) {}
+ grpc_connectivity_state state = GRPC_CHANNEL_IDLE,
+ const absl::Status& status = absl::Status())
+ : name_(name), state_(state), status_(status) {}
~ConnectivityStateTracker();
@@ -110,15 +116,21 @@ class ConnectivityStateTracker {
// Sets connectivity state.
// Not thread safe; access must be serialized with an external lock.
- void SetState(grpc_connectivity_state state, const char* reason);
+ void SetState(grpc_connectivity_state state, const absl::Status& status,
+ const char* reason);
// Gets the current state.
// Thread safe; no need to use an external lock.
grpc_connectivity_state state() const;
+ // Get the current status.
+ // Not thread safe; access must be serialized with an external lock.
+ absl::Status status() const { return status_; }
+
private:
const char* name_;
Atomic state_;
+ absl::Status status_;
// TODO(roth): Once we can use C++-14 heterogeneous lookups, this can
// be a set instead of a map.
std::map(status),
+ absl::string_view(reinterpret_cast(
+ GRPC_SLICE_START_PTR(message)),
+ GRPC_SLICE_LENGTH(message)));
+}
+
bool grpc_error_has_clear_grpc_status(grpc_error* error) {
intptr_t unused;
if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &unused)) {
diff --git a/src/core/lib/transport/error_utils.h b/src/core/lib/transport/error_utils.h
index 9a46267f38a..e9b1a8f1d2f 100644
--- a/src/core/lib/transport/error_utils.h
+++ b/src/core/lib/transport/error_utils.h
@@ -21,6 +21,8 @@
#include
+#include "absl/status/status.h"
+
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/transport/http2_errors.h"
@@ -37,6 +39,10 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline,
grpc_http2_error_code* http_status,
const char** error_string);
+/// Utility Function to convert a grpc_error * \a error to an absl::Status.
+/// Does NOT consume a ref to grpc_error.
+absl::Status grpc_error_to_absl_status(grpc_error* error);
+
/// A utility function to check whether there is a clear status code that
/// doesn't need to be guessed in \a error. This means that \a error or some
/// child has GRPC_ERROR_INT_GRPC_STATUS set, or that it is GRPC_ERROR_NONE or
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index 32ac91d4bbb..108762e76ab 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -97,7 +97,8 @@ std::shared_ptr WrapCallCredentials(
std::shared_ptr GoogleDefaultCredentials() {
grpc::GrpcLibraryCodegen init; // To call grpc_init().
- return WrapChannelCredentials(grpc_google_default_credentials_create());
+ return WrapChannelCredentials(
+ grpc_google_default_credentials_create(nullptr));
}
// Builds SSL Credentials given SSL specific options
diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c
index a1611d13518..ae9e469547d 100644
--- a/src/php/ext/grpc/channel_credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -131,7 +131,7 @@ PHP_METHOD(ChannelCredentials, invalidateDefaultRootsPem) {
* @return ChannelCredentials The new default channel credentials object
*/
PHP_METHOD(ChannelCredentials, createDefault) {
- grpc_channel_credentials *creds = grpc_google_default_credentials_create();
+ grpc_channel_credentials *creds = grpc_google_default_credentials_create(NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds, NULL, false
TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py
index 25f76b8a9d9..9d1f81348cb 100644
--- a/src/python/grpcio/grpc/__init__.py
+++ b/src/python/grpcio/grpc/__init__.py
@@ -1868,6 +1868,23 @@ def alts_server_credentials():
return ServerCredentials(_cygrpc.server_credentials_alts())
+def compute_engine_channel_credentials(call_credentials):
+ """Creates a compute engine channel credential.
+
+ This credential can only be used in a GCP environment as it relies on
+ a handshaker service. For more info about ALTS, see
+ https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security
+
+ This channel credential is expected to be used as part of a composite
+ credential in conjunction with a call credentials that authenticates the
+ VM's default service account. If used with any other sort of call
+ credential, the connection may suddenly and unexpectedly begin failing RPCs.
+ """
+ return ChannelCredentials(
+ _cygrpc.channel_credentials_compute_engine(
+ call_credentials._credentials))
+
+
def channel_ready_future(channel):
"""Creates a Future that tracks when a Channel is ready.
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
index 0ff3706d134..c75579cc04f 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
@@ -380,3 +380,22 @@ def server_credentials_alts():
# Options can be destroyed as deep copy was performed.
grpc_alts_credentials_options_destroy(c_options)
return credentials
+
+
+cdef class ComputeEngineChannelCredentials(ChannelCredentials):
+ cdef grpc_channel_credentials* _c_creds
+ cdef grpc_call_credentials* _call_creds
+
+ def __cinit__(self, CallCredentials call_creds):
+ self._c_creds = NULL
+ self._call_creds = call_creds.c()
+ if self._call_creds == NULL:
+ raise ValueError("Call credentials may not be NULL.")
+
+ cdef grpc_channel_credentials *c(self) except *:
+ self._c_creds = grpc_google_default_credentials_create(self._call_creds)
+ return self._c_creds
+
+
+def channel_credentials_compute_engine(call_creds):
+ return ComputeEngineChannelCredentials(call_creds)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index 98a71f92699..a7131355a07 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -504,7 +504,7 @@ cdef extern from "grpc/grpc_security.h":
void grpc_set_ssl_roots_override_callback(
grpc_ssl_roots_override_callback cb) nogil
- grpc_channel_credentials *grpc_google_default_credentials_create() nogil
+ grpc_channel_credentials *grpc_google_default_credentials_create(grpc_call_credentials* call_credentials) nogil
grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
verify_peer_options *verify_options, void *reserved) nogil
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 5b9dc43d30d..cb217c93534 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -476,6 +476,7 @@ CORE_SOURCE_FILES = [
'src/core/tsi/transport_security_grpc.cc',
'third_party/abseil-cpp/absl/base/dynamic_annotations.cc',
'third_party/abseil-cpp/absl/base/internal/cycleclock.cc',
+ 'third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc',
'third_party/abseil-cpp/absl/base/internal/raw_logging.cc',
'third_party/abseil-cpp/absl/base/internal/spinlock.cc',
'third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc',
@@ -484,9 +485,18 @@ CORE_SOURCE_FILES = [
'third_party/abseil-cpp/absl/base/internal/throw_delegate.cc',
'third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc',
'third_party/abseil-cpp/absl/base/log_severity.cc',
+ 'third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc',
+ 'third_party/abseil-cpp/absl/debugging/internal/demangle.cc',
+ 'third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc',
+ 'third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc',
+ 'third_party/abseil-cpp/absl/debugging/stacktrace.cc',
+ 'third_party/abseil-cpp/absl/debugging/symbolize.cc',
'third_party/abseil-cpp/absl/numeric/int128.cc',
+ 'third_party/abseil-cpp/absl/status/status.cc',
+ 'third_party/abseil-cpp/absl/status/status_payload_printer.cc',
'third_party/abseil-cpp/absl/strings/ascii.cc',
'third_party/abseil-cpp/absl/strings/charconv.cc',
+ 'third_party/abseil-cpp/absl/strings/cord.cc',
'third_party/abseil-cpp/absl/strings/escaping.cc',
'third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc',
'third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc',
diff --git a/src/python/grpcio_tests/tests/interop/BUILD.bazel b/src/python/grpcio_tests/tests/interop/BUILD.bazel
index 4685852162b..f38b82b030a 100644
--- a/src/python/grpcio_tests/tests/interop/BUILD.bazel
+++ b/src/python/grpcio_tests/tests/interop/BUILD.bazel
@@ -13,7 +13,7 @@ py_library(
)
py_library(
- name = "client",
+ name = "client_lib",
srcs = ["client.py"],
imports = ["../../"],
deps = [
@@ -25,6 +25,13 @@ py_library(
],
)
+py_binary(
+ name = "client",
+ srcs = ["client.py"],
+ python_version = "PY3",
+ deps = [":client_lib"],
+)
+
py_library(
name = "methods",
srcs = ["methods.py"],
diff --git a/src/python/grpcio_tests/tests/interop/client.py b/src/python/grpcio_tests/tests/interop/client.py
index 04b82c0b401..4d35f7ca32a 100644
--- a/src/python/grpcio_tests/tests/interop/client.py
+++ b/src/python/grpcio_tests/tests/interop/client.py
@@ -51,6 +51,10 @@ def parse_interop_client_args():
default=False,
type=resources.parse_bool,
help='replace platform root CAs with ca.pem')
+ parser.add_argument('--custom_credentials_type',
+ choices=["compute_engine_channel_creds"],
+ default=None,
+ help='use google default credentials')
parser.add_argument('--server_host_override',
type=str,
help='the server host to which to claim to connect')
@@ -60,6 +64,14 @@ def parse_interop_client_args():
parser.add_argument('--default_service_account',
type=str,
help='email address of the default service account')
+ parser.add_argument(
+ "--grpc_test_use_grpclb_with_child_policy",
+ type=str,
+ help=(
+ "If non-empty, set a static service config on channels created by "
+ + "grpc::CreateTestChannel, that configures the grpclb LB policy " +
+ "with a child policy being the value of this flag (e.g. round_robin "
+ + "or pick_first)."))
return parser.parse_args()
@@ -89,8 +101,27 @@ def _create_call_credentials(args):
def get_secure_channel_parameters(args):
call_credentials = _create_call_credentials(args)
- channel_opts = None
- if args.use_tls:
+ channel_opts = ()
+ if args.grpc_test_use_grpclb_with_child_policy:
+ channel_opts += ((
+ "grpc.service_config",
+ '{"loadBalancingConfig": [{"grpclb": {"childPolicy": [{"%s": {}}]}}]}'
+ % args.grpc_test_use_grpclb_with_child_policy),)
+ if args.custom_credentials_type is not None:
+ if args.custom_credentials_type == "compute_engine_channel_creds":
+ assert call_credentials is None
+ google_credentials, unused_project_id = google_auth.default(
+ scopes=[args.oauth_scope])
+ call_creds = grpc.metadata_call_credentials(
+ google_auth.transport.grpc.AuthMetadataPlugin(
+ credentials=google_credentials,
+ request=google_auth.transport.requests.Request()))
+ channel_credentials = grpc.compute_engine_channel_credentials(
+ call_creds)
+ else:
+ raise ValueError("Unknown credentials type '{}'".format(
+ args.custom_credentials_type))
+ elif args.use_tls:
if args.use_test_ca:
root_certificates = resources.test_root_certificates()
else:
@@ -102,7 +133,7 @@ def get_secure_channel_parameters(args):
channel_credentials, call_credentials)
if args.server_host_override:
- channel_opts = ((
+ channel_opts += ((
'grpc.ssl_target_name_override',
args.server_host_override,
),)
@@ -115,7 +146,7 @@ def get_secure_channel_parameters(args):
def _create_channel(args):
target = '{}:{}'.format(args.server_host, args.server_port)
- if args.use_tls or args.use_alts:
+ if args.use_tls or args.use_alts or args.custom_credentials_type is not None:
channel_credentials, options = get_secure_channel_parameters(args)
return grpc.secure_channel(target, channel_credentials, options)
else:
diff --git a/src/python/grpcio_tests/tests_aio/interop/BUILD.bazel b/src/python/grpcio_tests/tests_aio/interop/BUILD.bazel
index f67ad35cca7..4b908ecd47f 100644
--- a/src/python/grpcio_tests/tests_aio/interop/BUILD.bazel
+++ b/src/python/grpcio_tests/tests_aio/interop/BUILD.bazel
@@ -70,7 +70,7 @@ py_binary(
deps = [
":methods",
"//src/python/grpcio/grpc:grpcio",
- "//src/python/grpcio_tests/tests/interop:client",
+ "//src/python/grpcio_tests/tests/interop:client_lib",
"//src/python/grpcio_tests/tests/interop:resources",
],
)
diff --git a/src/python/grpcio_tests/tests_aio/interop/client.py b/src/python/grpcio_tests/tests_aio/interop/client.py
index 7731f3bd6eb..a4c5e12ceda 100644
--- a/src/python/grpcio_tests/tests_aio/interop/client.py
+++ b/src/python/grpcio_tests/tests_aio/interop/client.py
@@ -30,7 +30,7 @@ _LOGGER.setLevel(logging.DEBUG)
def _create_channel(args):
target = f'{args.server_host}:{args.server_port}'
- if args.use_tls or args.use_alts:
+ if args.use_tls or args.use_alts or args.custom_credentials_type is not None:
channel_credentials, options = interop_client_lib.get_secure_channel_parameters(
args)
return aio.secure_channel(target, channel_credentials, options)
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 37b864d5be4..ef9ee0fe6a7 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -120,12 +120,12 @@ grpc_auth_context_set_peer_identity_property_name_type grpc_auth_context_set_pee
grpc_ssl_session_cache_create_lru_type grpc_ssl_session_cache_create_lru_import;
grpc_ssl_session_cache_destroy_type grpc_ssl_session_cache_destroy_import;
grpc_ssl_session_cache_create_channel_arg_type grpc_ssl_session_cache_create_channel_arg_import;
+grpc_call_credentials_release_type grpc_call_credentials_release_import;
grpc_channel_credentials_release_type grpc_channel_credentials_release_import;
grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import;
grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import;
grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import;
grpc_ssl_credentials_create_ex_type grpc_ssl_credentials_create_ex_import;
-grpc_call_credentials_release_type grpc_call_credentials_release_import;
grpc_composite_channel_credentials_create_type grpc_composite_channel_credentials_create_import;
grpc_composite_call_credentials_create_type grpc_composite_call_credentials_create_import;
grpc_google_compute_engine_credentials_create_type grpc_google_compute_engine_credentials_create_import;
@@ -394,12 +394,12 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_ssl_session_cache_create_lru_import = (grpc_ssl_session_cache_create_lru_type) GetProcAddress(library, "grpc_ssl_session_cache_create_lru");
grpc_ssl_session_cache_destroy_import = (grpc_ssl_session_cache_destroy_type) GetProcAddress(library, "grpc_ssl_session_cache_destroy");
grpc_ssl_session_cache_create_channel_arg_import = (grpc_ssl_session_cache_create_channel_arg_type) GetProcAddress(library, "grpc_ssl_session_cache_create_channel_arg");
+ grpc_call_credentials_release_import = (grpc_call_credentials_release_type) GetProcAddress(library, "grpc_call_credentials_release");
grpc_channel_credentials_release_import = (grpc_channel_credentials_release_type) GetProcAddress(library, "grpc_channel_credentials_release");
grpc_google_default_credentials_create_import = (grpc_google_default_credentials_create_type) GetProcAddress(library, "grpc_google_default_credentials_create");
grpc_set_ssl_roots_override_callback_import = (grpc_set_ssl_roots_override_callback_type) GetProcAddress(library, "grpc_set_ssl_roots_override_callback");
grpc_ssl_credentials_create_import = (grpc_ssl_credentials_create_type) GetProcAddress(library, "grpc_ssl_credentials_create");
grpc_ssl_credentials_create_ex_import = (grpc_ssl_credentials_create_ex_type) GetProcAddress(library, "grpc_ssl_credentials_create_ex");
- grpc_call_credentials_release_import = (grpc_call_credentials_release_type) GetProcAddress(library, "grpc_call_credentials_release");
grpc_composite_channel_credentials_create_import = (grpc_composite_channel_credentials_create_type) GetProcAddress(library, "grpc_composite_channel_credentials_create");
grpc_composite_call_credentials_create_import = (grpc_composite_call_credentials_create_type) GetProcAddress(library, "grpc_composite_call_credentials_create");
grpc_google_compute_engine_credentials_create_import = (grpc_google_compute_engine_credentials_create_type) GetProcAddress(library, "grpc_google_compute_engine_credentials_create");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 260d673a668..b9bad36dd2d 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -335,10 +335,13 @@ extern grpc_ssl_session_cache_destroy_type grpc_ssl_session_cache_destroy_import
typedef grpc_arg(*grpc_ssl_session_cache_create_channel_arg_type)(grpc_ssl_session_cache* cache);
extern grpc_ssl_session_cache_create_channel_arg_type grpc_ssl_session_cache_create_channel_arg_import;
#define grpc_ssl_session_cache_create_channel_arg grpc_ssl_session_cache_create_channel_arg_import
+typedef void(*grpc_call_credentials_release_type)(grpc_call_credentials* creds);
+extern grpc_call_credentials_release_type grpc_call_credentials_release_import;
+#define grpc_call_credentials_release grpc_call_credentials_release_import
typedef void(*grpc_channel_credentials_release_type)(grpc_channel_credentials* creds);
extern grpc_channel_credentials_release_type grpc_channel_credentials_release_import;
#define grpc_channel_credentials_release grpc_channel_credentials_release_import
-typedef grpc_channel_credentials*(*grpc_google_default_credentials_create_type)(void);
+typedef grpc_channel_credentials*(*grpc_google_default_credentials_create_type)(grpc_call_credentials* call_credentials);
extern grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import;
#define grpc_google_default_credentials_create grpc_google_default_credentials_create_import
typedef void(*grpc_set_ssl_roots_override_callback_type)(grpc_ssl_roots_override_callback cb);
@@ -350,9 +353,6 @@ extern grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import;
typedef grpc_channel_credentials*(*grpc_ssl_credentials_create_ex_type)(const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, const grpc_ssl_verify_peer_options* verify_options, void* reserved);
extern grpc_ssl_credentials_create_ex_type grpc_ssl_credentials_create_ex_import;
#define grpc_ssl_credentials_create_ex grpc_ssl_credentials_create_ex_import
-typedef void(*grpc_call_credentials_release_type)(grpc_call_credentials* creds);
-extern grpc_call_credentials_release_type grpc_call_credentials_release_import;
-#define grpc_call_credentials_release grpc_call_credentials_release_import
typedef grpc_channel_credentials*(*grpc_composite_channel_credentials_create_type)(grpc_channel_credentials* channel_creds, grpc_call_credentials* call_creds, void* reserved);
extern grpc_composite_channel_credentials_create_type grpc_composite_channel_credentials_create_import;
#define grpc_composite_channel_credentials_create grpc_composite_channel_credentials_create_import
diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template b/templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template
index 79a6262beb5..fb0f2d2e5ad 100644
--- a/templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template
+++ b/templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template
@@ -41,4 +41,5 @@
# Cloning from a local path sets RepositoryUrl to a path and breaks Source Link.
# Override RepositoryUrl to a URL to fix Source Link. The value doesn't matter.
- dotnet build --configuration Debug Grpc.DotNet.sln -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git
+ dotnet build --configuration Debug --output ./output/InteropTestsWebsite testassets/InteropTestsWebsite/InteropTestsWebsite.csproj -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git
+ dotnet build --configuration Debug --output ./output/InteropTestsClient testassets/InteropTestsClient/InteropTestsClient.csproj -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git
diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc
index eb07947597c..22f6cdb7573 100644
--- a/test/core/security/credentials_test.cc
+++ b/test/core/security/credentials_test.cc
@@ -1347,16 +1347,24 @@ static void set_google_default_creds_env_var_with_file_contents(
gpr_free(creds_file_name);
}
+static bool test_gce_tenancy_checker(void) {
+ g_test_gce_tenancy_checker_called = true;
+ return g_test_is_on_gce;
+}
+
static void test_google_default_creds_auth_key(void) {
grpc_core::ExecCtx exec_ctx;
grpc_composite_channel_credentials* creds;
char* json_key = test_json_key_str();
grpc_flush_cached_google_default_credentials();
+ set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
+ g_test_gce_tenancy_checker_called = false;
+ g_test_is_on_gce = true;
set_google_default_creds_env_var_with_file_contents(
"json_key_google_default_creds", json_key);
gpr_free(json_key);
creds = reinterpret_cast(
- grpc_google_default_credentials_create());
+ grpc_google_default_credentials_create(nullptr));
auto* default_creds =
reinterpret_cast(
creds->inner_creds());
@@ -1368,6 +1376,7 @@ static void test_google_default_creds_auth_key(void) {
strcmp(jwt->key().client_id,
"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") ==
0);
+ GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
creds->Unref();
gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
}
@@ -1379,7 +1388,7 @@ static void test_google_default_creds_refresh_token(void) {
set_google_default_creds_env_var_with_file_contents(
"refresh_token_google_default_creds", test_refresh_token_str);
creds = reinterpret_cast(
- grpc_google_default_credentials_create());
+ grpc_google_default_credentials_create(nullptr));
auto* default_creds =
reinterpret_cast(
creds->inner_creds());
@@ -1411,11 +1420,6 @@ static int default_creds_metadata_server_detection_httpcli_get_success_override(
static std::string null_well_known_creds_path_getter(void) { return ""; }
-static bool test_gce_tenancy_checker(void) {
- g_test_gce_tenancy_checker_called = true;
- return g_test_is_on_gce;
-}
-
static void test_google_default_creds_gce(void) {
grpc_core::ExecCtx exec_ctx;
expected_md emd[] = {
@@ -1435,7 +1439,7 @@ static void test_google_default_creds_gce(void) {
/* Simulate a successful detection of GCE. */
grpc_composite_channel_credentials* creds =
reinterpret_cast(
- grpc_google_default_credentials_create());
+ grpc_google_default_credentials_create(nullptr));
/* Verify that the default creds actually embeds a GCE creds. */
GPR_ASSERT(creds != nullptr);
@@ -1474,7 +1478,7 @@ static void test_google_default_creds_non_gce(void) {
httpcli_post_should_not_be_called);
grpc_composite_channel_credentials* creds =
reinterpret_cast(
- grpc_google_default_credentials_create());
+ grpc_google_default_credentials_create(nullptr));
/* Verify that the default creds actually embeds a GCE creds. */
GPR_ASSERT(creds != nullptr);
GPR_ASSERT(creds->call_creds() != nullptr);
@@ -1512,16 +1516,105 @@ static void test_no_google_default_creds(void) {
default_creds_gce_detection_httpcli_get_failure_override,
httpcli_post_should_not_be_called);
/* Simulate a successful detection of GCE. */
- GPR_ASSERT(grpc_google_default_credentials_create() == nullptr);
+ GPR_ASSERT(grpc_google_default_credentials_create(nullptr) == nullptr);
/* Try a second one. GCE detection should occur again. */
g_test_gce_tenancy_checker_called = false;
- GPR_ASSERT(grpc_google_default_credentials_create() == nullptr);
+ GPR_ASSERT(grpc_google_default_credentials_create(nullptr) == nullptr);
GPR_ASSERT(g_test_gce_tenancy_checker_called == true);
/* Cleanup. */
grpc_override_well_known_credentials_path_getter(nullptr);
grpc_httpcli_set_override(nullptr, nullptr);
}
+static void test_google_default_creds_call_creds_specified(void) {
+ expected_md emd[] = {
+ {"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
+ request_metadata_state* state =
+ make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
+ nullptr, nullptr};
+ grpc_core::ExecCtx exec_ctx;
+ grpc_flush_cached_google_default_credentials();
+ grpc_call_credentials* call_creds =
+ grpc_google_compute_engine_credentials_create(nullptr);
+ set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
+ g_test_gce_tenancy_checker_called = false;
+ g_test_is_on_gce = true;
+ grpc_httpcli_set_override(
+ default_creds_metadata_server_detection_httpcli_get_success_override,
+ httpcli_post_should_not_be_called);
+ grpc_composite_channel_credentials* channel_creds =
+ reinterpret_cast(
+ grpc_google_default_credentials_create(call_creds));
+ GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
+ GPR_ASSERT(channel_creds != nullptr);
+ GPR_ASSERT(channel_creds->call_creds() != nullptr);
+ grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
+ httpcli_post_should_not_be_called);
+ run_request_metadata_test(channel_creds->mutable_call_creds(), auth_md_ctx,
+ state);
+ grpc_core::ExecCtx::Get()->Flush();
+ channel_creds->Unref();
+ grpc_httpcli_set_override(nullptr, nullptr);
+}
+
+struct fake_call_creds : public grpc_call_credentials {
+ public:
+ explicit fake_call_creds() : grpc_call_credentials("fake") {
+ grpc_slice key = grpc_slice_from_static_string("foo");
+ grpc_slice value = grpc_slice_from_static_string("oof");
+ dummy_md_ = grpc_mdelem_from_slices(key, value);
+ grpc_slice_unref(key);
+ grpc_slice_unref(value);
+ }
+
+ ~fake_call_creds() { GRPC_MDELEM_UNREF(dummy_md_); }
+
+ bool get_request_metadata(grpc_polling_entity* pollent,
+ grpc_auth_metadata_context context,
+ grpc_credentials_mdelem_array* md_array,
+ grpc_closure* on_request_metadata,
+ grpc_error** error) {
+ grpc_credentials_mdelem_array_add(md_array, dummy_md_);
+ return true;
+ }
+
+ void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array,
+ grpc_error* error) {}
+
+ private:
+ grpc_mdelem dummy_md_;
+};
+
+static void test_google_default_creds_not_default(void) {
+ expected_md emd[] = {{"foo", "oof"}};
+ request_metadata_state* state =
+ make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
+ nullptr, nullptr};
+ grpc_core::ExecCtx exec_ctx;
+ grpc_flush_cached_google_default_credentials();
+ grpc_core::RefCountedPtr call_creds =
+ grpc_core::MakeRefCounted();
+ set_gce_tenancy_checker_for_testing(test_gce_tenancy_checker);
+ g_test_gce_tenancy_checker_called = false;
+ g_test_is_on_gce = true;
+ grpc_httpcli_set_override(
+ default_creds_metadata_server_detection_httpcli_get_success_override,
+ httpcli_post_should_not_be_called);
+ grpc_composite_channel_credentials* channel_creds =
+ reinterpret_cast(
+ grpc_google_default_credentials_create(call_creds.release()));
+ GPR_ASSERT(g_test_gce_tenancy_checker_called == false);
+ GPR_ASSERT(channel_creds != nullptr);
+ GPR_ASSERT(channel_creds->call_creds() != nullptr);
+ run_request_metadata_test(channel_creds->mutable_call_creds(), auth_md_ctx,
+ state);
+ grpc_core::ExecCtx::Get()->Flush();
+ channel_creds->Unref();
+ grpc_httpcli_set_override(nullptr, nullptr);
+}
+
typedef enum {
PLUGIN_INITIAL_STATE,
PLUGIN_GET_METADATA_CALLED_STATE,
@@ -1825,6 +1918,8 @@ int main(int argc, char** argv) {
test_google_default_creds_gce();
test_google_default_creds_non_gce();
test_no_google_default_creds();
+ test_google_default_creds_call_creds_specified();
+ test_google_default_creds_not_default();
test_metadata_plugin_success();
test_metadata_plugin_failure();
test_get_well_known_google_credentials_file_path();
diff --git a/test/core/surface/lame_client_test.cc b/test/core/surface/lame_client_test.cc
index 812b1455094..c63335445d7 100644
--- a/test/core/surface/lame_client_test.cc
+++ b/test/core/surface/lame_client_test.cc
@@ -30,7 +30,8 @@
class Watcher : public grpc_core::ConnectivityStateWatcherInterface {
public:
- void Notify(grpc_connectivity_state new_state) override {
+ void Notify(grpc_connectivity_state new_state,
+ const absl::Status& /* status */) override {
GPR_ASSERT(new_state == GRPC_CHANNEL_SHUTDOWN);
}
};
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index 1b119317969..67edc35f6b0 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -164,12 +164,12 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_ssl_session_cache_create_lru);
printf("%lx", (unsigned long) grpc_ssl_session_cache_destroy);
printf("%lx", (unsigned long) grpc_ssl_session_cache_create_channel_arg);
+ printf("%lx", (unsigned long) grpc_call_credentials_release);
printf("%lx", (unsigned long) grpc_channel_credentials_release);
printf("%lx", (unsigned long) grpc_google_default_credentials_create);
printf("%lx", (unsigned long) grpc_set_ssl_roots_override_callback);
printf("%lx", (unsigned long) grpc_ssl_credentials_create);
printf("%lx", (unsigned long) grpc_ssl_credentials_create_ex);
- printf("%lx", (unsigned long) grpc_call_credentials_release);
printf("%lx", (unsigned long) grpc_composite_channel_credentials_create);
printf("%lx", (unsigned long) grpc_composite_call_credentials_create);
printf("%lx", (unsigned long) grpc_google_compute_engine_credentials_create);
diff --git a/test/core/transport/chttp2/too_many_pings_test.cc b/test/core/transport/chttp2/too_many_pings_test.cc
index 708ddd1cfde..308b7216e12 100644
--- a/test/core/transport/chttp2/too_many_pings_test.cc
+++ b/test/core/transport/chttp2/too_many_pings_test.cc
@@ -65,7 +65,6 @@ grpc_status_code PerformCall(grpc_channel* channel, grpc_server* server,
cq_verifier* cqv = cq_verifier_create(cq);
grpc_op ops[6];
grpc_op* op;
- grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv;
grpc_call_details call_details;
@@ -78,7 +77,6 @@ grpc_status_code PerformCall(grpc_channel* channel, grpc_server* server,
grpc_slice_from_static_string("/foo"), nullptr,
deadline, nullptr);
GPR_ASSERT(c);
- grpc_metadata_array_init(&initial_metadata_recv);
grpc_metadata_array_init(&trailing_metadata_recv);
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
@@ -111,7 +109,6 @@ grpc_status_code PerformCall(grpc_channel* channel, grpc_server* server,
cq_verify(cqv);
// cleanup
grpc_slice_unref(details);
- grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
diff --git a/test/core/transport/connectivity_state_test.cc b/test/core/transport/connectivity_state_test.cc
index 23bd100e686..e0bd8d02198 100644
--- a/test/core/transport/connectivity_state_test.cc
+++ b/test/core/transport/connectivity_state_test.cc
@@ -42,116 +42,164 @@ TEST(ConnectivityStateName, Basic) {
class Watcher : public ConnectivityStateWatcherInterface {
public:
- Watcher(int* count, grpc_connectivity_state* output,
+ Watcher(int* count, grpc_connectivity_state* output, absl::Status* status,
bool* destroyed = nullptr)
- : count_(count), output_(output), destroyed_(destroyed) {}
+ : count_(count),
+ output_(output),
+ status_(status),
+ destroyed_(destroyed) {}
~Watcher() {
if (destroyed_ != nullptr) *destroyed_ = true;
}
- void Notify(grpc_connectivity_state new_state) override {
+ void Notify(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
++*count_;
*output_ = new_state;
+ *status_ = status;
}
private:
int* count_;
grpc_connectivity_state* output_;
+ absl::Status* status_;
bool* destroyed_;
};
TEST(StateTracker, SetAndGetState) {
- ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING);
+ ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING,
+ absl::Status());
EXPECT_EQ(tracker.state(), GRPC_CHANNEL_CONNECTING);
- tracker.SetState(GRPC_CHANNEL_READY, "whee");
+ EXPECT_TRUE(tracker.status().ok());
+ tracker.SetState(GRPC_CHANNEL_READY, absl::Status(), "whee");
EXPECT_EQ(tracker.state(), GRPC_CHANNEL_READY);
+ EXPECT_TRUE(tracker.status().ok());
+ absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
+ "status for testing");
+ tracker.SetState(GRPC_CHANNEL_TRANSIENT_FAILURE, transient_failure_status,
+ "reason");
+ EXPECT_EQ(tracker.state(), GRPC_CHANNEL_TRANSIENT_FAILURE);
+ EXPECT_EQ(tracker.status(), transient_failure_status);
}
TEST(StateTracker, NotificationUponAddingWatcher) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
- MakeOrphanable(&count, &state));
+ MakeOrphanable(&count, &state, &status));
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING);
+ EXPECT_TRUE(status.ok());
+}
+
+TEST(StateTracker, NotificationUponAddingWatcherWithTransientFailure) {
+ int count = 0;
+ grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
+ absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
+ "status for testing");
+ ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_TRANSIENT_FAILURE,
+ transient_failure_status);
+ tracker.AddWatcher(GRPC_CHANNEL_IDLE,
+ MakeOrphanable(&count, &state, &status));
+ EXPECT_EQ(count, 1);
+ EXPECT_EQ(state, GRPC_CHANNEL_TRANSIENT_FAILURE);
+ EXPECT_EQ(status, transient_failure_status);
}
TEST(StateTracker, NotificationUponStateChange) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
- MakeOrphanable(&count, &state));
+ MakeOrphanable(&count, &state, &status));
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
- tracker.SetState(GRPC_CHANNEL_CONNECTING, "whee");
+ EXPECT_TRUE(status.ok());
+ absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
+ "status for testing");
+ tracker.SetState(GRPC_CHANNEL_TRANSIENT_FAILURE, transient_failure_status,
+ "whee");
EXPECT_EQ(count, 1);
- EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING);
+ EXPECT_EQ(state, GRPC_CHANNEL_TRANSIENT_FAILURE);
+ EXPECT_EQ(status, transient_failure_status);
}
TEST(StateTracker, SubscribeThenUnsubscribe) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
bool destroyed = false;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
ConnectivityStateWatcherInterface* watcher =
- new Watcher(&count, &state, &destroyed);
+ new Watcher(&count, &state, &status, &destroyed);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr(watcher));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
+ EXPECT_TRUE(status.ok());
// Cancel watch. This should not generate another notification.
tracker.RemoveWatcher(watcher);
EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
+ EXPECT_TRUE(status.ok());
}
TEST(StateTracker, OrphanUponShutdown) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
bool destroyed = false;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
ConnectivityStateWatcherInterface* watcher =
- new Watcher(&count, &state, &destroyed);
+ new Watcher(&count, &state, &status, &destroyed);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr(watcher));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
+ EXPECT_TRUE(status.ok());
// Set state to SHUTDOWN.
- tracker.SetState(GRPC_CHANNEL_SHUTDOWN, "shutting down");
+ tracker.SetState(GRPC_CHANNEL_SHUTDOWN, absl::Status(), "shutting down");
EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
+ EXPECT_TRUE(status.ok());
}
TEST(StateTracker, AddWhenAlreadyShutdown) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
bool destroyed = false;
- ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN);
+ ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN,
+ absl::Status());
ConnectivityStateWatcherInterface* watcher =
- new Watcher(&count, &state, &destroyed);
+ new Watcher(&count, &state, &status, &destroyed);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr(watcher));
EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
+ EXPECT_TRUE(status.ok());
}
TEST(StateTracker, NotifyShutdownAtDestruction) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
{
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
- MakeOrphanable(&count, &state));
+ MakeOrphanable(&count, &state, &status));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
@@ -165,10 +213,11 @@ TEST(StateTracker, NotifyShutdownAtDestruction) {
TEST(StateTracker, DoNotNotifyShutdownAtDestructionIfAlreadyInShutdown) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_SHUTDOWN;
+ absl::Status status;
{
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN);
tracker.AddWatcher(GRPC_CHANNEL_SHUTDOWN,
- MakeOrphanable(&count, &state));
+ MakeOrphanable(&count, &state, &status));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
diff --git a/test/core/util/test_lb_policies.cc b/test/core/util/test_lb_policies.cc
index 56978b97949..5aa5dabafa0 100644
--- a/test/core/util/test_lb_policies.cc
+++ b/test/core/util/test_lb_policies.cc
@@ -142,10 +142,10 @@ class TestPickArgsLb : public ForwardingLoadBalancingPolicy {
return parent_->channel_control_helper()->CreateSubchannel(args);
}
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
parent_->channel_control_helper()->UpdateState(
- state, absl::make_unique(std::move(picker), cb_));
+ state, status, absl::make_unique(std::move(picker), cb_));
}
void RequestReresolution() override {
@@ -252,10 +252,10 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy
return parent_->channel_control_helper()->CreateSubchannel(args);
}
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
parent_->channel_control_helper()->UpdateState(
- state, absl::make_unique(std::move(picker), cb_));
+ state, status, absl::make_unique(std::move(picker), cb_));
}
void RequestReresolution() override {
diff --git a/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh
index 31f21ce7839..20a61c07eae 100644
--- a/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh
+++ b/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh
@@ -39,4 +39,5 @@ fi
# Cloning from a local path sets RepositoryUrl to a path and breaks Source Link.
# Override RepositoryUrl to a URL to fix Source Link. The value doesn't matter.
-dotnet build --configuration Debug Grpc.DotNet.sln -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git
+dotnet build --configuration Debug --output ./output/InteropTestsWebsite testassets/InteropTestsWebsite/InteropTestsWebsite.csproj -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git
+dotnet build --configuration Debug --output ./output/InteropTestsClient testassets/InteropTestsClient/InteropTestsClient.csproj -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index eff5288b205..32e247553b0 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -190,8 +190,8 @@ class CSharpCoreCLRLanguage:
class AspNetCoreLanguage:
def __init__(self):
- self.client_cwd = '../grpc-dotnet/testassets/InteropTestsClient/bin/Debug/netcoreapp3.0'
- self.server_cwd = '../grpc-dotnet/testassets/InteropTestsWebsite/bin/Debug/netcoreapp3.0'
+ self.client_cwd = '../grpc-dotnet/output/InteropTestsClient'
+ self.server_cwd = '../grpc-dotnet/output/InteropTestsWebsite'
self.safename = str(self)
def cloud_to_prod_env(self):